Merge Samba3 and Samba4 together
[kai/samba-autobuild/.git] / source4 / torture / rpc / spoolss.c
1 /* 
2    Unix SMB/CIFS implementation.
3    test suite for spoolss rpc operations
4
5    Copyright (C) Tim Potter 2003
6    Copyright (C) Stefan Metzmacher 2005
7    Copyright (C) Jelmer Vernooij 2007
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "torture/torture.h"
25 #include "torture/rpc/rpc.h"
26 #include "librpc/gen_ndr/ndr_spoolss_c.h"
27
28 struct test_spoolss_context {
29         /* print server handle */
30         struct policy_handle server_handle;
31
32         /* for EnumPorts */
33         uint32_t port_count[3];
34         union spoolss_PortInfo *ports[3];
35
36         /* for EnumPrinterDrivers */
37         uint32_t driver_count[7];
38         union spoolss_DriverInfo *drivers[7];
39
40         /* for EnumMonitors */
41         uint32_t monitor_count[3];
42         union spoolss_MonitorInfo *monitors[3];
43
44         /* for EnumPrintProcessors */
45         uint32_t print_processor_count[2];
46         union spoolss_PrintProcessorInfo *print_processors[2];
47
48         /* for EnumPrinters */
49         uint32_t printer_count[6];
50         union spoolss_PrinterInfo *printers[6];
51 };
52
53 #define COMPARE_STRING(tctx, c,r,e) \
54         torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
55
56 /* not every compiler supports __typeof__() */
57 #if (__GNUC__ >= 3)
58 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
59         if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
60                 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
61         }\
62         if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
63                 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
64         }\
65 } while(0)
66 #else
67 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
68 #endif
69
70 #define COMPARE_UINT32(tctx, c, r, e) do {\
71         _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
72         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
73 } while(0)
74
75 #define COMPARE_STRING_ARRAY(tctx, c,r,e)
76
77 static bool test_OpenPrinter_server(struct torture_context *tctx, struct dcerpc_pipe *p, struct test_spoolss_context *ctx)
78 {
79         NTSTATUS status;
80         struct spoolss_OpenPrinter op;
81
82         op.in.printername       = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p));
83         op.in.datatype          = NULL;
84         op.in.devmode_ctr.devmode= NULL;
85         op.in.access_mask       = 0;
86         op.out.handle           = &ctx->server_handle;
87
88         torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
89
90         status = dcerpc_spoolss_OpenPrinter(p, ctx, &op);
91         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
92         torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed"); 
93
94         return true;
95 }
96
97 static bool test_EnumPorts(struct torture_context *tctx, 
98                            struct dcerpc_pipe *p, 
99                            struct test_spoolss_context *ctx)
100 {
101         NTSTATUS status;
102         struct spoolss_EnumPorts r;
103         uint16_t levels[] = { 1, 2 };
104         int i, j;
105
106         for (i=0;i<ARRAY_SIZE(levels);i++) {
107                 int level = levels[i];
108                 DATA_BLOB blob;
109
110                 r.in.servername = "";
111                 r.in.level = level;
112                 r.in.buffer = NULL;
113                 r.in.offered = 0;
114
115                 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
116
117                 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
118                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
119                 if (W_ERROR_IS_OK(r.out.result)) {
120                         /* TODO: do some more checks here */
121                         continue;
122                 }
123                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER, 
124                         "EnumPorts unexpected return code");
125
126                 blob = data_blob_talloc(ctx, NULL, r.out.needed);
127                 data_blob_clear(&blob);
128                 r.in.buffer = &blob;
129                 r.in.offered = r.out.needed;
130
131                 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
132                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
133
134                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
135
136                 ctx->port_count[level]  = r.out.count;
137                 ctx->ports[level]       = r.out.info;
138         }
139
140         for (i=1;i<ARRAY_SIZE(levels);i++) {
141                 int level = levels[i];
142                 int old_level = levels[i-1];
143                 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level], 
144                         "EnumPorts invalid value");
145         }
146         /* if the array sizes are not the same we would maybe segfault in the following code */
147
148         for (i=0;i<ARRAY_SIZE(levels);i++) {
149                 int level = levels[i];
150                 for (j=0;j<ctx->port_count[level];j++) {
151                         union spoolss_PortInfo *cur = &ctx->ports[level][j];
152                         union spoolss_PortInfo *ref = &ctx->ports[2][j];
153                         switch (level) {
154                         case 1:
155                                 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
156                                 break;
157                         case 2:
158                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
159                                 break;
160                         }
161                 }
162         }
163
164         return true;
165 }
166
167 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx, 
168                                            struct dcerpc_pipe *p, 
169                                            struct test_spoolss_context *ctx)
170 {
171         NTSTATUS status;
172         struct spoolss_GetPrinterDriverDirectory r;
173         struct {
174                 uint16_t level;
175                 const char *server;
176         } levels[] = {{
177                         .level  = 1,
178                         .server = NULL
179                 },{
180                         .level  = 1,
181                         .server = ""
182                 },{
183                         .level  = 78,
184                         .server = ""
185                 },{
186                         .level  = 1,
187                         .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
188                 },{
189                         .level  = 1024,
190                         .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
191                 }
192         };
193         int i;
194
195         for (i=0;i<ARRAY_SIZE(levels);i++) {
196                 int level = levels[i].level;
197                 DATA_BLOB blob;
198
199                 r.in.server             = levels[i].server;
200                 r.in.environment        = SPOOLSS_ARCHITECTURE_NT_X86;
201                 r.in.level              = level;
202                 r.in.buffer             = NULL;
203                 r.in.offered            = 0;
204
205                 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
206
207                 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
208                 torture_assert_ntstatus_ok(tctx, status, 
209                         "dcerpc_spoolss_GetPrinterDriverDirectory failed");
210                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER, 
211                         "GetPrinterDriverDirectory unexpected return code");
212
213                 blob = data_blob_talloc(ctx, NULL, r.out.needed);
214                 data_blob_clear(&blob);
215                 r.in.buffer = &blob;
216                 r.in.offered = r.out.needed;
217
218                 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
219                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
220
221                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
222         }
223
224         return true;
225 }
226
227 static bool test_EnumPrinterDrivers(struct torture_context *tctx, 
228                                     struct dcerpc_pipe *p,
229                                     struct test_spoolss_context *ctx)
230 {
231         NTSTATUS status;
232         struct spoolss_EnumPrinterDrivers r;
233         uint16_t levels[] = { 1, 2, 3, 4, 5, 6 };
234         int i, j;
235
236         for (i=0;i<ARRAY_SIZE(levels);i++) {
237                 int level = levels[i];
238                 DATA_BLOB blob;
239
240                 r.in.server             = "";
241                 r.in.environment        = SPOOLSS_ARCHITECTURE_NT_X86;
242                 r.in.level              = level;
243                 r.in.buffer             = NULL;
244                 r.in.offered            = 0;
245
246                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
247
248                 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
249                 torture_assert_ntstatus_ok(tctx, status, 
250                                            "dcerpc_spoolss_EnumPrinterDrivers failed");
251                 if (W_ERROR_IS_OK(r.out.result)) {
252                         /* TODO: do some more checks here */
253                         continue;
254                 }
255                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER, 
256                         "EnumPrinterDrivers failed");
257
258                 blob = data_blob_talloc(ctx, NULL, r.out.needed);
259                 data_blob_clear(&blob);
260                 r.in.buffer = &blob;
261                 r.in.offered = r.out.needed;
262
263                 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
264                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
265
266                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
267
268                 ctx->driver_count[level]        = r.out.count;
269                 ctx->drivers[level]             = r.out.info;
270         }
271
272         for (i=1;i<ARRAY_SIZE(levels);i++) {
273                 int level = levels[i];
274                 int old_level = levels[i-1];
275                 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
276                         "EnumPrinterDrivers invalid value");
277         }
278
279         for (i=0;i<ARRAY_SIZE(levels);i++) {
280                 int level = levels[i];
281                 for (j=0;j<ctx->driver_count[level];j++) {
282                         union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
283                         union spoolss_DriverInfo *ref = &ctx->drivers[6][j];
284                         switch (level) {
285                         case 1:
286                                 COMPARE_STRING(tctx, cur->info1, ref->info6, driver_name);
287                                 break;
288                         case 2:
289                                 COMPARE_UINT32(tctx, cur->info2, ref->info6, version);
290                                 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_name);
291                                 COMPARE_STRING(tctx, cur->info2, ref->info6, architecture);
292                                 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_path);
293                                 COMPARE_STRING(tctx, cur->info2, ref->info6, data_file);
294                                 COMPARE_STRING(tctx, cur->info2, ref->info6, config_file);
295                                 break;
296                         case 3:
297                                 COMPARE_UINT32(tctx, cur->info3, ref->info6, version);
298                                 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_name);
299                                 COMPARE_STRING(tctx, cur->info3, ref->info6, architecture);
300                                 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_path);
301                                 COMPARE_STRING(tctx, cur->info3, ref->info6, data_file);
302                                 COMPARE_STRING(tctx, cur->info3, ref->info6, config_file);
303                                 COMPARE_STRING(tctx, cur->info3, ref->info6, help_file);
304                                 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info6, dependent_files);
305                                 COMPARE_STRING(tctx, cur->info3, ref->info6, monitor_name);
306                                 COMPARE_STRING(tctx, cur->info3, ref->info6, default_datatype);
307                                 break;
308                         case 4:
309                                 COMPARE_UINT32(tctx, cur->info4, ref->info6, version);
310                                 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_name);
311                                 COMPARE_STRING(tctx, cur->info4, ref->info6, architecture);
312                                 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_path);
313                                 COMPARE_STRING(tctx, cur->info4, ref->info6, data_file);
314                                 COMPARE_STRING(tctx, cur->info4, ref->info6, config_file);
315                                 COMPARE_STRING(tctx, cur->info4, ref->info6, help_file);
316                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, dependent_files);
317                                 COMPARE_STRING(tctx, cur->info4, ref->info6, monitor_name);
318                                 COMPARE_STRING(tctx, cur->info4, ref->info6, default_datatype);
319                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, previous_names);
320                                 break;
321                         case 5:
322                                 COMPARE_UINT32(tctx, cur->info5, ref->info6, version);
323                                 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_name);
324                                 COMPARE_STRING(tctx, cur->info5, ref->info6, architecture);
325                                 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_path);
326                                 COMPARE_STRING(tctx, cur->info5, ref->info6, data_file);
327                                 COMPARE_STRING(tctx, cur->info5, ref->info6, config_file);
328                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_attributes);*/
329                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, config_version);*/
330                                 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_version); */
331                                 break;
332                         case 6:
333                                 /* level 6 is our reference, and it makes no sense to compare it to itself */
334                                 break;
335                         }
336                 }
337         }
338
339         return true;
340 }
341
342 static bool test_EnumMonitors(struct torture_context *tctx, 
343                               struct dcerpc_pipe *p, 
344                               struct test_spoolss_context *ctx)
345 {
346         NTSTATUS status;
347         struct spoolss_EnumMonitors r;
348         uint16_t levels[] = { 1, 2 };
349         int i, j;
350
351         for (i=0;i<ARRAY_SIZE(levels);i++) {
352                 int level = levels[i];
353                 DATA_BLOB blob;
354
355                 r.in.servername = "";
356                 r.in.level = level;
357                 r.in.buffer = NULL;
358                 r.in.offered = 0;
359
360                 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
361
362                 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
363                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
364                 if (W_ERROR_IS_OK(r.out.result)) {
365                         /* TODO: do some more checks here */
366                         continue;
367                 }
368                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER, 
369                         "EnumMonitors failed");
370
371                 blob = data_blob_talloc(ctx, NULL, r.out.needed);
372                 data_blob_clear(&blob);
373                 r.in.buffer = &blob;
374                 r.in.offered = r.out.needed;
375
376                 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
377                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
378
379                 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
380
381                 ctx->monitor_count[level]       = r.out.count;
382                 ctx->monitors[level]            = r.out.info;
383         }
384
385         for (i=1;i<ARRAY_SIZE(levels);i++) {
386                 int level = levels[i];
387                 int old_level = levels[i-1];
388                 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level], 
389                                          "EnumMonitors invalid value");
390         }
391
392         for (i=0;i<ARRAY_SIZE(levels);i++) {
393                 int level = levels[i];
394                 for (j=0;j<ctx->monitor_count[level];j++) {
395                         union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
396                         union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
397                         switch (level) {
398                         case 1:
399                                 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
400                                 break;
401                         case 2:
402                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
403                                 break;
404                         }
405                 }
406         }
407
408         return true;
409 }
410
411 static bool test_EnumPrintProcessors(struct torture_context *tctx, 
412                                      struct dcerpc_pipe *p,
413                                      struct test_spoolss_context *ctx)
414 {
415         NTSTATUS status;
416         struct spoolss_EnumPrintProcessors r;
417         uint16_t levels[] = { 1 };
418         int i, j;
419
420         for (i=0;i<ARRAY_SIZE(levels);i++) {
421                 int level = levels[i];
422                 DATA_BLOB blob;
423
424                 r.in.servername = "";
425                 r.in.environment = "Windows NT x86";
426                 r.in.level = level;
427                 r.in.buffer = NULL;
428                 r.in.offered = 0;
429
430                 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
431
432                 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
433                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
434                 if (W_ERROR_IS_OK(r.out.result)) {
435                         /* TODO: do some more checks here */
436                         continue;
437                 }
438                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER, 
439                         "EnumPrintProcessors unexpected return code");
440
441                 blob = data_blob_talloc(ctx, NULL, r.out.needed);
442                 data_blob_clear(&blob);
443                 r.in.buffer = &blob;
444                 r.in.offered = r.out.needed;
445
446                 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
447                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
448
449                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
450
451                 ctx->print_processor_count[level]       = r.out.count;
452                 ctx->print_processors[level]            = r.out.info;
453         }
454
455         for (i=1;i<ARRAY_SIZE(levels);i++) {
456                 int level = levels[i];
457                 int old_level = levels[i-1];
458                 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
459                         "EnumPrintProcessors failed");
460         }
461
462         for (i=0;i<ARRAY_SIZE(levels);i++) {
463                 int level = levels[i];
464                 for (j=0;j<ctx->print_processor_count[level];j++) {
465 #if 0
466                         union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
467                         union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
468 #endif
469                         switch (level) {
470                         case 1:
471                                 /* level 1 is our reference, and it makes no sense to compare it to itself */
472                                 break;
473                         }
474                 }
475         }
476
477         return true;
478 }
479
480 static bool test_EnumPrinters(struct torture_context *tctx, 
481                               struct dcerpc_pipe *p,
482                               struct test_spoolss_context *ctx)
483 {
484         struct spoolss_EnumPrinters r;
485         NTSTATUS status;
486         uint16_t levels[] = { 0, 1, 2, 4, 5 };
487         int i, j;
488
489         for (i=0;i<ARRAY_SIZE(levels);i++) {
490                 int level = levels[i];
491                 DATA_BLOB blob;
492
493                 r.in.flags      = PRINTER_ENUM_LOCAL;
494                 r.in.server     = "";
495                 r.in.level      = level;
496                 r.in.buffer     = NULL;
497                 r.in.offered    = 0;
498
499                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
500
501                 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
502                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
503                 if (W_ERROR_IS_OK(r.out.result)) {
504                         /* TODO: do some more checks here */
505                         continue;
506                 }
507                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER, 
508                         "EnumPrinters unexpected return code");
509
510                 blob = data_blob_talloc(ctx, NULL, r.out.needed);
511                 data_blob_clear(&blob);
512                 r.in.buffer = &blob;
513                 r.in.offered = r.out.needed;
514
515                 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
516                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
517
518                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
519
520                 ctx->printer_count[level]       = r.out.count;
521                 ctx->printers[level]            = r.out.info;
522         }
523
524         for (i=1;i<ARRAY_SIZE(levels);i++) {
525                 int level = levels[i];
526                 int old_level = levels[i-1];
527                 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
528                                          "EnumPrinters invalid value");
529         }
530
531         for (i=0;i<ARRAY_SIZE(levels);i++) {
532                 int level = levels[i];
533                 for (j=0;j<ctx->printer_count[level];j++) {
534                         union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
535                         union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
536                         switch (level) {
537                         case 0:
538                                 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
539                                 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
540                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
541                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
542                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
543                                 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);                
544                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
545                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
546                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
547                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
548                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
549                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
550                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
551                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
552                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
553                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
554                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
555                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
556                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
557                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
558                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
559                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
560                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
561                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
562                                 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
563                                 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
564                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
565                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
566                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
567                                 break;
568                         case 1:
569                                 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
570                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
571                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
572                                 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
573                                 break;
574                         case 2:
575                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
576                                 break;
577                         case 4:
578                                 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
579                                 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
580                                 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
581                                 break;
582                         case 5:
583                                 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
584                                 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
585                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
586                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
587                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
588                                 break;
589                         }
590                 }
591         }
592
593         /* TODO:
594          *      - verify that the port of a printer was in the list returned by EnumPorts
595          */
596
597         return true;
598 }
599
600 static bool test_GetPrinter(struct torture_context *tctx, 
601                             struct dcerpc_pipe *p, 
602                      struct policy_handle *handle)
603 {
604         NTSTATUS status;
605         struct spoolss_GetPrinter r;
606         uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
607         int i;
608         
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
892         r.in.handle = handle;
893         r.in.job_id = job_id;
894         r.in.level = 1;
895         r.in.buffer = NULL;
896         r.in.offered = 0;
897
898         torture_comment(tctx, "Testing GetJob\n");
899
900         status = dcerpc_spoolss_GetJob(p, tctx, &r);
901         torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
902
903         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
904                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, r.out.needed);
905                 data_blob_clear(&blob);
906                 r.in.buffer = &blob;
907                 r.in.offered = r.out.needed;
908
909                 status = dcerpc_spoolss_GetJob(p, tctx, &r);
910
911                 torture_assert(tctx, r.out.info, "No job info returned");
912         }
913
914         return true;
915 }
916
917 static bool test_SetJob(struct torture_context *tctx, 
918                         struct dcerpc_pipe *p, 
919                         struct policy_handle *handle, uint32_t job_id, 
920                         enum spoolss_JobControl command)
921 {
922         NTSTATUS status;
923         struct spoolss_SetJob r;
924
925         r.in.handle     = handle;
926         r.in.job_id     = job_id;
927         r.in.ctr        = NULL;
928         r.in.command    = command;
929
930         torture_comment(tctx, "Testing SetJob\n");
931
932         status = dcerpc_spoolss_SetJob(p, tctx, &r);
933         torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
934         torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
935
936         return true;
937 }
938
939 static bool test_EnumJobs(struct torture_context *tctx, 
940                           struct dcerpc_pipe *p, 
941                           struct policy_handle *handle)
942 {
943         NTSTATUS status;
944         struct spoolss_EnumJobs r;
945
946         r.in.handle = handle;
947         r.in.firstjob = 0;
948         r.in.numjobs = 0xffffffff;
949         r.in.level = 1;
950         r.in.buffer = NULL;
951         r.in.offered = 0;
952
953         torture_comment(tctx, "Testing EnumJobs\n");
954
955         status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
956
957         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
958
959         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
960                 union spoolss_JobInfo *info;
961                 int j;
962                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, r.out.needed);
963                 data_blob_clear(&blob);
964                 r.in.buffer = &blob;
965                 r.in.offered = r.out.needed;
966
967                 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
968
969                 torture_assert(tctx, r.out.info, "No jobs returned");
970
971                 info = r.out.info;
972
973                 for (j = 0; j < r.out.count; j++) {
974                         test_GetJob(tctx, p, handle, info[j].info1.job_id);
975                         test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
976                         test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
977                 }
978
979         } else {
980                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
981         }
982
983         return true;
984 }
985
986 static bool test_DoPrintTest(struct torture_context *tctx, 
987                              struct dcerpc_pipe *p, 
988                              struct policy_handle *handle)
989 {
990         bool ret = true;
991         NTSTATUS status;
992         struct spoolss_StartDocPrinter s;
993         struct spoolss_DocumentInfo1 info1;
994         struct spoolss_StartPagePrinter sp;
995         struct spoolss_WritePrinter w;
996         struct spoolss_EndPagePrinter ep;
997         struct spoolss_EndDocPrinter e;
998         int i;
999         uint32_t job_id;
1000
1001         torture_comment(tctx, "Testing StartDocPrinter\n");
1002
1003         s.in.handle             = handle;
1004         s.in.level              = 1;
1005         s.in.info.info1         = &info1;
1006         info1.document_name     = "TorturePrintJob";
1007         info1.output_file       = NULL;
1008         info1.datatype          = "RAW";
1009
1010         status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
1011         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
1012         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
1013
1014         job_id = s.out.job_id;
1015
1016         for (i=1; i < 4; i++) {
1017                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
1018
1019                 sp.in.handle            = handle;
1020
1021                 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
1022                 torture_assert_ntstatus_ok(tctx, status, 
1023                                            "dcerpc_spoolss_StartPagePrinter failed");
1024                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
1025
1026                 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
1027
1028                 w.in.handle             = handle;
1029                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
1030
1031                 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
1032                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
1033                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
1034
1035                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
1036
1037                 ep.in.handle            = handle;
1038
1039                 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
1040                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
1041                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
1042         }
1043
1044         torture_comment(tctx, "Testing EndDocPrinter\n");
1045
1046         e.in.handle = handle;
1047
1048         status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
1049         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
1050         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
1051
1052         ret &= test_EnumJobs(tctx, p, handle);
1053
1054         ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
1055
1056         return ret;
1057 }
1058
1059 static bool test_PausePrinter(struct torture_context *tctx, 
1060                               struct dcerpc_pipe *p, 
1061                               struct policy_handle *handle)
1062 {
1063         NTSTATUS status;
1064         struct spoolss_SetPrinter r;
1065
1066         r.in.handle             = handle;
1067         r.in.level              = 0;
1068         r.in.info.info1         = NULL;
1069         r.in.devmode_ctr.devmode= NULL;
1070         r.in.secdesc_ctr.sd     = NULL;
1071         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
1072
1073         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1074
1075         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1076
1077         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1078
1079         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1080
1081         return true;
1082 }
1083
1084 static bool test_ResumePrinter(struct torture_context *tctx, 
1085                                struct dcerpc_pipe *p, 
1086                                struct policy_handle *handle)
1087 {
1088         NTSTATUS status;
1089         struct spoolss_SetPrinter r;
1090
1091         r.in.handle             = handle;
1092         r.in.level              = 0;
1093         r.in.info.info1         = NULL;
1094         r.in.devmode_ctr.devmode= NULL;
1095         r.in.secdesc_ctr.sd     = NULL;
1096         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
1097
1098         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
1099
1100         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1101
1102         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1103
1104         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1105
1106         return true;
1107 }
1108
1109 static bool test_GetPrinterData(struct torture_context *tctx, 
1110                                 struct dcerpc_pipe *p, 
1111                                 struct policy_handle *handle, 
1112                                 const char *value_name)
1113 {
1114         NTSTATUS status;
1115         struct spoolss_GetPrinterData r;
1116
1117         r.in.handle = handle;
1118         r.in.value_name = value_name;
1119         r.in.offered = 0;
1120
1121         torture_comment(tctx, "Testing GetPrinterData\n");
1122
1123         status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
1124         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
1125
1126         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1127                 r.in.offered = r.out.needed;
1128
1129                 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
1130                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
1131
1132                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterData failed");
1133         }
1134
1135         return true;
1136 }
1137
1138 static bool test_GetPrinterDataEx(struct torture_context *tctx, 
1139                                   struct dcerpc_pipe *p, 
1140                                   struct policy_handle *handle, 
1141                                   const char *key_name,
1142                                   const char *value_name)
1143 {
1144         NTSTATUS status;
1145         struct spoolss_GetPrinterDataEx r;
1146
1147         r.in.handle = handle;
1148         r.in.key_name = key_name;
1149         r.in.value_name = value_name;
1150         r.in.offered = 0;
1151
1152         torture_comment(tctx, "Testing GetPrinterDataEx\n");
1153
1154         status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
1155         if (!NT_STATUS_IS_OK(status)) {
1156                 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
1157                     p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1158                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
1159                 }
1160                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
1161         }
1162
1163         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1164                 r.in.offered = r.out.needed;
1165
1166                 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
1167                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
1168
1169                 torture_assert_werr_ok(tctx, r.out.result,  "GetPrinterDataEx failed");
1170         }
1171
1172         return true;
1173 }
1174
1175 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p, 
1176                                  struct policy_handle *handle)
1177 {
1178         NTSTATUS status;
1179         struct spoolss_EnumPrinterData r;
1180
1181         ZERO_STRUCT(r);
1182         r.in.handle = handle;
1183         r.in.enum_index = 0;
1184
1185         do {
1186                 uint32_t value_size = 0;
1187                 uint32_t data_size = 0;
1188                 uint32_t printerdata_type = 0;
1189                 DATA_BLOB data = data_blob(NULL,0);
1190
1191                 r.in.value_offered = value_size;
1192                 r.out.value_needed = &value_size;
1193                 r.in.data_offered = data_size;
1194                 r.out.data_needed = &data_size;
1195
1196                 r.out.printerdata_type = &printerdata_type;
1197                 r.out.buffer = &data;
1198
1199                 torture_comment(tctx, "Testing EnumPrinterData\n");
1200
1201                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
1202
1203                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
1204
1205                 r.in.value_offered = value_size;
1206                 r.in.data_offered = data_size;
1207
1208                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
1209
1210                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
1211                 
1212                 test_GetPrinterData(tctx, p, handle, r.out.value_name);
1213
1214                 test_GetPrinterDataEx(tctx, 
1215                         p, handle, "PrinterDriverData", 
1216                         r.out.value_name);
1217
1218                 r.in.enum_index++;
1219
1220         } while (W_ERROR_IS_OK(r.out.result));
1221
1222         return true;
1223 }
1224
1225 static bool test_EnumPrinterDataEx(struct torture_context *tctx, 
1226                                    struct dcerpc_pipe *p, 
1227                                    struct policy_handle *handle)
1228 {
1229         NTSTATUS status;
1230         struct spoolss_EnumPrinterDataEx r;
1231
1232         r.in.handle = handle;
1233         r.in.key_name = "PrinterDriverData";
1234         r.in.offered = 0;
1235
1236         torture_comment(tctx, "Testing EnumPrinterDataEx\n");
1237
1238         status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
1239         torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
1240
1241         r.in.offered = r.out.needed;
1242
1243         status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
1244
1245         torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
1246
1247         return true;
1248 }
1249
1250
1251 static bool test_DeletePrinterData(struct torture_context *tctx, 
1252                                    struct dcerpc_pipe *p, 
1253                                    struct policy_handle *handle, 
1254                                    const char *value_name)
1255 {
1256         NTSTATUS status;
1257         struct spoolss_DeletePrinterData r;
1258
1259         r.in.handle = handle;
1260         r.in.value_name = value_name;
1261
1262         torture_comment(tctx, "Testing DeletePrinterData\n");
1263
1264         status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
1265
1266         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
1267
1268         return true;
1269 }
1270
1271 static bool test_SetPrinterData(struct torture_context *tctx, 
1272                                 struct dcerpc_pipe *p, 
1273                                 struct policy_handle *handle)
1274 {
1275         NTSTATUS status;
1276         struct spoolss_SetPrinterData r;
1277         const char *value_name = "spottyfoot";
1278         
1279         r.in.handle = handle;
1280         r.in.value_name = value_name;
1281         r.in.type = SPOOLSS_PRINTER_DATA_TYPE_STRING;
1282         r.in.data.string = "dog";
1283
1284         torture_comment(tctx, "Testing SetPrinterData\n");
1285
1286         status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
1287
1288         torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
1289
1290         if (!test_GetPrinterData(tctx, p, handle, value_name)) {
1291                 return false;
1292         }
1293
1294         if (!test_DeletePrinterData(tctx, p, handle, value_name)) {
1295                 return false;
1296         }
1297
1298         return true;
1299 }
1300
1301 static bool test_SecondaryClosePrinter(struct torture_context *tctx, 
1302                                        struct dcerpc_pipe *p, 
1303                                        struct policy_handle *handle)
1304 {
1305         NTSTATUS status;
1306         struct dcerpc_binding *b;
1307         struct dcerpc_pipe *p2;
1308         struct spoolss_ClosePrinter cp;
1309
1310         /* only makes sense on SMB */
1311         if (p->conn->transport.transport != NCACN_NP) {
1312                 return true;
1313         }
1314
1315         torture_comment(tctx, "testing close on secondary pipe\n");
1316
1317         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
1318         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
1319
1320         status = dcerpc_secondary_connection(p, &p2, b);
1321         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
1322
1323         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
1324         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
1325
1326         cp.in.handle = handle;
1327         cp.out.handle = handle;
1328
1329         status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
1330         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
1331                         "ERROR: Allowed close on secondary connection");
1332
1333         torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, 
1334                                  "Unexpected fault code");
1335
1336         talloc_free(p2);
1337
1338         return true;
1339 }
1340
1341 static bool test_OpenPrinter_badname(struct torture_context *tctx, 
1342                                      struct dcerpc_pipe *p, const char *name)
1343 {
1344         NTSTATUS status;
1345         struct spoolss_OpenPrinter op;
1346         struct spoolss_OpenPrinterEx opEx;
1347         struct policy_handle handle;
1348         bool ret = true;
1349
1350         op.in.printername       = name;
1351         op.in.datatype          = NULL;
1352         op.in.devmode_ctr.devmode= NULL;
1353         op.in.access_mask       = 0;
1354         op.out.handle           = &handle;
1355
1356         torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
1357
1358         status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
1359         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
1360         if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
1361                 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
1362                         name, win_errstr(op.out.result));
1363         }
1364
1365         if (W_ERROR_IS_OK(op.out.result)) {
1366                 ret &=test_ClosePrinter(tctx, p, &handle);
1367         }
1368
1369         opEx.in.printername             = name;
1370         opEx.in.datatype                = NULL;
1371         opEx.in.devmode_ctr.devmode     = NULL;
1372         opEx.in.access_mask             = 0;
1373         opEx.in.level                   = 1;
1374         opEx.in.userlevel.level1        = NULL;
1375         opEx.out.handle                 = &handle;
1376
1377         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
1378
1379         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
1380         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
1381         if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
1382                 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
1383                         name, win_errstr(opEx.out.result));
1384         }
1385
1386         if (W_ERROR_IS_OK(opEx.out.result)) {
1387                 ret &=test_ClosePrinter(tctx, p, &handle);
1388         }
1389
1390         return ret;
1391 }
1392
1393 static bool test_OpenPrinter(struct torture_context *tctx, 
1394                              struct dcerpc_pipe *p, 
1395                              const char *name)
1396 {
1397         NTSTATUS status;
1398         struct spoolss_OpenPrinter r;
1399         struct policy_handle handle;
1400         bool ret = true;
1401
1402         r.in.printername        = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
1403         r.in.datatype           = NULL;
1404         r.in.devmode_ctr.devmode= NULL;
1405         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
1406         r.out.handle            = &handle;
1407
1408         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
1409
1410         status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
1411
1412         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
1413
1414         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
1415
1416         if (!test_GetPrinter(tctx, p, &handle)) {
1417                 ret = false;
1418         }
1419
1420         if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
1421                 ret = false;
1422         }
1423
1424         if (!test_ClosePrinter(tctx, p, &handle)) {
1425                 ret = false;
1426         }
1427
1428         return ret;
1429 }
1430
1431 static bool call_OpenPrinterEx(struct torture_context *tctx, 
1432                                struct dcerpc_pipe *p, 
1433                                const char *name, struct policy_handle *handle)
1434 {
1435         struct spoolss_OpenPrinterEx r;
1436         struct spoolss_UserLevel1 userlevel1;
1437         NTSTATUS status;
1438
1439         if (name && name[0]) {
1440                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", 
1441                                                    dcerpc_server_name(p), name);
1442         } else {
1443                 r.in.printername = talloc_asprintf(tctx, "\\\\%s", 
1444                                                    dcerpc_server_name(p));
1445         }
1446
1447         r.in.datatype           = NULL;
1448         r.in.devmode_ctr.devmode= NULL;
1449         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
1450         r.in.level              = 1;
1451         r.in.userlevel.level1   = &userlevel1;
1452         r.out.handle = handle;
1453
1454         userlevel1.size = 1234;
1455         userlevel1.client = "hello";
1456         userlevel1.user = "spottyfoot!";
1457         userlevel1.build = 1;
1458         userlevel1.major = 2;
1459         userlevel1.minor = 3;
1460         userlevel1.processor = 4;
1461
1462         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
1463
1464         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
1465
1466         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
1467         
1468         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
1469
1470         return true;
1471 }
1472
1473 static bool test_OpenPrinterEx(struct torture_context *tctx, 
1474                                struct dcerpc_pipe *p, 
1475                                const char *name)
1476 {
1477         struct policy_handle handle;
1478         bool ret = true;
1479
1480         if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
1481                 return false;
1482         }
1483
1484         if (!test_GetPrinter(tctx, p, &handle)) {
1485                 ret = false;
1486         }
1487
1488         if (!test_EnumForms(tctx, p, &handle, false)) {
1489                 ret = false;
1490         }
1491
1492         if (!test_AddForm(tctx, p, &handle, false)) {
1493                 ret = false;
1494         }
1495
1496         if (!test_EnumPrinterData(tctx, p, &handle)) {
1497                 ret = false;
1498         }
1499
1500         if (!test_EnumPrinterDataEx(tctx, p, &handle)) {
1501                 ret = false;
1502         }
1503
1504         if (!test_PausePrinter(tctx, p, &handle)) {
1505                 ret = false;
1506         }
1507
1508         if (!test_DoPrintTest(tctx, p, &handle)) {
1509                 ret = false;
1510         }
1511
1512         if (!test_ResumePrinter(tctx, p, &handle)) {
1513                 ret = false;
1514         }
1515
1516         if (!test_SetPrinterData(tctx, p, &handle)) {
1517                 ret = false;
1518         }
1519
1520         if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
1521                 ret = false;
1522         }
1523
1524         if (!test_ClosePrinter(tctx, p, &handle)) {
1525                 ret = false;
1526         }
1527         
1528         return ret;
1529 }
1530
1531 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
1532 {
1533         struct spoolss_EnumPrinters r;
1534         NTSTATUS status;
1535         uint16_t levels[] = {1, 2, 4, 5};
1536         int i;
1537         bool ret = true;
1538
1539         for (i=0;i<ARRAY_SIZE(levels);i++) {
1540                 union spoolss_PrinterInfo *info;
1541                 int j;
1542
1543                 r.in.flags      = PRINTER_ENUM_LOCAL;
1544                 r.in.server     = "";
1545                 r.in.level      = levels[i];
1546                 r.in.buffer     = NULL;
1547                 r.in.offered    = 0;
1548
1549                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1550
1551                 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
1552                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
1553
1554                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1555                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, r.out.needed);
1556                         data_blob_clear(&blob);
1557                         r.in.buffer = &blob;
1558                         r.in.offered = r.out.needed;
1559                         status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
1560                 }
1561
1562                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
1563
1564                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1565
1566                 if (!r.out.info) {
1567                         torture_comment(tctx, "No printers returned\n");
1568                         return true;
1569                 }
1570
1571                 info = r.out.info;
1572
1573                 for (j=0;j<r.out.count;j++) {
1574                         if (r.in.level == 1) {
1575                                 /* the names appear to be comma-separated name lists? */
1576                                 char *name = talloc_strdup(tctx, info[j].info1.name);
1577                                 char *comma = strchr(name, ',');
1578                                 if (comma) *comma = 0;
1579                                 if (!test_OpenPrinter(tctx, p, name)) {
1580                                         ret = false;
1581                                 }
1582                                 if (!test_OpenPrinterEx(tctx, p, name)) {
1583                                         ret = false;
1584                                 }
1585                         }
1586                 }
1587         }
1588
1589         return ret;
1590 }
1591
1592 #if 0
1593 static bool test_GetPrinterDriver2(struct dcerpc_pipe *p, 
1594                                    struct policy_handle *handle, 
1595                                    const char *driver_name)
1596 {
1597         NTSTATUS status;
1598         struct spoolss_GetPrinterDriver2 r;
1599
1600         r.in.handle = handle;
1601         r.in.architecture = "W32X86";
1602         r.in.level = 1;
1603         r.in.buffer = NULL;
1604         r.in.offered = 0;
1605         r.in.client_major_version = 0;
1606         r.in.client_minor_version = 0;
1607
1608         printf("Testing GetPrinterDriver2\n");
1609
1610         status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
1611         if (!NT_STATUS_IS_OK(status)) {
1612                 printf("GetPrinterDriver2 failed - %s\n", nt_errstr(status));
1613                 return false;
1614         }
1615
1616         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1617                 r.in.offered = r.out.needed;
1618                 status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
1619         }
1620                 
1621         if (!NT_STATUS_IS_OK(status)) {
1622                 printf("GetPrinterDriver2 failed - %s\n", 
1623                        nt_errstr(status));
1624                 return false;
1625         }
1626
1627         if (!W_ERROR_IS_OK(r.out.result)) {
1628                 printf("GetPrinterDriver2 failed - %s\n", 
1629                        win_errstr(r.out.result));
1630                 return false;
1631         }
1632
1633         return true;
1634 }
1635 #endif
1636
1637 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx, 
1638                                         struct dcerpc_pipe *p)
1639 {
1640         struct spoolss_EnumPrinterDrivers r;
1641         NTSTATUS status;
1642         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
1643         int i;
1644
1645         for (i=0;i<ARRAY_SIZE(levels);i++) {
1646
1647                 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1648                 r.in.environment = "Windows NT x86";
1649                 r.in.level = levels[i];
1650                 r.in.buffer = NULL;
1651                 r.in.offered = 0;
1652
1653                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
1654
1655                 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
1656
1657                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
1658
1659                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1660                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, r.out.needed);
1661                         data_blob_clear(&blob);
1662                         r.in.buffer = &blob;
1663                         r.in.offered = r.out.needed;
1664                         status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
1665                 }
1666
1667                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
1668
1669                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
1670
1671                 if (!r.out.info) {
1672                         torture_comment(tctx, "No printer drivers returned\n");
1673                         break;
1674                 }
1675         }
1676
1677         return true;
1678 }
1679
1680 /** Test that makes sure that calling ReplyOpenPrinter()
1681  * on Samba 4 will cause an irpc broadcast call.
1682  */
1683 static bool test_ReplyOpenPrinter(struct torture_context *tctx, 
1684                                   struct dcerpc_pipe *pipe)
1685 {
1686         struct spoolss_ReplyOpenPrinter r;
1687         struct spoolss_ReplyClosePrinter s;
1688         struct policy_handle h;
1689
1690         r.in.server_name = "earth";
1691         r.in.printer_local = 2;
1692         r.in.type = REG_DWORD;
1693         r.in.unknown1 = 0;
1694         r.in.unknown2 = 0;
1695         r.out.handle = &h;
1696
1697         torture_assert_ntstatus_ok(tctx, 
1698                         dcerpc_spoolss_ReplyOpenPrinter(pipe, tctx, &r),
1699                         "spoolss_ReplyOpenPrinter call failed");
1700
1701         torture_assert_werr_ok(tctx, r.out.result, "error return code");
1702
1703         s.in.handle = &h;
1704         s.out.handle = &h;
1705
1706         torture_assert_ntstatus_ok(tctx,
1707                         dcerpc_spoolss_ReplyClosePrinter(pipe, tctx, &s),
1708                         "spoolss_ReplyClosePrinter call failed");
1709
1710         torture_assert_werr_ok(tctx, r.out.result, "error return code");
1711
1712         return true;
1713 }
1714
1715 bool torture_rpc_spoolss(struct torture_context *torture)
1716 {
1717         NTSTATUS status;
1718         struct dcerpc_pipe *p;
1719         bool ret = true;
1720         struct test_spoolss_context *ctx;
1721
1722         status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
1723         if (!NT_STATUS_IS_OK(status)) {
1724                 return false;
1725         }
1726
1727         ctx = talloc_zero(torture, struct test_spoolss_context);
1728
1729         ret &= test_OpenPrinter_server(torture, p, ctx);
1730
1731         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "W3SvcInstalled");
1732         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "BeepEnabled");
1733         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "EventLog");
1734         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopup");
1735         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopupToComputer");
1736         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MajorVersion");
1737         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MinorVersion");
1738         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DefaultSpoolDirectory");
1739         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "Architecture");
1740         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DsPresent");
1741         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersion");
1742         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersionEx");
1743         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DNSMachineName");
1744         ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
1745         ret &= test_AddForm(torture, p, &ctx->server_handle, true);
1746         ret &= test_EnumPorts(torture, p, ctx);
1747         ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
1748         ret &= test_EnumPrinterDrivers(torture, p, ctx);
1749         ret &= test_EnumMonitors(torture, p, ctx);
1750         ret &= test_EnumPrintProcessors(torture, p, ctx);
1751         ret &= test_EnumPrinters(torture, p, ctx);
1752         ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
1753         ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
1754         ret &= test_OpenPrinter_badname(torture, p, "");
1755         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
1756         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
1757         ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
1758         ret &= test_OpenPrinter_badname(torture, p, 
1759                                         talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
1760
1761
1762         ret &= test_AddPort(torture, p);
1763         ret &= test_EnumPorts_old(torture, p);
1764         ret &= test_EnumPrinters_old(torture, p);
1765         ret &= test_EnumPrinterDrivers_old(torture, p);
1766         ret &= test_ReplyOpenPrinter(torture, p);
1767
1768         return ret;
1769 }