s4-smbtorture: restructure test_OpenPrinter_server in RPC-SPOOLSS a bit.
[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
816 static bool test_ClosePrinter(struct torture_context *tctx,
817                               struct dcerpc_pipe *p,
818                               struct policy_handle *handle)
819 {
820         NTSTATUS status;
821         struct spoolss_ClosePrinter r;
822
823         r.in.handle = handle;
824         r.out.handle = handle;
825
826         torture_comment(tctx, "Testing ClosePrinter\n");
827
828         status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
829         torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
830
831         return true;
832 }
833
834 static bool test_GetForm(struct torture_context *tctx,
835                          struct dcerpc_pipe *p,
836                          struct policy_handle *handle,
837                          const char *form_name,
838                          uint32_t level)
839 {
840         NTSTATUS status;
841         struct spoolss_GetForm r;
842         uint32_t needed;
843
844         r.in.handle = handle;
845         r.in.form_name = form_name;
846         r.in.level = level;
847         r.in.buffer = NULL;
848         r.in.offered = 0;
849         r.out.needed = &needed;
850
851         torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
852
853         status = dcerpc_spoolss_GetForm(p, tctx, &r);
854         torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
855
856         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
857                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
858                 data_blob_clear(&blob);
859                 r.in.buffer = &blob;
860                 r.in.offered = needed;
861                 status = dcerpc_spoolss_GetForm(p, tctx, &r);
862                 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
863
864                 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
865
866                 torture_assert(tctx, r.out.info, "No form info returned");
867         }
868
869         torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
870
871         return true;
872 }
873
874 static bool test_EnumForms(struct torture_context *tctx,
875                            struct dcerpc_pipe *p,
876                            struct policy_handle *handle, bool print_server)
877 {
878         NTSTATUS status;
879         struct spoolss_EnumForms r;
880         bool ret = true;
881         uint32_t needed;
882         uint32_t count;
883         uint32_t levels[] = { 1, 2 };
884         int i;
885
886         for (i=0; i<ARRAY_SIZE(levels); i++) {
887
888                 union spoolss_FormInfo *info;
889
890                 r.in.handle = handle;
891                 r.in.level = levels[i];
892                 r.in.buffer = NULL;
893                 r.in.offered = 0;
894                 r.out.needed = &needed;
895                 r.out.count = &count;
896                 r.out.info = &info;
897
898                 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
899
900                 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
901                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
902
903                 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
904                         break;
905                 }
906
907                 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
908                         torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
909
910                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
911                         int j;
912                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
913                         data_blob_clear(&blob);
914                         r.in.buffer = &blob;
915                         r.in.offered = needed;
916
917                         status = dcerpc_spoolss_EnumForms(p, tctx, &r);
918
919                         torture_assert(tctx, info, "No forms returned");
920
921                         for (j = 0; j < count; j++) {
922                                 if (!print_server)
923                                         ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
924                         }
925                 }
926
927                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
928
929                 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
930         }
931
932         return true;
933 }
934
935 static bool test_DeleteForm(struct torture_context *tctx,
936                             struct dcerpc_pipe *p,
937                             struct policy_handle *handle,
938                             const char *form_name)
939 {
940         NTSTATUS status;
941         struct spoolss_DeleteForm r;
942
943         r.in.handle = handle;
944         r.in.form_name = form_name;
945
946         status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
947
948         torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
949
950         torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
951
952         return true;
953 }
954
955 static bool test_AddForm(struct torture_context *tctx,
956                          struct dcerpc_pipe *p,
957                          struct policy_handle *handle, bool print_server)
958 {
959         struct spoolss_AddForm r;
960         struct spoolss_AddFormInfo1 addform;
961         const char *form_name = "testform3";
962         NTSTATUS status;
963         bool ret = true;
964
965         r.in.handle     = handle;
966         r.in.level      = 1;
967         r.in.info.info1 = &addform;
968         addform.flags           = SPOOLSS_FORM_USER;
969         addform.form_name       = form_name;
970         addform.size.width      = 50;
971         addform.size.height     = 25;
972         addform.area.left       = 5;
973         addform.area.top        = 10;
974         addform.area.right      = 45;
975         addform.area.bottom     = 15;
976
977         status = dcerpc_spoolss_AddForm(p, tctx, &r);
978
979         torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
980
981         torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
982
983         if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
984
985         {
986                 struct spoolss_SetForm sf;
987                 struct spoolss_AddFormInfo1 setform;
988
989                 sf.in.handle    = handle;
990                 sf.in.form_name = form_name;
991                 sf.in.level     = 1;
992                 sf.in.info.info1= &setform;
993                 setform.flags           = addform.flags;
994                 setform.form_name       = addform.form_name;
995                 setform.size            = addform.size;
996                 setform.area            = addform.area;
997
998                 setform.size.width      = 1234;
999
1000                 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
1001
1002                 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
1003
1004                 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
1005         }
1006
1007         if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1008
1009         {
1010                 struct spoolss_EnumForms e;
1011                 union spoolss_FormInfo *info;
1012                 uint32_t needed;
1013                 uint32_t count;
1014                 bool found = false;
1015
1016                 e.in.handle = handle;
1017                 e.in.level = 1;
1018                 e.in.buffer = NULL;
1019                 e.in.offered = 0;
1020                 e.out.needed = &needed;
1021                 e.out.count = &count;
1022                 e.out.info = &info;
1023
1024                 torture_comment(tctx, "Testing EnumForms level 1\n");
1025
1026                 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1027                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1028
1029                 if (print_server && W_ERROR_EQUAL(e.out.result, WERR_BADFID))
1030                         torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1031
1032                 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
1033                         int j;
1034                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1035                         data_blob_clear(&blob);
1036                         e.in.buffer = &blob;
1037                         e.in.offered = needed;
1038
1039                         status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1040
1041                         torture_assert(tctx, info, "No forms returned");
1042
1043                         for (j = 0; j < count; j++) {
1044                                 if (strequal(form_name, info[j].info1.form_name)) {
1045                                         found = true;
1046                                         break;
1047                                 }
1048                         }
1049                 }
1050                 torture_assert(tctx, found, "Newly added form not found in enum call");
1051         }
1052
1053         if (!test_DeleteForm(tctx, p, handle, form_name)) {
1054                 ret = false;
1055         }
1056
1057         return ret;
1058 }
1059
1060 static bool test_EnumPorts_old(struct torture_context *tctx,
1061                                struct dcerpc_pipe *p)
1062 {
1063         NTSTATUS status;
1064         struct spoolss_EnumPorts r;
1065         uint32_t needed;
1066         uint32_t count;
1067         union spoolss_PortInfo *info;
1068
1069         r.in.servername = talloc_asprintf(tctx, "\\\\%s",
1070                                           dcerpc_server_name(p));
1071         r.in.level = 2;
1072         r.in.buffer = NULL;
1073         r.in.offered = 0;
1074         r.out.needed = &needed;
1075         r.out.count = &count;
1076         r.out.info = &info;
1077
1078         torture_comment(tctx, "Testing EnumPorts\n");
1079
1080         status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1081
1082         torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1083
1084         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1085                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1086                 data_blob_clear(&blob);
1087                 r.in.buffer = &blob;
1088                 r.in.offered = needed;
1089
1090                 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1091                 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1092
1093                 torture_assert(tctx, info, "No ports returned");
1094         }
1095
1096         return true;
1097 }
1098
1099 static bool test_AddPort(struct torture_context *tctx,
1100                          struct dcerpc_pipe *p)
1101 {
1102         NTSTATUS status;
1103         struct spoolss_AddPort r;
1104
1105         r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
1106                                            dcerpc_server_name(p));
1107         r.in.unknown = 0;
1108         r.in.monitor_name = "foo";
1109
1110         torture_comment(tctx, "Testing AddPort\n");
1111
1112         status = dcerpc_spoolss_AddPort(p, tctx, &r);
1113
1114         torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
1115
1116         /* win2k3 returns WERR_NOT_SUPPORTED */
1117
1118 #if 0
1119
1120         if (!W_ERROR_IS_OK(r.out.result)) {
1121                 printf("AddPort failed - %s\n", win_errstr(r.out.result));
1122                 return false;
1123         }
1124
1125 #endif
1126
1127         return true;
1128 }
1129
1130 static bool test_GetJob(struct torture_context *tctx,
1131                         struct dcerpc_pipe *p,
1132                         struct policy_handle *handle, uint32_t job_id)
1133 {
1134         NTSTATUS status;
1135         struct spoolss_GetJob r;
1136         union spoolss_JobInfo info;
1137         uint32_t needed;
1138         uint32_t levels[] = {1, 2 /* 3, 4 */};
1139         uint32_t i;
1140
1141         r.in.handle = handle;
1142         r.in.job_id = job_id;
1143         r.in.level = 0;
1144         r.in.buffer = NULL;
1145         r.in.offered = 0;
1146         r.out.needed = &needed;
1147         r.out.info = &info;
1148
1149         torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1150
1151         status = dcerpc_spoolss_GetJob(p, tctx, &r);
1152         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
1153
1154         for (i = 0; i < ARRAY_SIZE(levels); i++) {
1155
1156                 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1157
1158                 needed = 0;
1159
1160                 r.in.level = levels[i];
1161                 r.in.offered = 0;
1162                 r.in.buffer = NULL;
1163
1164                 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1165                 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1166
1167                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1168                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1169                         data_blob_clear(&blob);
1170                         r.in.buffer = &blob;
1171                         r.in.offered = needed;
1172
1173                         status = dcerpc_spoolss_GetJob(p, tctx, &r);
1174                         torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1175
1176                 }
1177                 torture_assert(tctx, r.out.info, "No job info returned");
1178                 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
1179         }
1180
1181         return true;
1182 }
1183
1184 static bool test_SetJob(struct torture_context *tctx,
1185                         struct dcerpc_pipe *p,
1186                         struct policy_handle *handle, uint32_t job_id,
1187                         enum spoolss_JobControl command)
1188 {
1189         NTSTATUS status;
1190         struct spoolss_SetJob r;
1191
1192         r.in.handle     = handle;
1193         r.in.job_id     = job_id;
1194         r.in.ctr        = NULL;
1195         r.in.command    = command;
1196
1197         switch (command) {
1198         case SPOOLSS_JOB_CONTROL_PAUSE:
1199                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1200                 break;
1201         case SPOOLSS_JOB_CONTROL_RESUME:
1202                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1203                 break;
1204         case SPOOLSS_JOB_CONTROL_CANCEL:
1205                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1206                 break;
1207         case SPOOLSS_JOB_CONTROL_RESTART:
1208                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1209                 break;
1210         case SPOOLSS_JOB_CONTROL_DELETE:
1211                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1212                 break;
1213         case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
1214                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1215                 break;
1216         case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
1217                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1218                 break;
1219         case SPOOLSS_JOB_CONTROL_RETAIN:
1220                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1221                 break;
1222         case SPOOLSS_JOB_CONTROL_RELEASE:
1223                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1224                 break;
1225         default:
1226                 torture_comment(tctx, "Testing SetJob\n");
1227                 break;
1228         }
1229
1230         status = dcerpc_spoolss_SetJob(p, tctx, &r);
1231         torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
1232         torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
1233
1234         return true;
1235 }
1236
1237 static bool test_AddJob(struct torture_context *tctx,
1238                         struct dcerpc_pipe *p,
1239                         struct policy_handle *handle)
1240 {
1241         NTSTATUS status;
1242         struct spoolss_AddJob r;
1243         uint32_t needed;
1244
1245         r.in.level = 0;
1246         r.in.handle = handle;
1247         r.in.offered = 0;
1248         r.out.needed = &needed;
1249         r.in.buffer = r.out.buffer = NULL;
1250
1251         torture_comment(tctx, "Testing AddJob\n");
1252
1253         status = dcerpc_spoolss_AddJob(p, tctx, &r);
1254         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
1255
1256         r.in.level = 1;
1257
1258         status = dcerpc_spoolss_AddJob(p, tctx, &r);
1259         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
1260
1261         return true;
1262 }
1263
1264
1265 static bool test_EnumJobs(struct torture_context *tctx,
1266                           struct dcerpc_pipe *p,
1267                           struct policy_handle *handle)
1268 {
1269         NTSTATUS status;
1270         struct spoolss_EnumJobs r;
1271         uint32_t needed;
1272         uint32_t count;
1273         union spoolss_JobInfo *info;
1274
1275         r.in.handle = handle;
1276         r.in.firstjob = 0;
1277         r.in.numjobs = 0xffffffff;
1278         r.in.level = 1;
1279         r.in.buffer = NULL;
1280         r.in.offered = 0;
1281         r.out.needed = &needed;
1282         r.out.count = &count;
1283         r.out.info = &info;
1284
1285         torture_comment(tctx, "Testing EnumJobs\n");
1286
1287         status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1288
1289         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1290
1291         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1292                 int j;
1293                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1294                 data_blob_clear(&blob);
1295                 r.in.buffer = &blob;
1296                 r.in.offered = needed;
1297
1298                 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1299
1300                 torture_assert(tctx, info, "No jobs returned");
1301
1302                 for (j = 0; j < count; j++) {
1303
1304                         test_GetJob(tctx, p, handle, info[j].info1.job_id);
1305
1306                         /* FIXME - gd */
1307                         if (!torture_setting_bool(tctx, "samba3", false)) {
1308                                 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
1309                                 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
1310                         }
1311                 }
1312
1313         } else {
1314                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1315         }
1316
1317         return true;
1318 }
1319
1320 static bool test_DoPrintTest(struct torture_context *tctx,
1321                              struct dcerpc_pipe *p,
1322                              struct policy_handle *handle)
1323 {
1324         bool ret = true;
1325         NTSTATUS status;
1326         struct spoolss_StartDocPrinter s;
1327         struct spoolss_DocumentInfo1 info1;
1328         struct spoolss_StartPagePrinter sp;
1329         struct spoolss_WritePrinter w;
1330         struct spoolss_EndPagePrinter ep;
1331         struct spoolss_EndDocPrinter e;
1332         int i;
1333         uint32_t job_id;
1334         uint32_t num_written;
1335
1336         torture_comment(tctx, "Testing StartDocPrinter\n");
1337
1338         s.in.handle             = handle;
1339         s.in.level              = 1;
1340         s.in.info.info1         = &info1;
1341         s.out.job_id            = &job_id;
1342         info1.document_name     = "TorturePrintJob";
1343         info1.output_file       = NULL;
1344         info1.datatype          = "RAW";
1345
1346         status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
1347         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
1348         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
1349
1350         for (i=1; i < 4; i++) {
1351                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
1352
1353                 sp.in.handle            = handle;
1354
1355                 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
1356                 torture_assert_ntstatus_ok(tctx, status,
1357                                            "dcerpc_spoolss_StartPagePrinter failed");
1358                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
1359
1360                 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
1361
1362                 w.in.handle             = handle;
1363                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
1364                 w.out.num_written       = &num_written;
1365
1366                 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
1367                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
1368                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
1369
1370                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
1371
1372                 ep.in.handle            = handle;
1373
1374                 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
1375                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
1376                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
1377         }
1378
1379         torture_comment(tctx, "Testing EndDocPrinter\n");
1380
1381         e.in.handle = handle;
1382
1383         status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
1384         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
1385         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
1386
1387         ret &= test_AddJob(tctx, p, handle);
1388         ret &= test_EnumJobs(tctx, p, handle);
1389
1390         ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
1391
1392         return ret;
1393 }
1394
1395 static bool test_PausePrinter(struct torture_context *tctx,
1396                               struct dcerpc_pipe *p,
1397                               struct policy_handle *handle)
1398 {
1399         NTSTATUS status;
1400         struct spoolss_SetPrinter r;
1401         struct spoolss_SetPrinterInfoCtr info_ctr;
1402         struct spoolss_DevmodeContainer devmode_ctr;
1403         struct sec_desc_buf secdesc_ctr;
1404
1405         info_ctr.level = 0;
1406         info_ctr.info.info0 = NULL;
1407
1408         ZERO_STRUCT(devmode_ctr);
1409         ZERO_STRUCT(secdesc_ctr);
1410
1411         r.in.handle             = handle;
1412         r.in.info_ctr           = &info_ctr;
1413         r.in.devmode_ctr        = &devmode_ctr;
1414         r.in.secdesc_ctr        = &secdesc_ctr;
1415         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
1416
1417         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1418
1419         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1420
1421         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1422
1423         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1424
1425         return true;
1426 }
1427
1428 static bool test_ResumePrinter(struct torture_context *tctx,
1429                                struct dcerpc_pipe *p,
1430                                struct policy_handle *handle)
1431 {
1432         NTSTATUS status;
1433         struct spoolss_SetPrinter r;
1434         struct spoolss_SetPrinterInfoCtr info_ctr;
1435         struct spoolss_DevmodeContainer devmode_ctr;
1436         struct sec_desc_buf secdesc_ctr;
1437
1438         info_ctr.level = 0;
1439         info_ctr.info.info0 = NULL;
1440
1441         ZERO_STRUCT(devmode_ctr);
1442         ZERO_STRUCT(secdesc_ctr);
1443
1444         r.in.handle             = handle;
1445         r.in.info_ctr           = &info_ctr;
1446         r.in.devmode_ctr        = &devmode_ctr;
1447         r.in.secdesc_ctr        = &secdesc_ctr;
1448         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
1449
1450         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
1451
1452         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1453
1454         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1455
1456         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1457
1458         return true;
1459 }
1460
1461 static bool test_GetPrinterData(struct torture_context *tctx,
1462                                 struct dcerpc_pipe *p,
1463                                 struct policy_handle *handle,
1464                                 const char *value_name)
1465 {
1466         NTSTATUS status;
1467         struct spoolss_GetPrinterData r;
1468         uint32_t needed;
1469         enum winreg_Type type;
1470         union spoolss_PrinterData data;
1471
1472         r.in.handle = handle;
1473         r.in.value_name = value_name;
1474         r.in.offered = 0;
1475         r.out.needed = &needed;
1476         r.out.type = &type;
1477         r.out.data = &data;
1478
1479         torture_comment(tctx, "Testing GetPrinterData\n");
1480
1481         status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
1482         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
1483
1484         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1485                 r.in.offered = needed;
1486
1487                 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
1488                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
1489
1490                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterData failed");
1491         }
1492
1493         return true;
1494 }
1495
1496 static bool test_GetPrinterDataEx(struct torture_context *tctx,
1497                                   struct dcerpc_pipe *p,
1498                                   struct policy_handle *handle,
1499                                   const char *key_name,
1500                                   const char *value_name)
1501 {
1502         NTSTATUS status;
1503         struct spoolss_GetPrinterDataEx r;
1504         enum winreg_Type type;
1505         uint32_t needed;
1506
1507         r.in.handle = handle;
1508         r.in.key_name = key_name;
1509         r.in.value_name = value_name;
1510         r.in.offered = 0;
1511         r.out.type = &type;
1512         r.out.needed = &needed;
1513         r.out.buffer = NULL;
1514
1515         torture_comment(tctx, "Testing GetPrinterDataEx\n");
1516
1517         status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
1518         if (!NT_STATUS_IS_OK(status)) {
1519                 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
1520                     p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1521                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
1522                 }
1523                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
1524         }
1525
1526         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1527                 r.in.offered = needed;
1528                 r.out.buffer = talloc_array(tctx, uint8_t, needed);
1529
1530                 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
1531                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
1532
1533                 torture_assert_werr_ok(tctx, r.out.result,  "GetPrinterDataEx failed");
1534         }
1535
1536         return true;
1537 }
1538
1539 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
1540                                  struct policy_handle *handle)
1541 {
1542         NTSTATUS status;
1543         struct spoolss_EnumPrinterData r;
1544
1545         ZERO_STRUCT(r);
1546         r.in.handle = handle;
1547         r.in.enum_index = 0;
1548
1549         do {
1550                 uint32_t value_size = 0;
1551                 uint32_t data_size = 0;
1552                 enum winreg_Type type = 0;
1553
1554                 r.in.value_offered = value_size;
1555                 r.out.value_needed = &value_size;
1556                 r.in.data_offered = data_size;
1557                 r.out.data_needed = &data_size;
1558
1559                 r.out.type = &type;
1560                 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
1561
1562                 torture_comment(tctx, "Testing EnumPrinterData\n");
1563
1564                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
1565
1566                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
1567
1568                 r.in.value_offered = value_size;
1569                 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
1570                 r.in.data_offered = data_size;
1571                 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
1572
1573                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
1574
1575                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
1576
1577                 test_GetPrinterData(tctx, p, handle, r.out.value_name);
1578
1579                 test_GetPrinterDataEx(tctx,
1580                         p, handle, "PrinterDriverData",
1581                         r.out.value_name);
1582
1583                 r.in.enum_index++;
1584
1585         } while (W_ERROR_IS_OK(r.out.result));
1586
1587         return true;
1588 }
1589
1590 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
1591                                    struct dcerpc_pipe *p,
1592                                    struct policy_handle *handle)
1593 {
1594         NTSTATUS status;
1595         struct spoolss_EnumPrinterDataEx r;
1596         struct spoolss_PrinterEnumValues *info;
1597         uint32_t needed;
1598         uint32_t count;
1599
1600         r.in.handle = handle;
1601         r.in.key_name = "PrinterDriverData";
1602         r.in.offered = 0;
1603         r.out.needed = &needed;
1604         r.out.count = &count;
1605         r.out.info = &info;
1606
1607         torture_comment(tctx, "Testing EnumPrinterDataEx\n");
1608
1609         status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
1610         torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
1611
1612         r.in.offered = needed;
1613
1614         status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
1615
1616         torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
1617
1618         return true;
1619 }
1620
1621
1622 static bool test_DeletePrinterData(struct torture_context *tctx,
1623                                    struct dcerpc_pipe *p,
1624                                    struct policy_handle *handle,
1625                                    const char *value_name)
1626 {
1627         NTSTATUS status;
1628         struct spoolss_DeletePrinterData r;
1629
1630         r.in.handle = handle;
1631         r.in.value_name = value_name;
1632
1633         torture_comment(tctx, "Testing DeletePrinterData\n");
1634
1635         status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
1636
1637         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
1638
1639         return true;
1640 }
1641
1642 static bool test_SetPrinterData(struct torture_context *tctx,
1643                                 struct dcerpc_pipe *p,
1644                                 struct policy_handle *handle)
1645 {
1646         NTSTATUS status;
1647         struct spoolss_SetPrinterData r;
1648         const char *value_name = "spottyfoot";
1649
1650         r.in.handle = handle;
1651         r.in.value_name = value_name;
1652         r.in.type = REG_SZ;
1653         r.in.data.string = "dog";
1654
1655         torture_comment(tctx, "Testing SetPrinterData\n");
1656
1657         status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
1658
1659         torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
1660
1661         if (!test_GetPrinterData(tctx, p, handle, value_name)) {
1662                 return false;
1663         }
1664
1665         if (!test_DeletePrinterData(tctx, p, handle, value_name)) {
1666                 return false;
1667         }
1668
1669         return true;
1670 }
1671
1672 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
1673                                        struct dcerpc_pipe *p,
1674                                        struct policy_handle *handle)
1675 {
1676         NTSTATUS status;
1677         struct dcerpc_binding *b;
1678         struct dcerpc_pipe *p2;
1679         struct spoolss_ClosePrinter cp;
1680
1681         /* only makes sense on SMB */
1682         if (p->conn->transport.transport != NCACN_NP) {
1683                 return true;
1684         }
1685
1686         torture_comment(tctx, "testing close on secondary pipe\n");
1687
1688         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
1689         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
1690
1691         status = dcerpc_secondary_connection(p, &p2, b);
1692         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
1693
1694         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
1695         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
1696
1697         cp.in.handle = handle;
1698         cp.out.handle = handle;
1699
1700         status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
1701         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
1702                         "ERROR: Allowed close on secondary connection");
1703
1704         torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
1705                                  "Unexpected fault code");
1706
1707         talloc_free(p2);
1708
1709         return true;
1710 }
1711
1712 static bool test_OpenPrinter_badname(struct torture_context *tctx,
1713                                      struct dcerpc_pipe *p, const char *name)
1714 {
1715         NTSTATUS status;
1716         struct spoolss_OpenPrinter op;
1717         struct spoolss_OpenPrinterEx opEx;
1718         struct policy_handle handle;
1719         bool ret = true;
1720
1721         op.in.printername       = name;
1722         op.in.datatype          = NULL;
1723         op.in.devmode_ctr.devmode= NULL;
1724         op.in.access_mask       = 0;
1725         op.out.handle           = &handle;
1726
1727         torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
1728
1729         status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
1730         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
1731         if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
1732                 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
1733                         name, win_errstr(op.out.result));
1734         }
1735
1736         if (W_ERROR_IS_OK(op.out.result)) {
1737                 ret &=test_ClosePrinter(tctx, p, &handle);
1738         }
1739
1740         opEx.in.printername             = name;
1741         opEx.in.datatype                = NULL;
1742         opEx.in.devmode_ctr.devmode     = NULL;
1743         opEx.in.access_mask             = 0;
1744         opEx.in.level                   = 1;
1745         opEx.in.userlevel.level1        = NULL;
1746         opEx.out.handle                 = &handle;
1747
1748         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
1749
1750         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
1751         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
1752         if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
1753                 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
1754                         name, win_errstr(opEx.out.result));
1755         }
1756
1757         if (W_ERROR_IS_OK(opEx.out.result)) {
1758                 ret &=test_ClosePrinter(tctx, p, &handle);
1759         }
1760
1761         return ret;
1762 }
1763
1764 static bool test_OpenPrinter(struct torture_context *tctx,
1765                              struct dcerpc_pipe *p,
1766                              const char *name)
1767 {
1768         NTSTATUS status;
1769         struct spoolss_OpenPrinter r;
1770         struct policy_handle handle;
1771         bool ret = true;
1772
1773         r.in.printername        = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
1774         r.in.datatype           = NULL;
1775         r.in.devmode_ctr.devmode= NULL;
1776         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
1777         r.out.handle            = &handle;
1778
1779         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
1780
1781         status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
1782
1783         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
1784
1785         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
1786
1787         if (!test_GetPrinter(tctx, p, &handle)) {
1788                 ret = false;
1789         }
1790
1791         if (!torture_setting_bool(tctx, "samba3", false)) {
1792                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
1793                         ret = false;
1794                 }
1795         }
1796
1797         if (!test_ClosePrinter(tctx, p, &handle)) {
1798                 ret = false;
1799         }
1800
1801         return ret;
1802 }
1803
1804 static bool call_OpenPrinterEx(struct torture_context *tctx,
1805                                struct dcerpc_pipe *p,
1806                                const char *name, struct policy_handle *handle)
1807 {
1808         struct spoolss_OpenPrinterEx r;
1809         struct spoolss_UserLevel1 userlevel1;
1810         NTSTATUS status;
1811
1812         if (name && name[0]) {
1813                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
1814                                                    dcerpc_server_name(p), name);
1815         } else {
1816                 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
1817                                                    dcerpc_server_name(p));
1818         }
1819
1820         r.in.datatype           = NULL;
1821         r.in.devmode_ctr.devmode= NULL;
1822         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
1823         r.in.level              = 1;
1824         r.in.userlevel.level1   = &userlevel1;
1825         r.out.handle = handle;
1826
1827         userlevel1.size = 1234;
1828         userlevel1.client = "hello";
1829         userlevel1.user = "spottyfoot!";
1830         userlevel1.build = 1;
1831         userlevel1.major = 2;
1832         userlevel1.minor = 3;
1833         userlevel1.processor = 4;
1834
1835         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
1836
1837         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
1838
1839         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
1840
1841         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
1842
1843         return true;
1844 }
1845
1846 static bool test_OpenPrinterEx(struct torture_context *tctx,
1847                                struct dcerpc_pipe *p,
1848                                const char *name)
1849 {
1850         struct policy_handle handle;
1851         bool ret = true;
1852
1853         if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
1854                 return false;
1855         }
1856
1857         if (!test_GetPrinter(tctx, p, &handle)) {
1858                 ret = false;
1859         }
1860
1861         if (!test_EnumForms(tctx, p, &handle, false)) {
1862                 ret = false;
1863         }
1864
1865         if (!test_AddForm(tctx, p, &handle, false)) {
1866                 ret = false;
1867         }
1868
1869         if (!test_EnumPrinterData(tctx, p, &handle)) {
1870                 ret = false;
1871         }
1872
1873         if (!test_EnumPrinterDataEx(tctx, p, &handle)) {
1874                 ret = false;
1875         }
1876
1877         if (!test_PausePrinter(tctx, p, &handle)) {
1878                 ret = false;
1879         }
1880
1881         if (!test_DoPrintTest(tctx, p, &handle)) {
1882                 ret = false;
1883         }
1884
1885         if (!test_ResumePrinter(tctx, p, &handle)) {
1886                 ret = false;
1887         }
1888
1889         if (!test_SetPrinterData(tctx, p, &handle)) {
1890                 ret = false;
1891         }
1892
1893         if (!torture_setting_bool(tctx, "samba3", false)) {
1894                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
1895                         ret = false;
1896                 }
1897         }
1898
1899         if (!test_ClosePrinter(tctx, p, &handle)) {
1900                 ret = false;
1901         }
1902
1903         return ret;
1904 }
1905
1906 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
1907 {
1908         struct spoolss_EnumPrinters r;
1909         NTSTATUS status;
1910         uint16_t levels[] = {1, 2, 4, 5};
1911         int i;
1912         bool ret = true;
1913
1914         for (i=0;i<ARRAY_SIZE(levels);i++) {
1915                 union spoolss_PrinterInfo *info;
1916                 int j;
1917                 uint32_t needed;
1918                 uint32_t count;
1919
1920                 r.in.flags      = PRINTER_ENUM_LOCAL;
1921                 r.in.server     = "";
1922                 r.in.level      = levels[i];
1923                 r.in.buffer     = NULL;
1924                 r.in.offered    = 0;
1925                 r.out.needed    = &needed;
1926                 r.out.count     = &count;
1927                 r.out.info      = &info;
1928
1929                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1930
1931                 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
1932                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
1933
1934                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1935                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1936                         data_blob_clear(&blob);
1937                         r.in.buffer = &blob;
1938                         r.in.offered = needed;
1939                         status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
1940                 }
1941
1942                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
1943
1944                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1945
1946                 if (!info) {
1947                         torture_comment(tctx, "No printers returned\n");
1948                         return true;
1949                 }
1950
1951                 for (j=0;j<count;j++) {
1952                         if (r.in.level == 1) {
1953                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
1954                                 char *slash, *name;
1955                                 name = unc;
1956                                 if (unc[0] == '\\' && unc[1] == '\\') {
1957                                         unc +=2;
1958                                 }
1959                                 slash = strchr(unc, '\\');
1960                                 if (slash) {
1961                                         slash++;
1962                                         name = slash;
1963                                 }
1964                                 if (!test_OpenPrinter(tctx, p, name)) {
1965                                         ret = false;
1966                                 }
1967                                 if (!test_OpenPrinterEx(tctx, p, name)) {
1968                                         ret = false;
1969                                 }
1970                         }
1971                 }
1972         }
1973
1974         return ret;
1975 }
1976
1977 #if 0
1978 static bool test_GetPrinterDriver2(struct dcerpc_pipe *p,
1979                                    struct policy_handle *handle,
1980                                    const char *driver_name)
1981 {
1982         NTSTATUS status;
1983         struct spoolss_GetPrinterDriver2 r;
1984         uint32_t needed;
1985         uint32_t server_major_version;
1986         uint32_t server_minor_version;
1987
1988         r.in.handle = handle;
1989         r.in.architecture = "W32X86";
1990         r.in.level = 1;
1991         r.in.buffer = NULL;
1992         r.in.offered = 0;
1993         r.in.client_major_version = 0;
1994         r.in.client_minor_version = 0;
1995         r.out.needed = &needed;
1996         r.out.server_major_version = &server_major_version;
1997         r.out.server_minor_version = &server_minor_version;
1998
1999         printf("Testing GetPrinterDriver2\n");
2000
2001         status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
2002         if (!NT_STATUS_IS_OK(status)) {
2003                 printf("GetPrinterDriver2 failed - %s\n", nt_errstr(status));
2004                 return false;
2005         }
2006
2007         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2008                 r.in.offered = needed;
2009                 status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
2010         }
2011
2012         if (!NT_STATUS_IS_OK(status)) {
2013                 printf("GetPrinterDriver2 failed - %s\n",
2014                        nt_errstr(status));
2015                 return false;
2016         }
2017
2018         if (!W_ERROR_IS_OK(r.out.result)) {
2019                 printf("GetPrinterDriver2 failed - %s\n",
2020                        win_errstr(r.out.result));
2021                 return false;
2022         }
2023
2024         return true;
2025 }
2026 #endif
2027
2028 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
2029                                         struct dcerpc_pipe *p)
2030 {
2031         struct spoolss_EnumPrinterDrivers r;
2032         NTSTATUS status;
2033         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
2034         int i;
2035
2036         for (i=0;i<ARRAY_SIZE(levels);i++) {
2037
2038                 uint32_t needed;
2039                 uint32_t count;
2040                 union spoolss_DriverInfo *info;
2041
2042                 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2043                 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
2044                 r.in.level = levels[i];
2045                 r.in.buffer = NULL;
2046                 r.in.offered = 0;
2047                 r.out.needed = &needed;
2048                 r.out.count = &count;
2049                 r.out.info = &info;
2050
2051                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
2052
2053                 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2054
2055                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2056
2057                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2058                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2059                         data_blob_clear(&blob);
2060                         r.in.buffer = &blob;
2061                         r.in.offered = needed;
2062                         status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2063                 }
2064
2065                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2066
2067                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
2068
2069                 if (!info) {
2070                         torture_comment(tctx, "No printer drivers returned\n");
2071                         break;
2072                 }
2073         }
2074
2075         return true;
2076 }
2077
2078 bool torture_rpc_spoolss(struct torture_context *torture)
2079 {
2080         NTSTATUS status;
2081         struct dcerpc_pipe *p;
2082         bool ret = true;
2083         struct test_spoolss_context *ctx;
2084
2085         status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
2086         if (!NT_STATUS_IS_OK(status)) {
2087                 return false;
2088         }
2089
2090         ctx = talloc_zero(torture, struct test_spoolss_context);
2091
2092         ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
2093
2094         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "W3SvcInstalled");
2095         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "BeepEnabled");
2096         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "EventLog");
2097         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopup");
2098         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopupToComputer");
2099         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MajorVersion");
2100         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MinorVersion");
2101         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DefaultSpoolDirectory");
2102         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "Architecture");
2103         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DsPresent");
2104         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersion");
2105         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersionEx");
2106         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DNSMachineName");
2107         ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
2108         ret &= test_AddForm(torture, p, &ctx->server_handle, true);
2109         ret &= test_EnumPorts(torture, p, ctx);
2110         ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
2111         ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
2112         ret &= test_EnumPrinterDrivers(torture, p, ctx);
2113         ret &= test_EnumMonitors(torture, p, ctx);
2114         ret &= test_EnumPrintProcessors(torture, p, ctx);
2115         ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
2116         ret &= test_EnumPrinters(torture, p, ctx);
2117         ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
2118         ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
2119         ret &= test_OpenPrinter_badname(torture, p, "");
2120         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
2121         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
2122         ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
2123         ret &= test_OpenPrinter_badname(torture, p,
2124                                         talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
2125
2126
2127         ret &= test_AddPort(torture, p);
2128         ret &= test_EnumPorts_old(torture, p);
2129         ret &= test_EnumPrinters_old(torture, p);
2130         ret &= test_EnumPrinterDrivers_old(torture, p);
2131
2132         return ret;
2133 }