10e18e1531fb6f2b260d5ec7b9e79726b530e804
[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         union spoolss_JobInfo info;
1135         uint32_t needed;
1136         uint32_t levels[] = {1, 2 /* 3, 4 */};
1137         uint32_t i;
1138
1139         r.in.handle = handle;
1140         r.in.job_id = job_id;
1141         r.in.level = 0;
1142         r.in.buffer = NULL;
1143         r.in.offered = 0;
1144         r.out.needed = &needed;
1145         r.out.info = &info;
1146
1147         torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1148
1149         status = dcerpc_spoolss_GetJob(p, tctx, &r);
1150         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
1151
1152         for (i = 0; i < ARRAY_SIZE(levels); i++) {
1153
1154                 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1155
1156                 needed = 0;
1157
1158                 r.in.level = levels[i];
1159                 r.in.offered = 0;
1160                 r.in.buffer = NULL;
1161
1162                 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1163                 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1164
1165                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1166                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1167                         data_blob_clear(&blob);
1168                         r.in.buffer = &blob;
1169                         r.in.offered = needed;
1170
1171                         status = dcerpc_spoolss_GetJob(p, tctx, &r);
1172                         torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1173
1174                 }
1175                 torture_assert(tctx, r.out.info, "No job info returned");
1176                 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
1177         }
1178
1179         return true;
1180 }
1181
1182 static bool test_SetJob(struct torture_context *tctx,
1183                         struct dcerpc_pipe *p,
1184                         struct policy_handle *handle, uint32_t job_id,
1185                         enum spoolss_JobControl command)
1186 {
1187         NTSTATUS status;
1188         struct spoolss_SetJob r;
1189
1190         r.in.handle     = handle;
1191         r.in.job_id     = job_id;
1192         r.in.ctr        = NULL;
1193         r.in.command    = command;
1194
1195         switch (command) {
1196         case SPOOLSS_JOB_CONTROL_PAUSE:
1197                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1198                 break;
1199         case SPOOLSS_JOB_CONTROL_RESUME:
1200                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1201                 break;
1202         case SPOOLSS_JOB_CONTROL_CANCEL:
1203                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1204                 break;
1205         case SPOOLSS_JOB_CONTROL_RESTART:
1206                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1207                 break;
1208         case SPOOLSS_JOB_CONTROL_DELETE:
1209                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1210                 break;
1211         case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
1212                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1213                 break;
1214         case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
1215                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1216                 break;
1217         case SPOOLSS_JOB_CONTROL_RETAIN:
1218                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1219                 break;
1220         case SPOOLSS_JOB_CONTROL_RELEASE:
1221                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1222                 break;
1223         default:
1224                 torture_comment(tctx, "Testing SetJob\n");
1225                 break;
1226         }
1227
1228         status = dcerpc_spoolss_SetJob(p, tctx, &r);
1229         torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
1230         torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
1231
1232         return true;
1233 }
1234
1235 static bool test_AddJob(struct torture_context *tctx,
1236                         struct dcerpc_pipe *p,
1237                         struct policy_handle *handle)
1238 {
1239         NTSTATUS status;
1240         struct spoolss_AddJob r;
1241         uint32_t needed;
1242
1243         r.in.level = 0;
1244         r.in.handle = handle;
1245         r.in.offered = 0;
1246         r.out.needed = &needed;
1247         r.in.buffer = r.out.buffer = NULL;
1248
1249         torture_comment(tctx, "Testing AddJob\n");
1250
1251         status = dcerpc_spoolss_AddJob(p, tctx, &r);
1252         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
1253
1254         r.in.level = 1;
1255
1256         status = dcerpc_spoolss_AddJob(p, tctx, &r);
1257         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
1258
1259         return true;
1260 }
1261
1262
1263 static bool test_EnumJobs(struct torture_context *tctx,
1264                           struct dcerpc_pipe *p,
1265                           struct policy_handle *handle)
1266 {
1267         NTSTATUS status;
1268         struct spoolss_EnumJobs r;
1269         uint32_t needed;
1270         uint32_t count;
1271         union spoolss_JobInfo *info;
1272
1273         r.in.handle = handle;
1274         r.in.firstjob = 0;
1275         r.in.numjobs = 0xffffffff;
1276         r.in.level = 1;
1277         r.in.buffer = NULL;
1278         r.in.offered = 0;
1279         r.out.needed = &needed;
1280         r.out.count = &count;
1281         r.out.info = &info;
1282
1283         torture_comment(tctx, "Testing EnumJobs\n");
1284
1285         status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1286
1287         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1288
1289         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1290                 int j;
1291                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1292                 data_blob_clear(&blob);
1293                 r.in.buffer = &blob;
1294                 r.in.offered = needed;
1295
1296                 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1297
1298                 torture_assert(tctx, info, "No jobs returned");
1299
1300                 for (j = 0; j < count; j++) {
1301
1302                         test_GetJob(tctx, p, handle, info[j].info1.job_id);
1303
1304                         /* FIXME - gd */
1305                         if (!torture_setting_bool(tctx, "samba3", false)) {
1306                                 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
1307                                 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
1308                         }
1309                 }
1310
1311         } else {
1312                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1313         }
1314
1315         return true;
1316 }
1317
1318 static bool test_DoPrintTest(struct torture_context *tctx,
1319                              struct dcerpc_pipe *p,
1320                              struct policy_handle *handle)
1321 {
1322         bool ret = true;
1323         NTSTATUS status;
1324         struct spoolss_StartDocPrinter s;
1325         struct spoolss_DocumentInfo1 info1;
1326         struct spoolss_StartPagePrinter sp;
1327         struct spoolss_WritePrinter w;
1328         struct spoolss_EndPagePrinter ep;
1329         struct spoolss_EndDocPrinter e;
1330         int i;
1331         uint32_t job_id;
1332         uint32_t num_written;
1333
1334         torture_comment(tctx, "Testing StartDocPrinter\n");
1335
1336         s.in.handle             = handle;
1337         s.in.level              = 1;
1338         s.in.info.info1         = &info1;
1339         s.out.job_id            = &job_id;
1340         info1.document_name     = "TorturePrintJob";
1341         info1.output_file       = NULL;
1342         info1.datatype          = "RAW";
1343
1344         status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
1345         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
1346         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
1347
1348         for (i=1; i < 4; i++) {
1349                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
1350
1351                 sp.in.handle            = handle;
1352
1353                 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
1354                 torture_assert_ntstatus_ok(tctx, status,
1355                                            "dcerpc_spoolss_StartPagePrinter failed");
1356                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
1357
1358                 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
1359
1360                 w.in.handle             = handle;
1361                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
1362                 w.out.num_written       = &num_written;
1363
1364                 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
1365                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
1366                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
1367
1368                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
1369
1370                 ep.in.handle            = handle;
1371
1372                 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
1373                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
1374                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
1375         }
1376
1377         torture_comment(tctx, "Testing EndDocPrinter\n");
1378
1379         e.in.handle = handle;
1380
1381         status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
1382         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
1383         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
1384
1385         ret &= test_AddJob(tctx, p, handle);
1386         ret &= test_EnumJobs(tctx, p, handle);
1387
1388         ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
1389
1390         return ret;
1391 }
1392
1393 static bool test_PausePrinter(struct torture_context *tctx,
1394                               struct dcerpc_pipe *p,
1395                               struct policy_handle *handle)
1396 {
1397         NTSTATUS status;
1398         struct spoolss_SetPrinter r;
1399         struct spoolss_SetPrinterInfoCtr info_ctr;
1400         struct spoolss_DevmodeContainer devmode_ctr;
1401         struct sec_desc_buf secdesc_ctr;
1402
1403         info_ctr.level = 0;
1404         info_ctr.info.info0 = NULL;
1405
1406         ZERO_STRUCT(devmode_ctr);
1407         ZERO_STRUCT(secdesc_ctr);
1408
1409         r.in.handle             = handle;
1410         r.in.info_ctr           = &info_ctr;
1411         r.in.devmode_ctr        = &devmode_ctr;
1412         r.in.secdesc_ctr        = &secdesc_ctr;
1413         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
1414
1415         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1416
1417         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1418
1419         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1420
1421         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1422
1423         return true;
1424 }
1425
1426 static bool test_ResumePrinter(struct torture_context *tctx,
1427                                struct dcerpc_pipe *p,
1428                                struct policy_handle *handle)
1429 {
1430         NTSTATUS status;
1431         struct spoolss_SetPrinter r;
1432         struct spoolss_SetPrinterInfoCtr info_ctr;
1433         struct spoolss_DevmodeContainer devmode_ctr;
1434         struct sec_desc_buf secdesc_ctr;
1435
1436         info_ctr.level = 0;
1437         info_ctr.info.info0 = NULL;
1438
1439         ZERO_STRUCT(devmode_ctr);
1440         ZERO_STRUCT(secdesc_ctr);
1441
1442         r.in.handle             = handle;
1443         r.in.info_ctr           = &info_ctr;
1444         r.in.devmode_ctr        = &devmode_ctr;
1445         r.in.secdesc_ctr        = &secdesc_ctr;
1446         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
1447
1448         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
1449
1450         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1451
1452         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1453
1454         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1455
1456         return true;
1457 }
1458
1459 static bool test_GetPrinterData(struct torture_context *tctx,
1460                                 struct dcerpc_pipe *p,
1461                                 struct policy_handle *handle,
1462                                 const char *value_name)
1463 {
1464         NTSTATUS status;
1465         struct spoolss_GetPrinterData r;
1466         uint32_t needed;
1467         enum winreg_Type type;
1468         union spoolss_PrinterData data;
1469
1470         r.in.handle = handle;
1471         r.in.value_name = value_name;
1472         r.in.offered = 0;
1473         r.out.needed = &needed;
1474         r.out.type = &type;
1475         r.out.data = &data;
1476
1477         torture_comment(tctx, "Testing GetPrinterData\n");
1478
1479         status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
1480         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
1481
1482         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1483                 r.in.offered = needed;
1484
1485                 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
1486                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
1487
1488                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterData failed");
1489         }
1490
1491         return true;
1492 }
1493
1494 static bool test_GetPrinterDataEx(struct torture_context *tctx,
1495                                   struct dcerpc_pipe *p,
1496                                   struct policy_handle *handle,
1497                                   const char *key_name,
1498                                   const char *value_name)
1499 {
1500         NTSTATUS status;
1501         struct spoolss_GetPrinterDataEx r;
1502         enum winreg_Type type;
1503         uint32_t needed;
1504
1505         r.in.handle = handle;
1506         r.in.key_name = key_name;
1507         r.in.value_name = value_name;
1508         r.in.offered = 0;
1509         r.out.type = &type;
1510         r.out.needed = &needed;
1511         r.out.buffer = NULL;
1512
1513         torture_comment(tctx, "Testing GetPrinterDataEx\n");
1514
1515         status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
1516         if (!NT_STATUS_IS_OK(status)) {
1517                 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
1518                     p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1519                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
1520                 }
1521                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
1522         }
1523
1524         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1525                 r.in.offered = needed;
1526                 r.out.buffer = talloc_array(tctx, uint8_t, needed);
1527
1528                 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
1529                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
1530
1531                 torture_assert_werr_ok(tctx, r.out.result,  "GetPrinterDataEx failed");
1532         }
1533
1534         return true;
1535 }
1536
1537 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
1538                                  struct policy_handle *handle)
1539 {
1540         NTSTATUS status;
1541         struct spoolss_EnumPrinterData r;
1542
1543         ZERO_STRUCT(r);
1544         r.in.handle = handle;
1545         r.in.enum_index = 0;
1546
1547         do {
1548                 uint32_t value_size = 0;
1549                 uint32_t data_size = 0;
1550                 enum winreg_Type type = 0;
1551
1552                 r.in.value_offered = value_size;
1553                 r.out.value_needed = &value_size;
1554                 r.in.data_offered = data_size;
1555                 r.out.data_needed = &data_size;
1556
1557                 r.out.type = &type;
1558                 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
1559
1560                 torture_comment(tctx, "Testing EnumPrinterData\n");
1561
1562                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
1563
1564                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
1565
1566                 r.in.value_offered = value_size;
1567                 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
1568                 r.in.data_offered = data_size;
1569                 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
1570
1571                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
1572
1573                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
1574
1575                 test_GetPrinterData(tctx, p, handle, r.out.value_name);
1576
1577                 test_GetPrinterDataEx(tctx,
1578                         p, handle, "PrinterDriverData",
1579                         r.out.value_name);
1580
1581                 r.in.enum_index++;
1582
1583         } while (W_ERROR_IS_OK(r.out.result));
1584
1585         return true;
1586 }
1587
1588 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
1589                                    struct dcerpc_pipe *p,
1590                                    struct policy_handle *handle)
1591 {
1592         NTSTATUS status;
1593         struct spoolss_EnumPrinterDataEx r;
1594         struct spoolss_PrinterEnumValues *info;
1595         uint32_t needed;
1596         uint32_t count;
1597
1598         r.in.handle = handle;
1599         r.in.key_name = "PrinterDriverData";
1600         r.in.offered = 0;
1601         r.out.needed = &needed;
1602         r.out.count = &count;
1603         r.out.info = &info;
1604
1605         torture_comment(tctx, "Testing EnumPrinterDataEx\n");
1606
1607         status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
1608         torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
1609
1610         r.in.offered = needed;
1611
1612         status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
1613
1614         torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
1615
1616         return true;
1617 }
1618
1619
1620 static bool test_DeletePrinterData(struct torture_context *tctx,
1621                                    struct dcerpc_pipe *p,
1622                                    struct policy_handle *handle,
1623                                    const char *value_name)
1624 {
1625         NTSTATUS status;
1626         struct spoolss_DeletePrinterData r;
1627
1628         r.in.handle = handle;
1629         r.in.value_name = value_name;
1630
1631         torture_comment(tctx, "Testing DeletePrinterData\n");
1632
1633         status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
1634
1635         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
1636
1637         return true;
1638 }
1639
1640 static bool test_SetPrinterData(struct torture_context *tctx,
1641                                 struct dcerpc_pipe *p,
1642                                 struct policy_handle *handle)
1643 {
1644         NTSTATUS status;
1645         struct spoolss_SetPrinterData r;
1646         const char *value_name = "spottyfoot";
1647
1648         r.in.handle = handle;
1649         r.in.value_name = value_name;
1650         r.in.type = REG_SZ;
1651         r.in.data.string = "dog";
1652
1653         torture_comment(tctx, "Testing SetPrinterData\n");
1654
1655         status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
1656
1657         torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
1658
1659         if (!test_GetPrinterData(tctx, p, handle, value_name)) {
1660                 return false;
1661         }
1662
1663         if (!test_DeletePrinterData(tctx, p, handle, value_name)) {
1664                 return false;
1665         }
1666
1667         return true;
1668 }
1669
1670 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
1671                                        struct dcerpc_pipe *p,
1672                                        struct policy_handle *handle)
1673 {
1674         NTSTATUS status;
1675         struct dcerpc_binding *b;
1676         struct dcerpc_pipe *p2;
1677         struct spoolss_ClosePrinter cp;
1678
1679         /* only makes sense on SMB */
1680         if (p->conn->transport.transport != NCACN_NP) {
1681                 return true;
1682         }
1683
1684         torture_comment(tctx, "testing close on secondary pipe\n");
1685
1686         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
1687         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
1688
1689         status = dcerpc_secondary_connection(p, &p2, b);
1690         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
1691
1692         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
1693         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
1694
1695         cp.in.handle = handle;
1696         cp.out.handle = handle;
1697
1698         status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
1699         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
1700                         "ERROR: Allowed close on secondary connection");
1701
1702         torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
1703                                  "Unexpected fault code");
1704
1705         talloc_free(p2);
1706
1707         return true;
1708 }
1709
1710 static bool test_OpenPrinter_badname(struct torture_context *tctx,
1711                                      struct dcerpc_pipe *p, const char *name)
1712 {
1713         NTSTATUS status;
1714         struct spoolss_OpenPrinter op;
1715         struct spoolss_OpenPrinterEx opEx;
1716         struct policy_handle handle;
1717         bool ret = true;
1718
1719         op.in.printername       = name;
1720         op.in.datatype          = NULL;
1721         op.in.devmode_ctr.devmode= NULL;
1722         op.in.access_mask       = 0;
1723         op.out.handle           = &handle;
1724
1725         torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
1726
1727         status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
1728         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
1729         if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
1730                 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
1731                         name, win_errstr(op.out.result));
1732         }
1733
1734         if (W_ERROR_IS_OK(op.out.result)) {
1735                 ret &=test_ClosePrinter(tctx, p, &handle);
1736         }
1737
1738         opEx.in.printername             = name;
1739         opEx.in.datatype                = NULL;
1740         opEx.in.devmode_ctr.devmode     = NULL;
1741         opEx.in.access_mask             = 0;
1742         opEx.in.level                   = 1;
1743         opEx.in.userlevel.level1        = NULL;
1744         opEx.out.handle                 = &handle;
1745
1746         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
1747
1748         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
1749         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
1750         if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
1751                 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
1752                         name, win_errstr(opEx.out.result));
1753         }
1754
1755         if (W_ERROR_IS_OK(opEx.out.result)) {
1756                 ret &=test_ClosePrinter(tctx, p, &handle);
1757         }
1758
1759         return ret;
1760 }
1761
1762 static bool test_OpenPrinter(struct torture_context *tctx,
1763                              struct dcerpc_pipe *p,
1764                              const char *name)
1765 {
1766         NTSTATUS status;
1767         struct spoolss_OpenPrinter r;
1768         struct policy_handle handle;
1769         bool ret = true;
1770
1771         r.in.printername        = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
1772         r.in.datatype           = NULL;
1773         r.in.devmode_ctr.devmode= NULL;
1774         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
1775         r.out.handle            = &handle;
1776
1777         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
1778
1779         status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
1780
1781         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
1782
1783         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
1784
1785         if (!test_GetPrinter(tctx, p, &handle)) {
1786                 ret = false;
1787         }
1788
1789         if (!torture_setting_bool(tctx, "samba3", false)) {
1790                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
1791                         ret = false;
1792                 }
1793         }
1794
1795         if (!test_ClosePrinter(tctx, p, &handle)) {
1796                 ret = false;
1797         }
1798
1799         return ret;
1800 }
1801
1802 static bool call_OpenPrinterEx(struct torture_context *tctx,
1803                                struct dcerpc_pipe *p,
1804                                const char *name, struct policy_handle *handle)
1805 {
1806         struct spoolss_OpenPrinterEx r;
1807         struct spoolss_UserLevel1 userlevel1;
1808         NTSTATUS status;
1809
1810         if (name && name[0]) {
1811                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
1812                                                    dcerpc_server_name(p), name);
1813         } else {
1814                 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
1815                                                    dcerpc_server_name(p));
1816         }
1817
1818         r.in.datatype           = NULL;
1819         r.in.devmode_ctr.devmode= NULL;
1820         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
1821         r.in.level              = 1;
1822         r.in.userlevel.level1   = &userlevel1;
1823         r.out.handle = handle;
1824
1825         userlevel1.size = 1234;
1826         userlevel1.client = "hello";
1827         userlevel1.user = "spottyfoot!";
1828         userlevel1.build = 1;
1829         userlevel1.major = 2;
1830         userlevel1.minor = 3;
1831         userlevel1.processor = 4;
1832
1833         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
1834
1835         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
1836
1837         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
1838
1839         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
1840
1841         return true;
1842 }
1843
1844 static bool test_OpenPrinterEx(struct torture_context *tctx,
1845                                struct dcerpc_pipe *p,
1846                                const char *name)
1847 {
1848         struct policy_handle handle;
1849         bool ret = true;
1850
1851         if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
1852                 return false;
1853         }
1854
1855         if (!test_GetPrinter(tctx, p, &handle)) {
1856                 ret = false;
1857         }
1858
1859         if (!test_EnumForms(tctx, p, &handle, false)) {
1860                 ret = false;
1861         }
1862
1863         if (!test_AddForm(tctx, p, &handle, false)) {
1864                 ret = false;
1865         }
1866
1867         if (!test_EnumPrinterData(tctx, p, &handle)) {
1868                 ret = false;
1869         }
1870
1871         if (!test_EnumPrinterDataEx(tctx, p, &handle)) {
1872                 ret = false;
1873         }
1874
1875         if (!test_PausePrinter(tctx, p, &handle)) {
1876                 ret = false;
1877         }
1878
1879         if (!test_DoPrintTest(tctx, p, &handle)) {
1880                 ret = false;
1881         }
1882
1883         if (!test_ResumePrinter(tctx, p, &handle)) {
1884                 ret = false;
1885         }
1886
1887         if (!test_SetPrinterData(tctx, p, &handle)) {
1888                 ret = false;
1889         }
1890
1891         if (!torture_setting_bool(tctx, "samba3", false)) {
1892                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
1893                         ret = false;
1894                 }
1895         }
1896
1897         if (!test_ClosePrinter(tctx, p, &handle)) {
1898                 ret = false;
1899         }
1900
1901         return ret;
1902 }
1903
1904 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
1905 {
1906         struct spoolss_EnumPrinters r;
1907         NTSTATUS status;
1908         uint16_t levels[] = {1, 2, 4, 5};
1909         int i;
1910         bool ret = true;
1911
1912         for (i=0;i<ARRAY_SIZE(levels);i++) {
1913                 union spoolss_PrinterInfo *info;
1914                 int j;
1915                 uint32_t needed;
1916                 uint32_t count;
1917
1918                 r.in.flags      = PRINTER_ENUM_LOCAL;
1919                 r.in.server     = "";
1920                 r.in.level      = levels[i];
1921                 r.in.buffer     = NULL;
1922                 r.in.offered    = 0;
1923                 r.out.needed    = &needed;
1924                 r.out.count     = &count;
1925                 r.out.info      = &info;
1926
1927                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1928
1929                 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
1930                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
1931
1932                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1933                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1934                         data_blob_clear(&blob);
1935                         r.in.buffer = &blob;
1936                         r.in.offered = needed;
1937                         status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
1938                 }
1939
1940                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
1941
1942                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1943
1944                 if (!info) {
1945                         torture_comment(tctx, "No printers returned\n");
1946                         return true;
1947                 }
1948
1949                 for (j=0;j<count;j++) {
1950                         if (r.in.level == 1) {
1951                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
1952                                 char *slash, *name;
1953                                 name = unc;
1954                                 if (unc[0] == '\\' && unc[1] == '\\') {
1955                                         unc +=2;
1956                                 }
1957                                 slash = strchr(unc, '\\');
1958                                 if (slash) {
1959                                         slash++;
1960                                         name = slash;
1961                                 }
1962                                 if (!test_OpenPrinter(tctx, p, name)) {
1963                                         ret = false;
1964                                 }
1965                                 if (!test_OpenPrinterEx(tctx, p, name)) {
1966                                         ret = false;
1967                                 }
1968                         }
1969                 }
1970         }
1971
1972         return ret;
1973 }
1974
1975 #if 0
1976 static bool test_GetPrinterDriver2(struct dcerpc_pipe *p,
1977                                    struct policy_handle *handle,
1978                                    const char *driver_name)
1979 {
1980         NTSTATUS status;
1981         struct spoolss_GetPrinterDriver2 r;
1982         uint32_t needed;
1983         uint32_t server_major_version;
1984         uint32_t server_minor_version;
1985
1986         r.in.handle = handle;
1987         r.in.architecture = "W32X86";
1988         r.in.level = 1;
1989         r.in.buffer = NULL;
1990         r.in.offered = 0;
1991         r.in.client_major_version = 0;
1992         r.in.client_minor_version = 0;
1993         r.out.needed = &needed;
1994         r.out.server_major_version = &server_major_version;
1995         r.out.server_minor_version = &server_minor_version;
1996
1997         printf("Testing GetPrinterDriver2\n");
1998
1999         status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
2000         if (!NT_STATUS_IS_OK(status)) {
2001                 printf("GetPrinterDriver2 failed - %s\n", nt_errstr(status));
2002                 return false;
2003         }
2004
2005         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2006                 r.in.offered = needed;
2007                 status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
2008         }
2009
2010         if (!NT_STATUS_IS_OK(status)) {
2011                 printf("GetPrinterDriver2 failed - %s\n",
2012                        nt_errstr(status));
2013                 return false;
2014         }
2015
2016         if (!W_ERROR_IS_OK(r.out.result)) {
2017                 printf("GetPrinterDriver2 failed - %s\n",
2018                        win_errstr(r.out.result));
2019                 return false;
2020         }
2021
2022         return true;
2023 }
2024 #endif
2025
2026 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
2027                                         struct dcerpc_pipe *p)
2028 {
2029         struct spoolss_EnumPrinterDrivers r;
2030         NTSTATUS status;
2031         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
2032         int i;
2033
2034         for (i=0;i<ARRAY_SIZE(levels);i++) {
2035
2036                 uint32_t needed;
2037                 uint32_t count;
2038                 union spoolss_DriverInfo *info;
2039
2040                 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2041                 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
2042                 r.in.level = levels[i];
2043                 r.in.buffer = NULL;
2044                 r.in.offered = 0;
2045                 r.out.needed = &needed;
2046                 r.out.count = &count;
2047                 r.out.info = &info;
2048
2049                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
2050
2051                 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2052
2053                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2054
2055                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2056                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2057                         data_blob_clear(&blob);
2058                         r.in.buffer = &blob;
2059                         r.in.offered = needed;
2060                         status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2061                 }
2062
2063                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2064
2065                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
2066
2067                 if (!info) {
2068                         torture_comment(tctx, "No printer drivers returned\n");
2069                         break;
2070                 }
2071         }
2072
2073         return true;
2074 }
2075
2076 bool torture_rpc_spoolss(struct torture_context *torture)
2077 {
2078         NTSTATUS status;
2079         struct dcerpc_pipe *p;
2080         bool ret = true;
2081         struct test_spoolss_context *ctx;
2082
2083         status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
2084         if (!NT_STATUS_IS_OK(status)) {
2085                 return false;
2086         }
2087
2088         ctx = talloc_zero(torture, struct test_spoolss_context);
2089
2090         ret &= test_OpenPrinter_server(torture, p, ctx);
2091
2092         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "W3SvcInstalled");
2093         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "BeepEnabled");
2094         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "EventLog");
2095         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopup");
2096         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopupToComputer");
2097         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MajorVersion");
2098         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MinorVersion");
2099         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DefaultSpoolDirectory");
2100         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "Architecture");
2101         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DsPresent");
2102         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersion");
2103         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersionEx");
2104         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DNSMachineName");
2105         ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
2106         ret &= test_AddForm(torture, p, &ctx->server_handle, true);
2107         ret &= test_EnumPorts(torture, p, ctx);
2108         ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
2109         ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
2110         ret &= test_EnumPrinterDrivers(torture, p, ctx);
2111         ret &= test_EnumMonitors(torture, p, ctx);
2112         ret &= test_EnumPrintProcessors(torture, p, ctx);
2113         ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
2114         ret &= test_EnumPrinters(torture, p, ctx);
2115         ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
2116         ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
2117         ret &= test_OpenPrinter_badname(torture, p, "");
2118         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
2119         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
2120         ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
2121         ret &= test_OpenPrinter_badname(torture, p,
2122                                         talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
2123
2124
2125         ret &= test_AddPort(torture, p);
2126         ret &= test_EnumPorts_old(torture, p);
2127         ret &= test_EnumPrinters_old(torture, p);
2128         ret &= test_EnumPrinterDrivers_old(torture, p);
2129
2130         return ret;
2131 }