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