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