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