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