s4-smbtorture: fix test_GetJob.
[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
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         
609         for (i=0;i<ARRAY_SIZE(levels);i++) {
610                 r.in.handle = handle;
611                 r.in.level = levels[i];
612                 r.in.buffer = NULL;
613                 r.in.offered = 0;
614
615                 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
616
617                 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
618                 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
619                 
620                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
621                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, r.out.needed);
622                         data_blob_clear(&blob);
623                         r.in.buffer = &blob;
624                         r.in.offered = r.out.needed;
625                         status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
626                 }
627                 
628                 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
629
630                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
631         }
632
633         return true;
634 }
635
636
637 static bool test_ClosePrinter(struct torture_context *tctx, 
638                               struct dcerpc_pipe *p, 
639                               struct policy_handle *handle)
640 {
641         NTSTATUS status;
642         struct spoolss_ClosePrinter r;
643
644         r.in.handle = handle;
645         r.out.handle = handle;
646
647         torture_comment(tctx, "Testing ClosePrinter\n");
648
649         status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
650         torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
651
652         return true;
653 }
654
655 static bool test_GetForm(struct torture_context *tctx, 
656                          struct dcerpc_pipe *p, 
657                          struct policy_handle *handle, 
658                          const char *form_name)
659 {
660         NTSTATUS status;
661         struct spoolss_GetForm r;
662
663         r.in.handle = handle;
664         r.in.form_name = form_name;
665         r.in.level = 1;
666         r.in.buffer = NULL;
667         r.in.offered = 0;
668
669         torture_comment(tctx, "Testing GetForm\n");
670
671         status = dcerpc_spoolss_GetForm(p, tctx, &r);
672         torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
673
674         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
675                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, r.out.needed);
676                 data_blob_clear(&blob);
677                 r.in.buffer = &blob;
678                 r.in.offered = r.out.needed;
679                 status = dcerpc_spoolss_GetForm(p, tctx, &r);
680                 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
681
682                 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
683
684                 torture_assert(tctx, r.out.info, "No form info returned");
685         }
686
687         torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
688
689         return true;
690 }
691
692 static bool test_EnumForms(struct torture_context *tctx, 
693                            struct dcerpc_pipe *p, 
694                            struct policy_handle *handle, bool print_server)
695 {
696         NTSTATUS status;
697         struct spoolss_EnumForms r;
698         bool ret = true;
699
700         r.in.handle = handle;
701         r.in.level = 1;
702         r.in.buffer = NULL;
703         r.in.offered = 0;
704
705         torture_comment(tctx, "Testing EnumForms\n");
706
707         status = dcerpc_spoolss_EnumForms(p, tctx, &r);
708         torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
709
710         if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
711                 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
712
713         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
714                 union spoolss_FormInfo *info;
715                 int j;
716                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, r.out.needed);
717                 data_blob_clear(&blob);
718                 r.in.buffer = &blob;
719                 r.in.offered = r.out.needed;
720
721                 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
722
723                 torture_assert(tctx, r.out.info, "No forms returned");
724
725                 info = r.out.info;
726
727                 for (j = 0; j < r.out.count; j++) {
728                         if (!print_server) 
729                                 ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name);
730                 }
731         }
732
733         torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
734
735         torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
736
737         return true;
738 }
739
740 static bool test_DeleteForm(struct torture_context *tctx, 
741                             struct dcerpc_pipe *p, 
742                             struct policy_handle *handle, 
743                             const char *form_name)
744 {
745         NTSTATUS status;
746         struct spoolss_DeleteForm r;
747
748         r.in.handle = handle;
749         r.in.form_name = form_name;
750
751         status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
752
753         torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
754
755         torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
756
757         return true;
758 }
759
760 static bool test_AddForm(struct torture_context *tctx, 
761                          struct dcerpc_pipe *p, 
762                          struct policy_handle *handle, bool print_server)
763 {
764         struct spoolss_AddForm r;
765         struct spoolss_AddFormInfo1 addform;
766         const char *form_name = "testform3";
767         NTSTATUS status;
768         bool ret = true;
769
770         r.in.handle     = handle;
771         r.in.level      = 1;
772         r.in.info.info1 = &addform;
773         addform.flags           = SPOOLSS_FORM_USER;
774         addform.form_name       = form_name;
775         addform.size.width      = 50;
776         addform.size.height     = 25;
777         addform.area.left       = 5;
778         addform.area.top        = 10;
779         addform.area.right      = 45;
780         addform.area.bottom     = 15;
781
782         status = dcerpc_spoolss_AddForm(p, tctx, &r);
783
784         torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
785
786         torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
787
788         if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name);
789
790         {
791                 struct spoolss_SetForm sf;
792                 struct spoolss_AddFormInfo1 setform;
793
794                 sf.in.handle    = handle;
795                 sf.in.form_name = form_name;
796                 sf.in.level     = 1;
797                 sf.in.info.info1= &setform;
798                 setform.flags           = addform.flags;
799                 setform.form_name       = addform.form_name;
800                 setform.size            = addform.size;
801                 setform.area            = addform.area;
802
803                 setform.size.width      = 1234;
804
805                 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
806
807                 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
808
809                 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
810         }
811
812         if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name);
813
814         if (!test_DeleteForm(tctx, p, handle, form_name)) {
815                 ret = false;
816         }
817
818         return ret;
819 }
820
821 static bool test_EnumPorts_old(struct torture_context *tctx, 
822                                struct dcerpc_pipe *p)
823 {
824         NTSTATUS status;
825         struct spoolss_EnumPorts r;
826
827         r.in.servername = talloc_asprintf(tctx, "\\\\%s", 
828                                           dcerpc_server_name(p));
829         r.in.level = 2;
830         r.in.buffer = NULL;
831         r.in.offered = 0;
832
833         torture_comment(tctx, "Testing EnumPorts\n");
834
835         status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
836
837         torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
838
839         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
840                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, r.out.needed);
841                 data_blob_clear(&blob);
842                 r.in.buffer = &blob;
843                 r.in.offered = r.out.needed;
844
845                 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
846                 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
847
848                 torture_assert(tctx, r.out.info, "No ports returned");
849         }
850
851         return true;
852 }
853
854 static bool test_AddPort(struct torture_context *tctx, 
855                          struct dcerpc_pipe *p)
856 {
857         NTSTATUS status;
858         struct spoolss_AddPort r;
859
860         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", 
861                                            dcerpc_server_name(p));
862         r.in.unknown = 0;
863         r.in.monitor_name = "foo";
864
865         torture_comment(tctx, "Testing AddPort\n");
866
867         status = dcerpc_spoolss_AddPort(p, tctx, &r);
868
869         torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
870
871         /* win2k3 returns WERR_NOT_SUPPORTED */
872
873 #if 0
874
875         if (!W_ERROR_IS_OK(r.out.result)) {
876                 printf("AddPort failed - %s\n", win_errstr(r.out.result));
877                 return false;
878         }
879
880 #endif
881
882         return true;
883 }
884
885 static bool test_GetJob(struct torture_context *tctx, 
886                         struct dcerpc_pipe *p, 
887                         struct policy_handle *handle, uint32_t job_id)
888 {
889         NTSTATUS status;
890         struct spoolss_GetJob r;
891         uint32_t needed;
892
893         r.in.handle = handle;
894         r.in.job_id = job_id;
895         r.in.level = 1;
896         r.in.buffer = NULL;
897         r.in.offered = 0;
898         r.out.needed = &needed;
899
900         torture_comment(tctx, "Testing GetJob\n");
901
902         status = dcerpc_spoolss_GetJob(p, tctx, &r);
903         torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
904
905         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
906                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
907                 data_blob_clear(&blob);
908                 r.in.buffer = &blob;
909                 r.in.offered = needed;
910
911                 status = dcerpc_spoolss_GetJob(p, tctx, &r);
912
913                 torture_assert(tctx, r.out.info, "No job info returned");
914         }
915
916         return true;
917 }
918
919 static bool test_SetJob(struct torture_context *tctx, 
920                         struct dcerpc_pipe *p, 
921                         struct policy_handle *handle, uint32_t job_id, 
922                         enum spoolss_JobControl command)
923 {
924         NTSTATUS status;
925         struct spoolss_SetJob r;
926
927         r.in.handle     = handle;
928         r.in.job_id     = job_id;
929         r.in.ctr        = NULL;
930         r.in.command    = command;
931
932         torture_comment(tctx, "Testing SetJob\n");
933
934         status = dcerpc_spoolss_SetJob(p, tctx, &r);
935         torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
936         torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
937
938         return true;
939 }
940
941 static bool test_EnumJobs(struct torture_context *tctx, 
942                           struct dcerpc_pipe *p, 
943                           struct policy_handle *handle)
944 {
945         NTSTATUS status;
946         struct spoolss_EnumJobs r;
947
948         r.in.handle = handle;
949         r.in.firstjob = 0;
950         r.in.numjobs = 0xffffffff;
951         r.in.level = 1;
952         r.in.buffer = NULL;
953         r.in.offered = 0;
954
955         torture_comment(tctx, "Testing EnumJobs\n");
956
957         status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
958
959         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
960
961         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
962                 union spoolss_JobInfo *info;
963                 int j;
964                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, r.out.needed);
965                 data_blob_clear(&blob);
966                 r.in.buffer = &blob;
967                 r.in.offered = r.out.needed;
968
969                 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
970
971                 torture_assert(tctx, r.out.info, "No jobs returned");
972
973                 info = r.out.info;
974
975                 for (j = 0; j < r.out.count; j++) {
976                         test_GetJob(tctx, p, handle, info[j].info1.job_id);
977                         test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
978                         test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
979                 }
980
981         } else {
982                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
983         }
984
985         return true;
986 }
987
988 static bool test_DoPrintTest(struct torture_context *tctx, 
989                              struct dcerpc_pipe *p, 
990                              struct policy_handle *handle)
991 {
992         bool ret = true;
993         NTSTATUS status;
994         struct spoolss_StartDocPrinter s;
995         struct spoolss_DocumentInfo1 info1;
996         struct spoolss_StartPagePrinter sp;
997         struct spoolss_WritePrinter w;
998         struct spoolss_EndPagePrinter ep;
999         struct spoolss_EndDocPrinter e;
1000         int i;
1001         uint32_t job_id;
1002
1003         torture_comment(tctx, "Testing StartDocPrinter\n");
1004
1005         s.in.handle             = handle;
1006         s.in.level              = 1;
1007         s.in.info.info1         = &info1;
1008         info1.document_name     = "TorturePrintJob";
1009         info1.output_file       = NULL;
1010         info1.datatype          = "RAW";
1011
1012         status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
1013         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
1014         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
1015
1016         job_id = s.out.job_id;
1017
1018         for (i=1; i < 4; i++) {
1019                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
1020
1021                 sp.in.handle            = handle;
1022
1023                 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
1024                 torture_assert_ntstatus_ok(tctx, status, 
1025                                            "dcerpc_spoolss_StartPagePrinter failed");
1026                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
1027
1028                 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
1029
1030                 w.in.handle             = handle;
1031                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
1032
1033                 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
1034                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
1035                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
1036
1037                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
1038
1039                 ep.in.handle            = handle;
1040
1041                 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
1042                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
1043                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
1044         }
1045
1046         torture_comment(tctx, "Testing EndDocPrinter\n");
1047
1048         e.in.handle = handle;
1049
1050         status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
1051         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
1052         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
1053
1054         ret &= test_EnumJobs(tctx, p, handle);
1055
1056         ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
1057
1058         return ret;
1059 }
1060
1061 static bool test_PausePrinter(struct torture_context *tctx, 
1062                               struct dcerpc_pipe *p, 
1063                               struct policy_handle *handle)
1064 {
1065         NTSTATUS status;
1066         struct spoolss_SetPrinter r;
1067
1068         r.in.handle             = handle;
1069         r.in.level              = 0;
1070         r.in.info.info1         = NULL;
1071         r.in.devmode_ctr.devmode= NULL;
1072         r.in.secdesc_ctr.sd     = NULL;
1073         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
1074
1075         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1076
1077         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1078
1079         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1080
1081         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1082
1083         return true;
1084 }
1085
1086 static bool test_ResumePrinter(struct torture_context *tctx, 
1087                                struct dcerpc_pipe *p, 
1088                                struct policy_handle *handle)
1089 {
1090         NTSTATUS status;
1091         struct spoolss_SetPrinter r;
1092
1093         r.in.handle             = handle;
1094         r.in.level              = 0;
1095         r.in.info.info1         = NULL;
1096         r.in.devmode_ctr.devmode= NULL;
1097         r.in.secdesc_ctr.sd     = NULL;
1098         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
1099
1100         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
1101
1102         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1103
1104         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1105
1106         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1107
1108         return true;
1109 }
1110
1111 static bool test_GetPrinterData(struct torture_context *tctx, 
1112                                 struct dcerpc_pipe *p, 
1113                                 struct policy_handle *handle, 
1114                                 const char *value_name)
1115 {
1116         NTSTATUS status;
1117         struct spoolss_GetPrinterData r;
1118
1119         r.in.handle = handle;
1120         r.in.value_name = value_name;
1121         r.in.offered = 0;
1122
1123         torture_comment(tctx, "Testing GetPrinterData\n");
1124
1125         status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
1126         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
1127
1128         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1129                 r.in.offered = r.out.needed;
1130
1131                 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
1132                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
1133
1134                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterData failed");
1135         }
1136
1137         return true;
1138 }
1139
1140 static bool test_GetPrinterDataEx(struct torture_context *tctx, 
1141                                   struct dcerpc_pipe *p, 
1142                                   struct policy_handle *handle, 
1143                                   const char *key_name,
1144                                   const char *value_name)
1145 {
1146         NTSTATUS status;
1147         struct spoolss_GetPrinterDataEx r;
1148
1149         r.in.handle = handle;
1150         r.in.key_name = key_name;
1151         r.in.value_name = value_name;
1152         r.in.offered = 0;
1153
1154         torture_comment(tctx, "Testing GetPrinterDataEx\n");
1155
1156         status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
1157         if (!NT_STATUS_IS_OK(status)) {
1158                 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
1159                     p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1160                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
1161                 }
1162                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
1163         }
1164
1165         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1166                 r.in.offered = r.out.needed;
1167
1168                 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
1169                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
1170
1171                 torture_assert_werr_ok(tctx, r.out.result,  "GetPrinterDataEx failed");
1172         }
1173
1174         return true;
1175 }
1176
1177 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p, 
1178                                  struct policy_handle *handle)
1179 {
1180         NTSTATUS status;
1181         struct spoolss_EnumPrinterData r;
1182
1183         ZERO_STRUCT(r);
1184         r.in.handle = handle;
1185         r.in.enum_index = 0;
1186
1187         do {
1188                 uint32_t value_size = 0;
1189                 uint32_t data_size = 0;
1190                 uint32_t printerdata_type = 0;
1191                 DATA_BLOB data = data_blob(NULL,0);
1192
1193                 r.in.value_offered = value_size;
1194                 r.out.value_needed = &value_size;
1195                 r.in.data_offered = data_size;
1196                 r.out.data_needed = &data_size;
1197
1198                 r.out.printerdata_type = &printerdata_type;
1199                 r.out.buffer = &data;
1200
1201                 torture_comment(tctx, "Testing EnumPrinterData\n");
1202
1203                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
1204
1205                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
1206
1207                 r.in.value_offered = value_size;
1208                 r.in.data_offered = data_size;
1209
1210                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
1211
1212                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
1213                 
1214                 test_GetPrinterData(tctx, p, handle, r.out.value_name);
1215
1216                 test_GetPrinterDataEx(tctx, 
1217                         p, handle, "PrinterDriverData", 
1218                         r.out.value_name);
1219
1220                 r.in.enum_index++;
1221
1222         } while (W_ERROR_IS_OK(r.out.result));
1223
1224         return true;
1225 }
1226
1227 static bool test_EnumPrinterDataEx(struct torture_context *tctx, 
1228                                    struct dcerpc_pipe *p, 
1229                                    struct policy_handle *handle)
1230 {
1231         NTSTATUS status;
1232         struct spoolss_EnumPrinterDataEx r;
1233
1234         r.in.handle = handle;
1235         r.in.key_name = "PrinterDriverData";
1236         r.in.offered = 0;
1237
1238         torture_comment(tctx, "Testing EnumPrinterDataEx\n");
1239
1240         status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
1241         torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
1242
1243         r.in.offered = r.out.needed;
1244
1245         status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
1246
1247         torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
1248
1249         return true;
1250 }
1251
1252
1253 static bool test_DeletePrinterData(struct torture_context *tctx, 
1254                                    struct dcerpc_pipe *p, 
1255                                    struct policy_handle *handle, 
1256                                    const char *value_name)
1257 {
1258         NTSTATUS status;
1259         struct spoolss_DeletePrinterData r;
1260
1261         r.in.handle = handle;
1262         r.in.value_name = value_name;
1263
1264         torture_comment(tctx, "Testing DeletePrinterData\n");
1265
1266         status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
1267
1268         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
1269
1270         return true;
1271 }
1272
1273 static bool test_SetPrinterData(struct torture_context *tctx, 
1274                                 struct dcerpc_pipe *p, 
1275                                 struct policy_handle *handle)
1276 {
1277         NTSTATUS status;
1278         struct spoolss_SetPrinterData r;
1279         const char *value_name = "spottyfoot";
1280         
1281         r.in.handle = handle;
1282         r.in.value_name = value_name;
1283         r.in.type = SPOOLSS_PRINTER_DATA_TYPE_STRING;
1284         r.in.data.string = "dog";
1285
1286         torture_comment(tctx, "Testing SetPrinterData\n");
1287
1288         status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
1289
1290         torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
1291
1292         if (!test_GetPrinterData(tctx, p, handle, value_name)) {
1293                 return false;
1294         }
1295
1296         if (!test_DeletePrinterData(tctx, p, handle, value_name)) {
1297                 return false;
1298         }
1299
1300         return true;
1301 }
1302
1303 static bool test_SecondaryClosePrinter(struct torture_context *tctx, 
1304                                        struct dcerpc_pipe *p, 
1305                                        struct policy_handle *handle)
1306 {
1307         NTSTATUS status;
1308         struct dcerpc_binding *b;
1309         struct dcerpc_pipe *p2;
1310         struct spoolss_ClosePrinter cp;
1311
1312         /* only makes sense on SMB */
1313         if (p->conn->transport.transport != NCACN_NP) {
1314                 return true;
1315         }
1316
1317         torture_comment(tctx, "testing close on secondary pipe\n");
1318
1319         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
1320         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
1321
1322         status = dcerpc_secondary_connection(p, &p2, b);
1323         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
1324
1325         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
1326         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
1327
1328         cp.in.handle = handle;
1329         cp.out.handle = handle;
1330
1331         status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
1332         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
1333                         "ERROR: Allowed close on secondary connection");
1334
1335         torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, 
1336                                  "Unexpected fault code");
1337
1338         talloc_free(p2);
1339
1340         return true;
1341 }
1342
1343 static bool test_OpenPrinter_badname(struct torture_context *tctx, 
1344                                      struct dcerpc_pipe *p, const char *name)
1345 {
1346         NTSTATUS status;
1347         struct spoolss_OpenPrinter op;
1348         struct spoolss_OpenPrinterEx opEx;
1349         struct policy_handle handle;
1350         bool ret = true;
1351
1352         op.in.printername       = name;
1353         op.in.datatype          = NULL;
1354         op.in.devmode_ctr.devmode= NULL;
1355         op.in.access_mask       = 0;
1356         op.out.handle           = &handle;
1357
1358         torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
1359
1360         status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
1361         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
1362         if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
1363                 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
1364                         name, win_errstr(op.out.result));
1365         }
1366
1367         if (W_ERROR_IS_OK(op.out.result)) {
1368                 ret &=test_ClosePrinter(tctx, p, &handle);
1369         }
1370
1371         opEx.in.printername             = name;
1372         opEx.in.datatype                = NULL;
1373         opEx.in.devmode_ctr.devmode     = NULL;
1374         opEx.in.access_mask             = 0;
1375         opEx.in.level                   = 1;
1376         opEx.in.userlevel.level1        = NULL;
1377         opEx.out.handle                 = &handle;
1378
1379         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
1380
1381         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
1382         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
1383         if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
1384                 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
1385                         name, win_errstr(opEx.out.result));
1386         }
1387
1388         if (W_ERROR_IS_OK(opEx.out.result)) {
1389                 ret &=test_ClosePrinter(tctx, p, &handle);
1390         }
1391
1392         return ret;
1393 }
1394
1395 static bool test_OpenPrinter(struct torture_context *tctx, 
1396                              struct dcerpc_pipe *p, 
1397                              const char *name)
1398 {
1399         NTSTATUS status;
1400         struct spoolss_OpenPrinter r;
1401         struct policy_handle handle;
1402         bool ret = true;
1403
1404         r.in.printername        = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
1405         r.in.datatype           = NULL;
1406         r.in.devmode_ctr.devmode= NULL;
1407         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
1408         r.out.handle            = &handle;
1409
1410         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
1411
1412         status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
1413
1414         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
1415
1416         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
1417
1418         if (!test_GetPrinter(tctx, p, &handle)) {
1419                 ret = false;
1420         }
1421
1422         if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
1423                 ret = false;
1424         }
1425
1426         if (!test_ClosePrinter(tctx, p, &handle)) {
1427                 ret = false;
1428         }
1429
1430         return ret;
1431 }
1432
1433 static bool call_OpenPrinterEx(struct torture_context *tctx, 
1434                                struct dcerpc_pipe *p, 
1435                                const char *name, struct policy_handle *handle)
1436 {
1437         struct spoolss_OpenPrinterEx r;
1438         struct spoolss_UserLevel1 userlevel1;
1439         NTSTATUS status;
1440
1441         if (name && name[0]) {
1442                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", 
1443                                                    dcerpc_server_name(p), name);
1444         } else {
1445                 r.in.printername = talloc_asprintf(tctx, "\\\\%s", 
1446                                                    dcerpc_server_name(p));
1447         }
1448
1449         r.in.datatype           = NULL;
1450         r.in.devmode_ctr.devmode= NULL;
1451         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
1452         r.in.level              = 1;
1453         r.in.userlevel.level1   = &userlevel1;
1454         r.out.handle = handle;
1455
1456         userlevel1.size = 1234;
1457         userlevel1.client = "hello";
1458         userlevel1.user = "spottyfoot!";
1459         userlevel1.build = 1;
1460         userlevel1.major = 2;
1461         userlevel1.minor = 3;
1462         userlevel1.processor = 4;
1463
1464         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
1465
1466         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
1467
1468         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
1469         
1470         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
1471
1472         return true;
1473 }
1474
1475 static bool test_OpenPrinterEx(struct torture_context *tctx, 
1476                                struct dcerpc_pipe *p, 
1477                                const char *name)
1478 {
1479         struct policy_handle handle;
1480         bool ret = true;
1481
1482         if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
1483                 return false;
1484         }
1485
1486         if (!test_GetPrinter(tctx, p, &handle)) {
1487                 ret = false;
1488         }
1489
1490         if (!test_EnumForms(tctx, p, &handle, false)) {
1491                 ret = false;
1492         }
1493
1494         if (!test_AddForm(tctx, p, &handle, false)) {
1495                 ret = false;
1496         }
1497
1498         if (!test_EnumPrinterData(tctx, p, &handle)) {
1499                 ret = false;
1500         }
1501
1502         if (!test_EnumPrinterDataEx(tctx, p, &handle)) {
1503                 ret = false;
1504         }
1505
1506         if (!test_PausePrinter(tctx, p, &handle)) {
1507                 ret = false;
1508         }
1509
1510         if (!test_DoPrintTest(tctx, p, &handle)) {
1511                 ret = false;
1512         }
1513
1514         if (!test_ResumePrinter(tctx, p, &handle)) {
1515                 ret = false;
1516         }
1517
1518         if (!test_SetPrinterData(tctx, p, &handle)) {
1519                 ret = false;
1520         }
1521
1522         if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
1523                 ret = false;
1524         }
1525
1526         if (!test_ClosePrinter(tctx, p, &handle)) {
1527                 ret = false;
1528         }
1529         
1530         return ret;
1531 }
1532
1533 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
1534 {
1535         struct spoolss_EnumPrinters r;
1536         NTSTATUS status;
1537         uint16_t levels[] = {1, 2, 4, 5};
1538         int i;
1539         bool ret = true;
1540
1541         for (i=0;i<ARRAY_SIZE(levels);i++) {
1542                 union spoolss_PrinterInfo *info;
1543                 int j;
1544
1545                 r.in.flags      = PRINTER_ENUM_LOCAL;
1546                 r.in.server     = "";
1547                 r.in.level      = levels[i];
1548                 r.in.buffer     = NULL;
1549                 r.in.offered    = 0;
1550
1551                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1552
1553                 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
1554                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
1555
1556                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1557                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, r.out.needed);
1558                         data_blob_clear(&blob);
1559                         r.in.buffer = &blob;
1560                         r.in.offered = r.out.needed;
1561                         status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
1562                 }
1563
1564                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
1565
1566                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1567
1568                 if (!r.out.info) {
1569                         torture_comment(tctx, "No printers returned\n");
1570                         return true;
1571                 }
1572
1573                 info = r.out.info;
1574
1575                 for (j=0;j<r.out.count;j++) {
1576                         if (r.in.level == 1) {
1577                                 /* the names appear to be comma-separated name lists? */
1578                                 char *name = talloc_strdup(tctx, info[j].info1.name);
1579                                 char *comma = strchr(name, ',');
1580                                 if (comma) *comma = 0;
1581                                 if (!test_OpenPrinter(tctx, p, name)) {
1582                                         ret = false;
1583                                 }
1584                                 if (!test_OpenPrinterEx(tctx, p, name)) {
1585                                         ret = false;
1586                                 }
1587                         }
1588                 }
1589         }
1590
1591         return ret;
1592 }
1593
1594 #if 0
1595 static bool test_GetPrinterDriver2(struct dcerpc_pipe *p, 
1596                                    struct policy_handle *handle, 
1597                                    const char *driver_name)
1598 {
1599         NTSTATUS status;
1600         struct spoolss_GetPrinterDriver2 r;
1601
1602         r.in.handle = handle;
1603         r.in.architecture = "W32X86";
1604         r.in.level = 1;
1605         r.in.buffer = NULL;
1606         r.in.offered = 0;
1607         r.in.client_major_version = 0;
1608         r.in.client_minor_version = 0;
1609
1610         printf("Testing GetPrinterDriver2\n");
1611
1612         status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
1613         if (!NT_STATUS_IS_OK(status)) {
1614                 printf("GetPrinterDriver2 failed - %s\n", nt_errstr(status));
1615                 return false;
1616         }
1617
1618         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1619                 r.in.offered = r.out.needed;
1620                 status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
1621         }
1622                 
1623         if (!NT_STATUS_IS_OK(status)) {
1624                 printf("GetPrinterDriver2 failed - %s\n", 
1625                        nt_errstr(status));
1626                 return false;
1627         }
1628
1629         if (!W_ERROR_IS_OK(r.out.result)) {
1630                 printf("GetPrinterDriver2 failed - %s\n", 
1631                        win_errstr(r.out.result));
1632                 return false;
1633         }
1634
1635         return true;
1636 }
1637 #endif
1638
1639 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx, 
1640                                         struct dcerpc_pipe *p)
1641 {
1642         struct spoolss_EnumPrinterDrivers r;
1643         NTSTATUS status;
1644         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
1645         int i;
1646
1647         for (i=0;i<ARRAY_SIZE(levels);i++) {
1648
1649                 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1650                 r.in.environment = "Windows NT x86";
1651                 r.in.level = levels[i];
1652                 r.in.buffer = NULL;
1653                 r.in.offered = 0;
1654
1655                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
1656
1657                 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
1658
1659                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
1660
1661                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1662                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, r.out.needed);
1663                         data_blob_clear(&blob);
1664                         r.in.buffer = &blob;
1665                         r.in.offered = r.out.needed;
1666                         status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
1667                 }
1668
1669                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
1670
1671                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
1672
1673                 if (!r.out.info) {
1674                         torture_comment(tctx, "No printer drivers returned\n");
1675                         break;
1676                 }
1677         }
1678
1679         return true;
1680 }
1681
1682 /** Test that makes sure that calling ReplyOpenPrinter()
1683  * on Samba 4 will cause an irpc broadcast call.
1684  */
1685 static bool test_ReplyOpenPrinter(struct torture_context *tctx, 
1686                                   struct dcerpc_pipe *pipe)
1687 {
1688         struct spoolss_ReplyOpenPrinter r;
1689         struct spoolss_ReplyClosePrinter s;
1690         struct policy_handle h;
1691
1692         r.in.server_name = "earth";
1693         r.in.printer_local = 2;
1694         r.in.type = REG_DWORD;
1695         r.in.unknown1 = 0;
1696         r.in.unknown2 = 0;
1697         r.out.handle = &h;
1698
1699         torture_assert_ntstatus_ok(tctx, 
1700                         dcerpc_spoolss_ReplyOpenPrinter(pipe, tctx, &r),
1701                         "spoolss_ReplyOpenPrinter call failed");
1702
1703         torture_assert_werr_ok(tctx, r.out.result, "error return code");
1704
1705         s.in.handle = &h;
1706         s.out.handle = &h;
1707
1708         torture_assert_ntstatus_ok(tctx,
1709                         dcerpc_spoolss_ReplyClosePrinter(pipe, tctx, &s),
1710                         "spoolss_ReplyClosePrinter call failed");
1711
1712         torture_assert_werr_ok(tctx, r.out.result, "error return code");
1713
1714         return true;
1715 }
1716
1717 bool torture_rpc_spoolss(struct torture_context *torture)
1718 {
1719         NTSTATUS status;
1720         struct dcerpc_pipe *p;
1721         bool ret = true;
1722         struct test_spoolss_context *ctx;
1723
1724         status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
1725         if (!NT_STATUS_IS_OK(status)) {
1726                 return false;
1727         }
1728
1729         ctx = talloc_zero(torture, struct test_spoolss_context);
1730
1731         ret &= test_OpenPrinter_server(torture, p, ctx);
1732
1733         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "W3SvcInstalled");
1734         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "BeepEnabled");
1735         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "EventLog");
1736         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopup");
1737         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopupToComputer");
1738         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MajorVersion");
1739         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MinorVersion");
1740         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DefaultSpoolDirectory");
1741         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "Architecture");
1742         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DsPresent");
1743         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersion");
1744         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersionEx");
1745         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DNSMachineName");
1746         ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
1747         ret &= test_AddForm(torture, p, &ctx->server_handle, true);
1748         ret &= test_EnumPorts(torture, p, ctx);
1749         ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
1750         ret &= test_EnumPrinterDrivers(torture, p, ctx);
1751         ret &= test_EnumMonitors(torture, p, ctx);
1752         ret &= test_EnumPrintProcessors(torture, p, ctx);
1753         ret &= test_EnumPrinters(torture, p, ctx);
1754         ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
1755         ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
1756         ret &= test_OpenPrinter_badname(torture, p, "");
1757         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
1758         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
1759         ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
1760         ret &= test_OpenPrinter_badname(torture, p, 
1761                                         talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
1762
1763
1764         ret &= test_AddPort(torture, p);
1765         ret &= test_EnumPorts_old(torture, p);
1766         ret &= test_EnumPrinters_old(torture, p);
1767         ret &= test_EnumPrinterDrivers_old(torture, p);
1768         ret &= test_ReplyOpenPrinter(torture, p);
1769
1770         return ret;
1771 }