1c4b8ed0d0f935dfdd4fd7bfb4473ecb8a95ac74
[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, struct dcerpc_pipe *p, struct test_spoolss_context *ctx)
79 {
80         NTSTATUS status;
81         struct spoolss_OpenPrinter op;
82
83         op.in.printername       = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p));
84         op.in.datatype          = NULL;
85         op.in.devmode_ctr.devmode= NULL;
86         op.in.access_mask       = 0;
87         op.out.handle           = &ctx->server_handle;
88
89         torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
90
91         status = dcerpc_spoolss_OpenPrinter(p, ctx, &op);
92         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
93         torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
94
95         return true;
96 }
97
98 static bool test_EnumPorts(struct torture_context *tctx,
99                            struct dcerpc_pipe *p,
100                            struct test_spoolss_context *ctx)
101 {
102         NTSTATUS status;
103         struct spoolss_EnumPorts r;
104         uint16_t levels[] = { 1, 2 };
105         int i, j;
106
107         for (i=0;i<ARRAY_SIZE(levels);i++) {
108                 int level = levels[i];
109                 DATA_BLOB blob;
110                 uint32_t needed;
111                 uint32_t count;
112                 union spoolss_PortInfo *info;
113
114                 r.in.servername = "";
115                 r.in.level = level;
116                 r.in.buffer = NULL;
117                 r.in.offered = 0;
118                 r.out.needed = &needed;
119                 r.out.count = &count;
120                 r.out.info = &info;
121
122                 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
123
124                 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
125                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
126                 if (W_ERROR_IS_OK(r.out.result)) {
127                         /* TODO: do some more checks here */
128                         continue;
129                 }
130                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
131                         "EnumPorts unexpected return code");
132
133                 blob = data_blob_talloc(ctx, NULL, needed);
134                 data_blob_clear(&blob);
135                 r.in.buffer = &blob;
136                 r.in.offered = needed;
137
138                 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
139                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
140
141                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
142
143                 torture_assert(tctx, info, "EnumPorts returned no info");
144
145                 ctx->port_count[level]  = count;
146                 ctx->ports[level]       = info;
147         }
148
149         for (i=1;i<ARRAY_SIZE(levels);i++) {
150                 int level = levels[i];
151                 int old_level = levels[i-1];
152                 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
153                         "EnumPorts invalid value");
154         }
155         /* if the array sizes are not the same we would maybe segfault in the following code */
156
157         for (i=0;i<ARRAY_SIZE(levels);i++) {
158                 int level = levels[i];
159                 for (j=0;j<ctx->port_count[level];j++) {
160                         union spoolss_PortInfo *cur = &ctx->ports[level][j];
161                         union spoolss_PortInfo *ref = &ctx->ports[2][j];
162                         switch (level) {
163                         case 1:
164                                 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
165                                 break;
166                         case 2:
167                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
168                                 break;
169                         }
170                 }
171         }
172
173         return true;
174 }
175
176 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
177                                             struct dcerpc_pipe *p,
178                                             struct test_spoolss_context *ctx)
179 {
180         NTSTATUS status;
181         struct spoolss_GetPrintProcessorDirectory r;
182         struct {
183                 uint16_t level;
184                 const char *server;
185         } levels[] = {{
186                         .level  = 1,
187                         .server = NULL
188                 },{
189                         .level  = 1,
190                         .server = ""
191                 },{
192                         .level  = 78,
193                         .server = ""
194                 },{
195                         .level  = 1,
196                         .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
197                 },{
198                         .level  = 1024,
199                         .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
200                 }
201         };
202         int i;
203         uint32_t needed;
204
205         for (i=0;i<ARRAY_SIZE(levels);i++) {
206                 int level = levels[i].level;
207                 DATA_BLOB blob;
208
209                 r.in.server             = levels[i].server;
210                 r.in.environment        = SPOOLSS_ARCHITECTURE_NT_X86;
211                 r.in.level              = level;
212                 r.in.buffer             = NULL;
213                 r.in.offered            = 0;
214                 r.out.needed            = &needed;
215
216                 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
217
218                 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
219                 torture_assert_ntstatus_ok(tctx, status,
220                         "dcerpc_spoolss_GetPrintProcessorDirectory failed");
221                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
222                         "GetPrintProcessorDirectory unexpected return code");
223
224                 blob = data_blob_talloc(ctx, NULL, needed);
225                 data_blob_clear(&blob);
226                 r.in.buffer = &blob;
227                 r.in.offered = needed;
228
229                 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
230                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
231
232                 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
233         }
234
235         return true;
236 }
237
238
239 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
240                                            struct dcerpc_pipe *p,
241                                            struct test_spoolss_context *ctx)
242 {
243         NTSTATUS status;
244         struct spoolss_GetPrinterDriverDirectory r;
245         struct {
246                 uint16_t level;
247                 const char *server;
248         } levels[] = {{
249                         .level  = 1,
250                         .server = NULL
251                 },{
252                         .level  = 1,
253                         .server = ""
254                 },{
255                         .level  = 78,
256                         .server = ""
257                 },{
258                         .level  = 1,
259                         .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
260                 },{
261                         .level  = 1024,
262                         .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
263                 }
264         };
265         int i;
266         uint32_t needed;
267
268         for (i=0;i<ARRAY_SIZE(levels);i++) {
269                 int level = levels[i].level;
270                 DATA_BLOB blob;
271
272                 r.in.server             = levels[i].server;
273                 r.in.environment        = SPOOLSS_ARCHITECTURE_NT_X86;
274                 r.in.level              = level;
275                 r.in.buffer             = NULL;
276                 r.in.offered            = 0;
277                 r.out.needed            = &needed;
278
279                 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
280
281                 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
282                 torture_assert_ntstatus_ok(tctx, status,
283                         "dcerpc_spoolss_GetPrinterDriverDirectory failed");
284                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
285                         "GetPrinterDriverDirectory unexpected return code");
286
287                 blob = data_blob_talloc(ctx, NULL, needed);
288                 data_blob_clear(&blob);
289                 r.in.buffer = &blob;
290                 r.in.offered = needed;
291
292                 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
293                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
294
295                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
296         }
297
298         return true;
299 }
300
301 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
302                                     struct dcerpc_pipe *p,
303                                     struct test_spoolss_context *ctx)
304 {
305         NTSTATUS status;
306         struct spoolss_EnumPrinterDrivers r;
307         uint16_t levels[] = { 1, 2, 3, 4, 5, 6 };
308         int i, j, a;
309         const char *architectures[] = {
310                 SPOOLSS_ARCHITECTURE_NT_X86,
311                 SPOOLSS_ARCHITECTURE_ALL
312         };
313
314         for (i=0;i<ARRAY_SIZE(levels);i++) {
315         for (a=0;a<ARRAY_SIZE(architectures);a++) {
316                 int level = levels[i];
317                 DATA_BLOB blob;
318                 uint32_t needed;
319                 uint32_t count;
320                 union spoolss_DriverInfo *info;
321
322                 /* FIXME: gd, come back and fix "" as server, and handle
323                  * priority of returned error codes in torture test and samba 3
324                  * server */
325
326                 r.in.server             = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
327                 r.in.environment        = architectures[a];
328                 r.in.level              = level;
329                 r.in.buffer             = NULL;
330                 r.in.offered            = 0;
331                 r.out.needed            = &needed;
332                 r.out.count             = &count;
333                 r.out.info              = &info;
334
335                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u (%s)\n", r.in.level, r.in.environment);
336
337                 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
338                 torture_assert_ntstatus_ok(tctx, status,
339                                            "dcerpc_spoolss_EnumPrinterDrivers failed");
340                 if (W_ERROR_IS_OK(r.out.result)) {
341                         /* TODO: do some more checks here */
342                         continue;
343                 }
344                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
345                         blob = data_blob_talloc(ctx, NULL, needed);
346                         data_blob_clear(&blob);
347                         r.in.buffer = &blob;
348                         r.in.offered = needed;
349
350                         status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
351                         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
352                 }
353
354                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
355
356                 /* don't do cross-architecture comparison */
357                 if (strequal(r.in.environment, SPOOLSS_ARCHITECTURE_ALL)) {
358                         continue;
359                 }
360
361                 ctx->driver_count[level]        = count;
362                 ctx->drivers[level]             = info;
363         }
364         }
365
366         for (i=1;i<ARRAY_SIZE(levels);i++) {
367                 int level = levels[i];
368                 int old_level = levels[i-1];
369
370                 /* don't do cross-architecture comparison */
371                 if (strequal(r.in.environment, SPOOLSS_ARCHITECTURE_ALL)) {
372                         continue;
373                 }
374
375                 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
376                         "EnumPrinterDrivers invalid value");
377         }
378
379         for (i=0;i<ARRAY_SIZE(levels);i++) {
380                 int level = levels[i];
381
382                 /* don't do cross-architecture comparison */
383                 if (strequal(r.in.environment, SPOOLSS_ARCHITECTURE_ALL)) {
384                         continue;
385                 }
386
387                 for (j=0;j<ctx->driver_count[level];j++) {
388                         union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
389                         union spoolss_DriverInfo *ref = &ctx->drivers[6][j];
390                         switch (level) {
391                         case 1:
392                                 COMPARE_STRING(tctx, cur->info1, ref->info6, driver_name);
393                                 break;
394                         case 2:
395                                 COMPARE_UINT32(tctx, cur->info2, ref->info6, version);
396                                 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_name);
397                                 COMPARE_STRING(tctx, cur->info2, ref->info6, architecture);
398                                 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_path);
399                                 COMPARE_STRING(tctx, cur->info2, ref->info6, data_file);
400                                 COMPARE_STRING(tctx, cur->info2, ref->info6, config_file);
401                                 break;
402                         case 3:
403                                 COMPARE_UINT32(tctx, cur->info3, ref->info6, version);
404                                 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_name);
405                                 COMPARE_STRING(tctx, cur->info3, ref->info6, architecture);
406                                 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_path);
407                                 COMPARE_STRING(tctx, cur->info3, ref->info6, data_file);
408                                 COMPARE_STRING(tctx, cur->info3, ref->info6, config_file);
409                                 COMPARE_STRING(tctx, cur->info3, ref->info6, help_file);
410                                 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info6, dependent_files);
411                                 COMPARE_STRING(tctx, cur->info3, ref->info6, monitor_name);
412                                 COMPARE_STRING(tctx, cur->info3, ref->info6, default_datatype);
413                                 break;
414                         case 4:
415                                 COMPARE_UINT32(tctx, cur->info4, ref->info6, version);
416                                 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_name);
417                                 COMPARE_STRING(tctx, cur->info4, ref->info6, architecture);
418                                 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_path);
419                                 COMPARE_STRING(tctx, cur->info4, ref->info6, data_file);
420                                 COMPARE_STRING(tctx, cur->info4, ref->info6, config_file);
421                                 COMPARE_STRING(tctx, cur->info4, ref->info6, help_file);
422                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, dependent_files);
423                                 COMPARE_STRING(tctx, cur->info4, ref->info6, monitor_name);
424                                 COMPARE_STRING(tctx, cur->info4, ref->info6, default_datatype);
425                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, previous_names);
426                                 break;
427                         case 5:
428                                 COMPARE_UINT32(tctx, cur->info5, ref->info6, version);
429                                 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_name);
430                                 COMPARE_STRING(tctx, cur->info5, ref->info6, architecture);
431                                 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_path);
432                                 COMPARE_STRING(tctx, cur->info5, ref->info6, data_file);
433                                 COMPARE_STRING(tctx, cur->info5, ref->info6, config_file);
434                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_attributes);*/
435                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, config_version);*/
436                                 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_version); */
437                                 break;
438                         case 6:
439                                 /* level 6 is our reference, and it makes no sense to compare it to itself */
440                                 break;
441                         }
442                 }
443         }
444
445         return true;
446 }
447
448 static bool test_EnumMonitors(struct torture_context *tctx,
449                               struct dcerpc_pipe *p,
450                               struct test_spoolss_context *ctx)
451 {
452         NTSTATUS status;
453         struct spoolss_EnumMonitors r;
454         uint16_t levels[] = { 1, 2 };
455         int i, j;
456
457         for (i=0;i<ARRAY_SIZE(levels);i++) {
458                 int level = levels[i];
459                 DATA_BLOB blob;
460                 uint32_t needed;
461                 uint32_t count;
462                 union spoolss_MonitorInfo *info;
463
464                 r.in.servername = "";
465                 r.in.level = level;
466                 r.in.buffer = NULL;
467                 r.in.offered = 0;
468                 r.out.needed = &needed;
469                 r.out.count = &count;
470                 r.out.info = &info;
471
472                 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
473
474                 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
475                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
476                 if (W_ERROR_IS_OK(r.out.result)) {
477                         /* TODO: do some more checks here */
478                         continue;
479                 }
480                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
481                         "EnumMonitors failed");
482
483                 blob = data_blob_talloc(ctx, NULL, needed);
484                 data_blob_clear(&blob);
485                 r.in.buffer = &blob;
486                 r.in.offered = needed;
487
488                 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
489                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
490
491                 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
492
493                 ctx->monitor_count[level]       = count;
494                 ctx->monitors[level]            = info;
495         }
496
497         for (i=1;i<ARRAY_SIZE(levels);i++) {
498                 int level = levels[i];
499                 int old_level = levels[i-1];
500                 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
501                                          "EnumMonitors invalid value");
502         }
503
504         for (i=0;i<ARRAY_SIZE(levels);i++) {
505                 int level = levels[i];
506                 for (j=0;j<ctx->monitor_count[level];j++) {
507                         union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
508                         union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
509                         switch (level) {
510                         case 1:
511                                 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
512                                 break;
513                         case 2:
514                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
515                                 break;
516                         }
517                 }
518         }
519
520         return true;
521 }
522
523 static bool test_EnumPrintProcessors(struct torture_context *tctx,
524                                      struct dcerpc_pipe *p,
525                                      struct test_spoolss_context *ctx)
526 {
527         NTSTATUS status;
528         struct spoolss_EnumPrintProcessors r;
529         uint16_t levels[] = { 1 };
530         int i, j;
531
532         for (i=0;i<ARRAY_SIZE(levels);i++) {
533                 int level = levels[i];
534                 DATA_BLOB blob;
535                 uint32_t needed;
536                 uint32_t count;
537                 union spoolss_PrintProcessorInfo *info;
538
539                 r.in.servername = "";
540                 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
541                 r.in.level = level;
542                 r.in.buffer = NULL;
543                 r.in.offered = 0;
544                 r.out.needed = &needed;
545                 r.out.count = &count;
546                 r.out.info = &info;
547
548                 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
549
550                 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
551                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
552                 if (W_ERROR_IS_OK(r.out.result)) {
553                         /* TODO: do some more checks here */
554                         continue;
555                 }
556                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
557                         "EnumPrintProcessors unexpected return code");
558
559                 blob = data_blob_talloc(ctx, NULL, needed);
560                 data_blob_clear(&blob);
561                 r.in.buffer = &blob;
562                 r.in.offered = needed;
563
564                 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
565                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
566
567                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
568
569                 ctx->print_processor_count[level]       = count;
570                 ctx->print_processors[level]            = info;
571         }
572
573         for (i=1;i<ARRAY_SIZE(levels);i++) {
574                 int level = levels[i];
575                 int old_level = levels[i-1];
576                 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
577                         "EnumPrintProcessors failed");
578         }
579
580         for (i=0;i<ARRAY_SIZE(levels);i++) {
581                 int level = levels[i];
582                 for (j=0;j<ctx->print_processor_count[level];j++) {
583 #if 0
584                         union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
585                         union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
586 #endif
587                         switch (level) {
588                         case 1:
589                                 /* level 1 is our reference, and it makes no sense to compare it to itself */
590                                 break;
591                         }
592                 }
593         }
594
595         return true;
596 }
597
598 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
599                                         struct dcerpc_pipe *p,
600                                         struct test_spoolss_context *ctx)
601 {
602         NTSTATUS status;
603         struct spoolss_EnumPrintProcDataTypes r;
604         uint16_t levels[] = { 1 };
605         int i;
606
607         for (i=0;i<ARRAY_SIZE(levels);i++) {
608                 int level = levels[i];
609                 DATA_BLOB blob;
610                 uint32_t needed;
611                 uint32_t count;
612                 union spoolss_PrintProcDataTypesInfo *info;
613
614                 r.in.servername = "";
615                 r.in.print_processor_name = "winprint";
616                 r.in.level = level;
617                 r.in.buffer = NULL;
618                 r.in.offered = 0;
619                 r.out.needed = &needed;
620                 r.out.count = &count;
621                 r.out.info = &info;
622
623                 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
624
625                 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
626                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
627                 if (W_ERROR_IS_OK(r.out.result)) {
628                         /* TODO: do some more checks here */
629                         continue;
630                 }
631                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
632                         "EnumPrintProcDataTypes unexpected return code");
633
634                 blob = data_blob_talloc(ctx, NULL, needed);
635                 data_blob_clear(&blob);
636                 r.in.buffer = &blob;
637                 r.in.offered = needed;
638
639                 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
640                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
641
642                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
643         }
644
645         return true;
646 }
647
648
649 static bool test_EnumPrinters(struct torture_context *tctx,
650                               struct dcerpc_pipe *p,
651                               struct test_spoolss_context *ctx)
652 {
653         struct spoolss_EnumPrinters r;
654         NTSTATUS status;
655         uint16_t levels[] = { 0, 1, 2, 4, 5 };
656         int i, j;
657
658         for (i=0;i<ARRAY_SIZE(levels);i++) {
659                 int level = levels[i];
660                 DATA_BLOB blob;
661                 uint32_t needed;
662                 uint32_t count;
663                 union spoolss_PrinterInfo *info;
664
665                 r.in.flags      = PRINTER_ENUM_LOCAL;
666                 r.in.server     = "";
667                 r.in.level      = level;
668                 r.in.buffer     = NULL;
669                 r.in.offered    = 0;
670                 r.out.needed    = &needed;
671                 r.out.count     = &count;
672                 r.out.info      = &info;
673
674                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
675
676                 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
677                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
678                 if (W_ERROR_IS_OK(r.out.result)) {
679                         /* TODO: do some more checks here */
680                         continue;
681                 }
682                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
683                         "EnumPrinters unexpected return code");
684
685                 blob = data_blob_talloc(ctx, NULL, needed);
686                 data_blob_clear(&blob);
687                 r.in.buffer = &blob;
688                 r.in.offered = needed;
689
690                 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
691                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
692
693                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
694
695                 ctx->printer_count[level]       = count;
696                 ctx->printers[level]            = info;
697         }
698
699         for (i=1;i<ARRAY_SIZE(levels);i++) {
700                 int level = levels[i];
701                 int old_level = levels[i-1];
702                 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
703                                          "EnumPrinters invalid value");
704         }
705
706         for (i=0;i<ARRAY_SIZE(levels);i++) {
707                 int level = levels[i];
708                 for (j=0;j<ctx->printer_count[level];j++) {
709                         union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
710                         union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
711                         switch (level) {
712                         case 0:
713                                 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
714                                 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
715                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
716                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
717                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
718                                 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
719                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
720                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
721                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
722                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
723                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
724                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
725                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
726                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
727                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
728                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
729                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
730                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
731                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
732                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
733                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
734                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
735                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
736                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
737                                 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
738                                 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
739                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
740                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
741                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
742                                 break;
743                         case 1:
744                                 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
745                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
746                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
747                                 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
748                                 break;
749                         case 2:
750                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
751                                 break;
752                         case 4:
753                                 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
754                                 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
755                                 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
756                                 break;
757                         case 5:
758                                 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
759                                 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
760                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
761                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
762                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
763                                 break;
764                         }
765                 }
766         }
767
768         /* TODO:
769          *      - verify that the port of a printer was in the list returned by EnumPorts
770          */
771
772         return true;
773 }
774
775 static bool test_GetPrinter(struct torture_context *tctx,
776                             struct dcerpc_pipe *p,
777                      struct policy_handle *handle)
778 {
779         NTSTATUS status;
780         struct spoolss_GetPrinter r;
781         uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
782         int i;
783         uint32_t needed;
784
785         for (i=0;i<ARRAY_SIZE(levels);i++) {
786                 r.in.handle = handle;
787                 r.in.level = levels[i];
788                 r.in.buffer = NULL;
789                 r.in.offered = 0;
790                 r.out.needed = &needed;
791
792                 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
793
794                 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
795                 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
796
797                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
798                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
799                         data_blob_clear(&blob);
800                         r.in.buffer = &blob;
801                         r.in.offered = needed;
802                         status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
803                 }
804
805                 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
806
807                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
808         }
809
810         return true;
811 }
812
813
814 static bool test_ClosePrinter(struct torture_context *tctx,
815                               struct dcerpc_pipe *p,
816                               struct policy_handle *handle)
817 {
818         NTSTATUS status;
819         struct spoolss_ClosePrinter r;
820
821         r.in.handle = handle;
822         r.out.handle = handle;
823
824         torture_comment(tctx, "Testing ClosePrinter\n");
825
826         status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
827         torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
828
829         return true;
830 }
831
832 static bool test_GetForm(struct torture_context *tctx,
833                          struct dcerpc_pipe *p,
834                          struct policy_handle *handle,
835                          const char *form_name,
836                          uint32_t level)
837 {
838         NTSTATUS status;
839         struct spoolss_GetForm r;
840         uint32_t needed;
841
842         r.in.handle = handle;
843         r.in.form_name = form_name;
844         r.in.level = level;
845         r.in.buffer = NULL;
846         r.in.offered = 0;
847         r.out.needed = &needed;
848
849         torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
850
851         status = dcerpc_spoolss_GetForm(p, tctx, &r);
852         torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
853
854         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
855                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
856                 data_blob_clear(&blob);
857                 r.in.buffer = &blob;
858                 r.in.offered = needed;
859                 status = dcerpc_spoolss_GetForm(p, tctx, &r);
860                 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
861
862                 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
863
864                 torture_assert(tctx, r.out.info, "No form info returned");
865         }
866
867         torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
868
869         return true;
870 }
871
872 static bool test_EnumForms(struct torture_context *tctx,
873                            struct dcerpc_pipe *p,
874                            struct policy_handle *handle, bool print_server)
875 {
876         NTSTATUS status;
877         struct spoolss_EnumForms r;
878         bool ret = true;
879         uint32_t needed;
880         uint32_t count;
881         uint32_t levels[] = { 1, 2 };
882         int i;
883
884         for (i=0; i<ARRAY_SIZE(levels); i++) {
885
886                 union spoolss_FormInfo *info;
887
888                 r.in.handle = handle;
889                 r.in.level = levels[i];
890                 r.in.buffer = NULL;
891                 r.in.offered = 0;
892                 r.out.needed = &needed;
893                 r.out.count = &count;
894                 r.out.info = &info;
895
896                 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
897
898                 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
899                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
900
901                 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
902                         break;
903                 }
904
905                 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
906                         torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
907
908                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
909                         int j;
910                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
911                         data_blob_clear(&blob);
912                         r.in.buffer = &blob;
913                         r.in.offered = needed;
914
915                         status = dcerpc_spoolss_EnumForms(p, tctx, &r);
916
917                         torture_assert(tctx, info, "No forms returned");
918
919                         for (j = 0; j < count; j++) {
920                                 if (!print_server)
921                                         ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
922                         }
923                 }
924
925                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
926
927                 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
928         }
929
930         return true;
931 }
932
933 static bool test_DeleteForm(struct torture_context *tctx,
934                             struct dcerpc_pipe *p,
935                             struct policy_handle *handle,
936                             const char *form_name)
937 {
938         NTSTATUS status;
939         struct spoolss_DeleteForm r;
940
941         r.in.handle = handle;
942         r.in.form_name = form_name;
943
944         status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
945
946         torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
947
948         torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
949
950         return true;
951 }
952
953 static bool test_AddForm(struct torture_context *tctx,
954                          struct dcerpc_pipe *p,
955                          struct policy_handle *handle, bool print_server)
956 {
957         struct spoolss_AddForm r;
958         struct spoolss_AddFormInfo1 addform;
959         const char *form_name = "testform3";
960         NTSTATUS status;
961         bool ret = true;
962
963         r.in.handle     = handle;
964         r.in.level      = 1;
965         r.in.info.info1 = &addform;
966         addform.flags           = SPOOLSS_FORM_USER;
967         addform.form_name       = form_name;
968         addform.size.width      = 50;
969         addform.size.height     = 25;
970         addform.area.left       = 5;
971         addform.area.top        = 10;
972         addform.area.right      = 45;
973         addform.area.bottom     = 15;
974
975         status = dcerpc_spoolss_AddForm(p, tctx, &r);
976
977         torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
978
979         torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
980
981         if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
982
983         {
984                 struct spoolss_SetForm sf;
985                 struct spoolss_AddFormInfo1 setform;
986
987                 sf.in.handle    = handle;
988                 sf.in.form_name = form_name;
989                 sf.in.level     = 1;
990                 sf.in.info.info1= &setform;
991                 setform.flags           = addform.flags;
992                 setform.form_name       = addform.form_name;
993                 setform.size            = addform.size;
994                 setform.area            = addform.area;
995
996                 setform.size.width      = 1234;
997
998                 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
999
1000                 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
1001
1002                 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
1003         }
1004
1005         if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1006
1007         {
1008                 struct spoolss_EnumForms e;
1009                 union spoolss_FormInfo *info;
1010                 uint32_t needed;
1011                 uint32_t count;
1012                 bool found = false;
1013
1014                 e.in.handle = handle;
1015                 e.in.level = 1;
1016                 e.in.buffer = NULL;
1017                 e.in.offered = 0;
1018                 e.out.needed = &needed;
1019                 e.out.count = &count;
1020                 e.out.info = &info;
1021
1022                 torture_comment(tctx, "Testing EnumForms level 1\n");
1023
1024                 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1025                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1026
1027                 if (print_server && W_ERROR_EQUAL(e.out.result, WERR_BADFID))
1028                         torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1029
1030                 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
1031                         int j;
1032                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1033                         data_blob_clear(&blob);
1034                         e.in.buffer = &blob;
1035                         e.in.offered = needed;
1036
1037                         status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1038
1039                         torture_assert(tctx, info, "No forms returned");
1040
1041                         for (j = 0; j < count; j++) {
1042                                 if (strequal(form_name, info[j].info1.form_name)) {
1043                                         found = true;
1044                                         break;
1045                                 }
1046                         }
1047                 }
1048                 torture_assert(tctx, found, "Newly added form not found in enum call");
1049         }
1050
1051         if (!test_DeleteForm(tctx, p, handle, form_name)) {
1052                 ret = false;
1053         }
1054
1055         return ret;
1056 }
1057
1058 static bool test_EnumPorts_old(struct torture_context *tctx,
1059                                struct dcerpc_pipe *p)
1060 {
1061         NTSTATUS status;
1062         struct spoolss_EnumPorts r;
1063         uint32_t needed;
1064         uint32_t count;
1065         union spoolss_PortInfo *info;
1066
1067         r.in.servername = talloc_asprintf(tctx, "\\\\%s",
1068                                           dcerpc_server_name(p));
1069         r.in.level = 2;
1070         r.in.buffer = NULL;
1071         r.in.offered = 0;
1072         r.out.needed = &needed;
1073         r.out.count = &count;
1074         r.out.info = &info;
1075
1076         torture_comment(tctx, "Testing EnumPorts\n");
1077
1078         status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1079
1080         torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1081
1082         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1083                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1084                 data_blob_clear(&blob);
1085                 r.in.buffer = &blob;
1086                 r.in.offered = needed;
1087
1088                 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1089                 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1090
1091                 torture_assert(tctx, info, "No ports returned");
1092         }
1093
1094         return true;
1095 }
1096
1097 static bool test_AddPort(struct torture_context *tctx,
1098                          struct dcerpc_pipe *p)
1099 {
1100         NTSTATUS status;
1101         struct spoolss_AddPort r;
1102
1103         r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
1104                                            dcerpc_server_name(p));
1105         r.in.unknown = 0;
1106         r.in.monitor_name = "foo";
1107
1108         torture_comment(tctx, "Testing AddPort\n");
1109
1110         status = dcerpc_spoolss_AddPort(p, tctx, &r);
1111
1112         torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
1113
1114         /* win2k3 returns WERR_NOT_SUPPORTED */
1115
1116 #if 0
1117
1118         if (!W_ERROR_IS_OK(r.out.result)) {
1119                 printf("AddPort failed - %s\n", win_errstr(r.out.result));
1120                 return false;
1121         }
1122
1123 #endif
1124
1125         return true;
1126 }
1127
1128 static bool test_GetJob(struct torture_context *tctx,
1129                         struct dcerpc_pipe *p,
1130                         struct policy_handle *handle, uint32_t job_id)
1131 {
1132         NTSTATUS status;
1133         struct spoolss_GetJob r;
1134         uint32_t needed;
1135         uint32_t levels[] = {1, 2 /* 3, 4 */};
1136         uint32_t i;
1137
1138         r.in.handle = handle;
1139         r.in.job_id = job_id;
1140         r.in.level = 0;
1141         r.in.buffer = NULL;
1142         r.in.offered = 0;
1143         r.out.needed = &needed;
1144
1145         torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1146
1147         status = dcerpc_spoolss_GetJob(p, tctx, &r);
1148         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
1149
1150         for (i = 0; i < ARRAY_SIZE(levels); i++) {
1151
1152                 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1153
1154                 r.in.level = levels[i];
1155                 r.in.offered = 0;
1156
1157                 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1158                 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1159
1160                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1161                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1162                         data_blob_clear(&blob);
1163                         r.in.buffer = &blob;
1164                         r.in.offered = needed;
1165
1166                         status = dcerpc_spoolss_GetJob(p, tctx, &r);
1167                         torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1168
1169                 }
1170                 torture_assert(tctx, r.out.info, "No job info returned");
1171                 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
1172         }
1173
1174         return true;
1175 }
1176
1177 static bool test_SetJob(struct torture_context *tctx,
1178                         struct dcerpc_pipe *p,
1179                         struct policy_handle *handle, uint32_t job_id,
1180                         enum spoolss_JobControl command)
1181 {
1182         NTSTATUS status;
1183         struct spoolss_SetJob r;
1184
1185         r.in.handle     = handle;
1186         r.in.job_id     = job_id;
1187         r.in.ctr        = NULL;
1188         r.in.command    = command;
1189
1190         switch (command) {
1191         case SPOOLSS_JOB_CONTROL_PAUSE:
1192                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1193                 break;
1194         case SPOOLSS_JOB_CONTROL_RESUME:
1195                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1196                 break;
1197         case SPOOLSS_JOB_CONTROL_CANCEL:
1198                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1199                 break;
1200         case SPOOLSS_JOB_CONTROL_RESTART:
1201                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1202                 break;
1203         case SPOOLSS_JOB_CONTROL_DELETE:
1204                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1205                 break;
1206         case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
1207                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1208                 break;
1209         case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
1210                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1211                 break;
1212         case SPOOLSS_JOB_CONTROL_RETAIN:
1213                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1214                 break;
1215         case SPOOLSS_JOB_CONTROL_RELEASE:
1216                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1217                 break;
1218         default:
1219                 torture_comment(tctx, "Testing SetJob\n");
1220                 break;
1221         }
1222
1223         status = dcerpc_spoolss_SetJob(p, tctx, &r);
1224         torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
1225         torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
1226
1227         return true;
1228 }
1229
1230 static bool test_AddJob(struct torture_context *tctx,
1231                         struct dcerpc_pipe *p,
1232                         struct policy_handle *handle)
1233 {
1234         NTSTATUS status;
1235         struct spoolss_AddJob r;
1236         uint32_t needed;
1237
1238         r.in.level = 0;
1239         r.in.handle = handle;
1240         r.in.offered = 0;
1241         r.out.needed = &needed;
1242         r.in.buffer = r.out.buffer = NULL;
1243
1244         torture_comment(tctx, "Testing AddJob\n");
1245
1246         status = dcerpc_spoolss_AddJob(p, tctx, &r);
1247         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
1248
1249         r.in.level = 1;
1250
1251         status = dcerpc_spoolss_AddJob(p, tctx, &r);
1252         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
1253
1254         return true;
1255 }
1256
1257
1258 static bool test_EnumJobs(struct torture_context *tctx,
1259                           struct dcerpc_pipe *p,
1260                           struct policy_handle *handle)
1261 {
1262         NTSTATUS status;
1263         struct spoolss_EnumJobs r;
1264         uint32_t needed;
1265         uint32_t count;
1266         union spoolss_JobInfo *info;
1267
1268         r.in.handle = handle;
1269         r.in.firstjob = 0;
1270         r.in.numjobs = 0xffffffff;
1271         r.in.level = 1;
1272         r.in.buffer = NULL;
1273         r.in.offered = 0;
1274         r.out.needed = &needed;
1275         r.out.count = &count;
1276         r.out.info = &info;
1277
1278         torture_comment(tctx, "Testing EnumJobs\n");
1279
1280         status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1281
1282         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1283
1284         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1285                 int j;
1286                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1287                 data_blob_clear(&blob);
1288                 r.in.buffer = &blob;
1289                 r.in.offered = needed;
1290
1291                 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1292
1293                 torture_assert(tctx, info, "No jobs returned");
1294
1295                 for (j = 0; j < count; j++) {
1296
1297                         test_GetJob(tctx, p, handle, info[j].info1.job_id);
1298
1299                         /* FIXME - gd */
1300                         if (!torture_setting_bool(tctx, "samba3", false)) {
1301                                 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
1302                                 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
1303                         }
1304                 }
1305
1306         } else {
1307                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1308         }
1309
1310         return true;
1311 }
1312
1313 static bool test_DoPrintTest(struct torture_context *tctx,
1314                              struct dcerpc_pipe *p,
1315                              struct policy_handle *handle)
1316 {
1317         bool ret = true;
1318         NTSTATUS status;
1319         struct spoolss_StartDocPrinter s;
1320         struct spoolss_DocumentInfo1 info1;
1321         struct spoolss_StartPagePrinter sp;
1322         struct spoolss_WritePrinter w;
1323         struct spoolss_EndPagePrinter ep;
1324         struct spoolss_EndDocPrinter e;
1325         int i;
1326         uint32_t job_id;
1327         uint32_t num_written;
1328
1329         torture_comment(tctx, "Testing StartDocPrinter\n");
1330
1331         s.in.handle             = handle;
1332         s.in.level              = 1;
1333         s.in.info.info1         = &info1;
1334         s.out.job_id            = &job_id;
1335         info1.document_name     = "TorturePrintJob";
1336         info1.output_file       = NULL;
1337         info1.datatype          = "RAW";
1338
1339         status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
1340         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
1341         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
1342
1343         for (i=1; i < 4; i++) {
1344                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
1345
1346                 sp.in.handle            = handle;
1347
1348                 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
1349                 torture_assert_ntstatus_ok(tctx, status,
1350                                            "dcerpc_spoolss_StartPagePrinter failed");
1351                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
1352
1353                 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
1354
1355                 w.in.handle             = handle;
1356                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
1357                 w.out.num_written       = &num_written;
1358
1359                 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
1360                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
1361                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
1362
1363                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
1364
1365                 ep.in.handle            = handle;
1366
1367                 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
1368                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
1369                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
1370         }
1371
1372         torture_comment(tctx, "Testing EndDocPrinter\n");
1373
1374         e.in.handle = handle;
1375
1376         status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
1377         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
1378         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
1379
1380         ret &= test_AddJob(tctx, p, handle);
1381         ret &= test_EnumJobs(tctx, p, handle);
1382
1383         ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
1384
1385         return ret;
1386 }
1387
1388 static bool test_PausePrinter(struct torture_context *tctx,
1389                               struct dcerpc_pipe *p,
1390                               struct policy_handle *handle)
1391 {
1392         NTSTATUS status;
1393         struct spoolss_SetPrinter r;
1394         struct spoolss_SetPrinterInfoCtr info_ctr;
1395         struct spoolss_DevmodeContainer devmode_ctr;
1396         struct sec_desc_buf secdesc_ctr;
1397
1398         info_ctr.level = 0;
1399         info_ctr.info.info0 = NULL;
1400
1401         ZERO_STRUCT(devmode_ctr);
1402         ZERO_STRUCT(secdesc_ctr);
1403
1404         r.in.handle             = handle;
1405         r.in.info_ctr           = &info_ctr;
1406         r.in.devmode_ctr        = &devmode_ctr;
1407         r.in.secdesc_ctr        = &secdesc_ctr;
1408         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
1409
1410         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1411
1412         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1413
1414         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1415
1416         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1417
1418         return true;
1419 }
1420
1421 static bool test_ResumePrinter(struct torture_context *tctx,
1422                                struct dcerpc_pipe *p,
1423                                struct policy_handle *handle)
1424 {
1425         NTSTATUS status;
1426         struct spoolss_SetPrinter r;
1427         struct spoolss_SetPrinterInfoCtr info_ctr;
1428         struct spoolss_DevmodeContainer devmode_ctr;
1429         struct sec_desc_buf secdesc_ctr;
1430
1431         info_ctr.level = 0;
1432         info_ctr.info.info0 = NULL;
1433
1434         ZERO_STRUCT(devmode_ctr);
1435         ZERO_STRUCT(secdesc_ctr);
1436
1437         r.in.handle             = handle;
1438         r.in.info_ctr           = &info_ctr;
1439         r.in.devmode_ctr        = &devmode_ctr;
1440         r.in.secdesc_ctr        = &secdesc_ctr;
1441         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
1442
1443         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
1444
1445         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1446
1447         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1448
1449         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1450
1451         return true;
1452 }
1453
1454 static bool test_GetPrinterData(struct torture_context *tctx,
1455                                 struct dcerpc_pipe *p,
1456                                 struct policy_handle *handle,
1457                                 const char *value_name)
1458 {
1459         NTSTATUS status;
1460         struct spoolss_GetPrinterData r;
1461         uint32_t needed;
1462         enum winreg_Type type;
1463         union spoolss_PrinterData data;
1464
1465         r.in.handle = handle;
1466         r.in.value_name = value_name;
1467         r.in.offered = 0;
1468         r.out.needed = &needed;
1469         r.out.type = &type;
1470         r.out.data = &data;
1471
1472         torture_comment(tctx, "Testing GetPrinterData\n");
1473
1474         status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
1475         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
1476
1477         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1478                 r.in.offered = needed;
1479
1480                 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
1481                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
1482
1483                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterData failed");
1484         }
1485
1486         return true;
1487 }
1488
1489 static bool test_GetPrinterDataEx(struct torture_context *tctx,
1490                                   struct dcerpc_pipe *p,
1491                                   struct policy_handle *handle,
1492                                   const char *key_name,
1493                                   const char *value_name)
1494 {
1495         NTSTATUS status;
1496         struct spoolss_GetPrinterDataEx r;
1497         enum winreg_Type type;
1498         uint32_t needed;
1499
1500         r.in.handle = handle;
1501         r.in.key_name = key_name;
1502         r.in.value_name = value_name;
1503         r.in.offered = 0;
1504         r.out.type = &type;
1505         r.out.needed = &needed;
1506         r.out.buffer = NULL;
1507
1508         torture_comment(tctx, "Testing GetPrinterDataEx\n");
1509
1510         status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
1511         if (!NT_STATUS_IS_OK(status)) {
1512                 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
1513                     p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1514                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
1515                 }
1516                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
1517         }
1518
1519         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1520                 r.in.offered = needed;
1521                 r.out.buffer = talloc_array(tctx, uint8_t, needed);
1522
1523                 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
1524                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
1525
1526                 torture_assert_werr_ok(tctx, r.out.result,  "GetPrinterDataEx failed");
1527         }
1528
1529         return true;
1530 }
1531
1532 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
1533                                  struct policy_handle *handle)
1534 {
1535         NTSTATUS status;
1536         struct spoolss_EnumPrinterData r;
1537
1538         ZERO_STRUCT(r);
1539         r.in.handle = handle;
1540         r.in.enum_index = 0;
1541
1542         do {
1543                 uint32_t value_size = 0;
1544                 uint32_t data_size = 0;
1545                 enum winreg_Type type = 0;
1546
1547                 r.in.value_offered = value_size;
1548                 r.out.value_needed = &value_size;
1549                 r.in.data_offered = data_size;
1550                 r.out.data_needed = &data_size;
1551
1552                 r.out.type = &type;
1553                 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
1554
1555                 torture_comment(tctx, "Testing EnumPrinterData\n");
1556
1557                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
1558
1559                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
1560
1561                 r.in.value_offered = value_size;
1562                 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
1563                 r.in.data_offered = data_size;
1564                 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
1565
1566                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
1567
1568                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
1569
1570                 test_GetPrinterData(tctx, p, handle, r.out.value_name);
1571
1572                 test_GetPrinterDataEx(tctx,
1573                         p, handle, "PrinterDriverData",
1574                         r.out.value_name);
1575
1576                 r.in.enum_index++;
1577
1578         } while (W_ERROR_IS_OK(r.out.result));
1579
1580         return true;
1581 }
1582
1583 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
1584                                    struct dcerpc_pipe *p,
1585                                    struct policy_handle *handle)
1586 {
1587         NTSTATUS status;
1588         struct spoolss_EnumPrinterDataEx r;
1589         struct spoolss_PrinterEnumValues *info;
1590         uint32_t needed;
1591         uint32_t count;
1592
1593         r.in.handle = handle;
1594         r.in.key_name = "PrinterDriverData";
1595         r.in.offered = 0;
1596         r.out.needed = &needed;
1597         r.out.count = &count;
1598         r.out.info = &info;
1599
1600         torture_comment(tctx, "Testing EnumPrinterDataEx\n");
1601
1602         status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
1603         torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
1604
1605         r.in.offered = needed;
1606
1607         status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
1608
1609         torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
1610
1611         return true;
1612 }
1613
1614
1615 static bool test_DeletePrinterData(struct torture_context *tctx,
1616                                    struct dcerpc_pipe *p,
1617                                    struct policy_handle *handle,
1618                                    const char *value_name)
1619 {
1620         NTSTATUS status;
1621         struct spoolss_DeletePrinterData r;
1622
1623         r.in.handle = handle;
1624         r.in.value_name = value_name;
1625
1626         torture_comment(tctx, "Testing DeletePrinterData\n");
1627
1628         status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
1629
1630         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
1631
1632         return true;
1633 }
1634
1635 static bool test_SetPrinterData(struct torture_context *tctx,
1636                                 struct dcerpc_pipe *p,
1637                                 struct policy_handle *handle)
1638 {
1639         NTSTATUS status;
1640         struct spoolss_SetPrinterData r;
1641         const char *value_name = "spottyfoot";
1642
1643         r.in.handle = handle;
1644         r.in.value_name = value_name;
1645         r.in.type = REG_SZ;
1646         r.in.data.string = "dog";
1647
1648         torture_comment(tctx, "Testing SetPrinterData\n");
1649
1650         status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
1651
1652         torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
1653
1654         if (!test_GetPrinterData(tctx, p, handle, value_name)) {
1655                 return false;
1656         }
1657
1658         if (!test_DeletePrinterData(tctx, p, handle, value_name)) {
1659                 return false;
1660         }
1661
1662         return true;
1663 }
1664
1665 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
1666                                        struct dcerpc_pipe *p,
1667                                        struct policy_handle *handle)
1668 {
1669         NTSTATUS status;
1670         struct dcerpc_binding *b;
1671         struct dcerpc_pipe *p2;
1672         struct spoolss_ClosePrinter cp;
1673
1674         /* only makes sense on SMB */
1675         if (p->conn->transport.transport != NCACN_NP) {
1676                 return true;
1677         }
1678
1679         torture_comment(tctx, "testing close on secondary pipe\n");
1680
1681         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
1682         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
1683
1684         status = dcerpc_secondary_connection(p, &p2, b);
1685         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
1686
1687         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
1688         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
1689
1690         cp.in.handle = handle;
1691         cp.out.handle = handle;
1692
1693         status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
1694         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
1695                         "ERROR: Allowed close on secondary connection");
1696
1697         torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
1698                                  "Unexpected fault code");
1699
1700         talloc_free(p2);
1701
1702         return true;
1703 }
1704
1705 static bool test_OpenPrinter_badname(struct torture_context *tctx,
1706                                      struct dcerpc_pipe *p, const char *name)
1707 {
1708         NTSTATUS status;
1709         struct spoolss_OpenPrinter op;
1710         struct spoolss_OpenPrinterEx opEx;
1711         struct policy_handle handle;
1712         bool ret = true;
1713
1714         op.in.printername       = name;
1715         op.in.datatype          = NULL;
1716         op.in.devmode_ctr.devmode= NULL;
1717         op.in.access_mask       = 0;
1718         op.out.handle           = &handle;
1719
1720         torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
1721
1722         status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
1723         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
1724         if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
1725                 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
1726                         name, win_errstr(op.out.result));
1727         }
1728
1729         if (W_ERROR_IS_OK(op.out.result)) {
1730                 ret &=test_ClosePrinter(tctx, p, &handle);
1731         }
1732
1733         opEx.in.printername             = name;
1734         opEx.in.datatype                = NULL;
1735         opEx.in.devmode_ctr.devmode     = NULL;
1736         opEx.in.access_mask             = 0;
1737         opEx.in.level                   = 1;
1738         opEx.in.userlevel.level1        = NULL;
1739         opEx.out.handle                 = &handle;
1740
1741         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
1742
1743         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
1744         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
1745         if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
1746                 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
1747                         name, win_errstr(opEx.out.result));
1748         }
1749
1750         if (W_ERROR_IS_OK(opEx.out.result)) {
1751                 ret &=test_ClosePrinter(tctx, p, &handle);
1752         }
1753
1754         return ret;
1755 }
1756
1757 static bool test_OpenPrinter(struct torture_context *tctx,
1758                              struct dcerpc_pipe *p,
1759                              const char *name)
1760 {
1761         NTSTATUS status;
1762         struct spoolss_OpenPrinter r;
1763         struct policy_handle handle;
1764         bool ret = true;
1765
1766         r.in.printername        = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
1767         r.in.datatype           = NULL;
1768         r.in.devmode_ctr.devmode= NULL;
1769         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
1770         r.out.handle            = &handle;
1771
1772         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
1773
1774         status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
1775
1776         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
1777
1778         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
1779
1780         if (!test_GetPrinter(tctx, p, &handle)) {
1781                 ret = false;
1782         }
1783
1784         if (!torture_setting_bool(tctx, "samba3", false)) {
1785                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
1786                         ret = false;
1787                 }
1788         }
1789
1790         if (!test_ClosePrinter(tctx, p, &handle)) {
1791                 ret = false;
1792         }
1793
1794         return ret;
1795 }
1796
1797 static bool call_OpenPrinterEx(struct torture_context *tctx,
1798                                struct dcerpc_pipe *p,
1799                                const char *name, struct policy_handle *handle)
1800 {
1801         struct spoolss_OpenPrinterEx r;
1802         struct spoolss_UserLevel1 userlevel1;
1803         NTSTATUS status;
1804
1805         if (name && name[0]) {
1806                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
1807                                                    dcerpc_server_name(p), name);
1808         } else {
1809                 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
1810                                                    dcerpc_server_name(p));
1811         }
1812
1813         r.in.datatype           = NULL;
1814         r.in.devmode_ctr.devmode= NULL;
1815         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
1816         r.in.level              = 1;
1817         r.in.userlevel.level1   = &userlevel1;
1818         r.out.handle = handle;
1819
1820         userlevel1.size = 1234;
1821         userlevel1.client = "hello";
1822         userlevel1.user = "spottyfoot!";
1823         userlevel1.build = 1;
1824         userlevel1.major = 2;
1825         userlevel1.minor = 3;
1826         userlevel1.processor = 4;
1827
1828         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
1829
1830         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
1831
1832         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
1833
1834         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
1835
1836         return true;
1837 }
1838
1839 static bool test_OpenPrinterEx(struct torture_context *tctx,
1840                                struct dcerpc_pipe *p,
1841                                const char *name)
1842 {
1843         struct policy_handle handle;
1844         bool ret = true;
1845
1846         if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
1847                 return false;
1848         }
1849
1850         if (!test_GetPrinter(tctx, p, &handle)) {
1851                 ret = false;
1852         }
1853
1854         if (!test_EnumForms(tctx, p, &handle, false)) {
1855                 ret = false;
1856         }
1857
1858         if (!test_AddForm(tctx, p, &handle, false)) {
1859                 ret = false;
1860         }
1861
1862         if (!test_EnumPrinterData(tctx, p, &handle)) {
1863                 ret = false;
1864         }
1865
1866         if (!test_EnumPrinterDataEx(tctx, p, &handle)) {
1867                 ret = false;
1868         }
1869
1870         if (!test_PausePrinter(tctx, p, &handle)) {
1871                 ret = false;
1872         }
1873
1874         if (!test_DoPrintTest(tctx, p, &handle)) {
1875                 ret = false;
1876         }
1877
1878         if (!test_ResumePrinter(tctx, p, &handle)) {
1879                 ret = false;
1880         }
1881
1882         if (!test_SetPrinterData(tctx, p, &handle)) {
1883                 ret = false;
1884         }
1885
1886         if (!torture_setting_bool(tctx, "samba3", false)) {
1887                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
1888                         ret = false;
1889                 }
1890         }
1891
1892         if (!test_ClosePrinter(tctx, p, &handle)) {
1893                 ret = false;
1894         }
1895
1896         return ret;
1897 }
1898
1899 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
1900 {
1901         struct spoolss_EnumPrinters r;
1902         NTSTATUS status;
1903         uint16_t levels[] = {1, 2, 4, 5};
1904         int i;
1905         bool ret = true;
1906
1907         for (i=0;i<ARRAY_SIZE(levels);i++) {
1908                 union spoolss_PrinterInfo *info;
1909                 int j;
1910                 uint32_t needed;
1911                 uint32_t count;
1912
1913                 r.in.flags      = PRINTER_ENUM_LOCAL;
1914                 r.in.server     = "";
1915                 r.in.level      = levels[i];
1916                 r.in.buffer     = NULL;
1917                 r.in.offered    = 0;
1918                 r.out.needed    = &needed;
1919                 r.out.count     = &count;
1920                 r.out.info      = &info;
1921
1922                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1923
1924                 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
1925                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
1926
1927                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1928                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1929                         data_blob_clear(&blob);
1930                         r.in.buffer = &blob;
1931                         r.in.offered = needed;
1932                         status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
1933                 }
1934
1935                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
1936
1937                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1938
1939                 if (!info) {
1940                         torture_comment(tctx, "No printers returned\n");
1941                         return true;
1942                 }
1943
1944                 for (j=0;j<count;j++) {
1945                         if (r.in.level == 1) {
1946                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
1947                                 char *slash, *name;
1948                                 name = unc;
1949                                 if (unc[0] == '\\' && unc[1] == '\\') {
1950                                         unc +=2;
1951                                 }
1952                                 slash = strchr(unc, '\\');
1953                                 if (slash) {
1954                                         slash++;
1955                                         name = slash;
1956                                 }
1957                                 if (!test_OpenPrinter(tctx, p, name)) {
1958                                         ret = false;
1959                                 }
1960                                 if (!test_OpenPrinterEx(tctx, p, name)) {
1961                                         ret = false;
1962                                 }
1963                         }
1964                 }
1965         }
1966
1967         return ret;
1968 }
1969
1970 #if 0
1971 static bool test_GetPrinterDriver2(struct dcerpc_pipe *p,
1972                                    struct policy_handle *handle,
1973                                    const char *driver_name)
1974 {
1975         NTSTATUS status;
1976         struct spoolss_GetPrinterDriver2 r;
1977         uint32_t needed;
1978         uint32_t server_major_version;
1979         uint32_t server_minor_version;
1980
1981         r.in.handle = handle;
1982         r.in.architecture = "W32X86";
1983         r.in.level = 1;
1984         r.in.buffer = NULL;
1985         r.in.offered = 0;
1986         r.in.client_major_version = 0;
1987         r.in.client_minor_version = 0;
1988         r.out.needed = &needed;
1989         r.out.server_major_version = &server_major_version;
1990         r.out.server_minor_version = &server_minor_version;
1991
1992         printf("Testing GetPrinterDriver2\n");
1993
1994         status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
1995         if (!NT_STATUS_IS_OK(status)) {
1996                 printf("GetPrinterDriver2 failed - %s\n", nt_errstr(status));
1997                 return false;
1998         }
1999
2000         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2001                 r.in.offered = needed;
2002                 status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
2003         }
2004
2005         if (!NT_STATUS_IS_OK(status)) {
2006                 printf("GetPrinterDriver2 failed - %s\n",
2007                        nt_errstr(status));
2008                 return false;
2009         }
2010
2011         if (!W_ERROR_IS_OK(r.out.result)) {
2012                 printf("GetPrinterDriver2 failed - %s\n",
2013                        win_errstr(r.out.result));
2014                 return false;
2015         }
2016
2017         return true;
2018 }
2019 #endif
2020
2021 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
2022                                         struct dcerpc_pipe *p)
2023 {
2024         struct spoolss_EnumPrinterDrivers r;
2025         NTSTATUS status;
2026         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
2027         int i;
2028
2029         for (i=0;i<ARRAY_SIZE(levels);i++) {
2030
2031                 uint32_t needed;
2032                 uint32_t count;
2033                 union spoolss_DriverInfo *info;
2034
2035                 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2036                 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
2037                 r.in.level = levels[i];
2038                 r.in.buffer = NULL;
2039                 r.in.offered = 0;
2040                 r.out.needed = &needed;
2041                 r.out.count = &count;
2042                 r.out.info = &info;
2043
2044                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
2045
2046                 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2047
2048                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2049
2050                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2051                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2052                         data_blob_clear(&blob);
2053                         r.in.buffer = &blob;
2054                         r.in.offered = needed;
2055                         status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2056                 }
2057
2058                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2059
2060                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
2061
2062                 if (!info) {
2063                         torture_comment(tctx, "No printer drivers returned\n");
2064                         break;
2065                 }
2066         }
2067
2068         return true;
2069 }
2070
2071 bool torture_rpc_spoolss(struct torture_context *torture)
2072 {
2073         NTSTATUS status;
2074         struct dcerpc_pipe *p;
2075         bool ret = true;
2076         struct test_spoolss_context *ctx;
2077
2078         status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
2079         if (!NT_STATUS_IS_OK(status)) {
2080                 return false;
2081         }
2082
2083         ctx = talloc_zero(torture, struct test_spoolss_context);
2084
2085         ret &= test_OpenPrinter_server(torture, p, ctx);
2086
2087         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "W3SvcInstalled");
2088         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "BeepEnabled");
2089         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "EventLog");
2090         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopup");
2091         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopupToComputer");
2092         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MajorVersion");
2093         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MinorVersion");
2094         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DefaultSpoolDirectory");
2095         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "Architecture");
2096         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DsPresent");
2097         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersion");
2098         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersionEx");
2099         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DNSMachineName");
2100         ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
2101         ret &= test_AddForm(torture, p, &ctx->server_handle, true);
2102         ret &= test_EnumPorts(torture, p, ctx);
2103         ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
2104         ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
2105         ret &= test_EnumPrinterDrivers(torture, p, ctx);
2106         ret &= test_EnumMonitors(torture, p, ctx);
2107         ret &= test_EnumPrintProcessors(torture, p, ctx);
2108         ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
2109         ret &= test_EnumPrinters(torture, p, ctx);
2110         ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
2111         ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
2112         ret &= test_OpenPrinter_badname(torture, p, "");
2113         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
2114         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
2115         ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
2116         ret &= test_OpenPrinter_badname(torture, p,
2117                                         talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
2118
2119
2120         ret &= test_AddPort(torture, p);
2121         ret &= test_EnumPorts_old(torture, p);
2122         ret &= test_EnumPrinters_old(torture, p);
2123         ret &= test_EnumPrinterDrivers_old(torture, p);
2124
2125         return ret;
2126 }