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