r23792: convert Samba4 to GPLv3
[sfrench/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    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "torture/torture.h"
24 #include "torture/rpc/rpc.h"
25 #include "librpc/gen_ndr/ndr_spoolss_c.h"
26
27 struct test_spoolss_context {
28         struct dcerpc_pipe *p;
29
30         /* print server handle */
31         struct policy_handle server_handle;
32
33         /* for EnumPorts */
34         uint32_t port_count[3];
35         union spoolss_PortInfo *ports[3];
36
37         /* for EnumPrinterDrivers */
38         uint32_t driver_count[7];
39         union spoolss_DriverInfo *drivers[7];
40
41         /* for EnumMonitors */
42         uint32_t monitor_count[3];
43         union spoolss_MonitorInfo *monitors[3];
44
45         /* for EnumPrintProcessors */
46         uint32_t print_processor_count[2];
47         union spoolss_PrintProcessorInfo *print_processors[2];
48
49         /* for EnumPrinters */
50         uint32_t printer_count[6];
51         union spoolss_PrinterInfo *printers[6];
52 };
53
54 #define COMPARE_STRING(c,r,e) do {\
55         BOOL _ok = True;\
56         if (c.e && !r.e) _ok = False;\
57         if (!c.e && r.e) _ok = False;\
58         if (c.e && r.e && strcmp_safe(c.e, r.e) != 0) _ok = False;\
59         if (!_ok){\
60                 printf("%s: " #c "." #e " [%s] doesn't match " #r "." #e " [%s]\n",\
61                         __location__, c.e, r.e);\
62                 ret = False;\
63         }\
64 } while(0)
65
66 /* not every compiler supports __typeof__() */
67 #if (__GNUC__ >= 3)
68 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
69         if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
70                 printf(__location__ ":" #c "." #e "field is not " #type "\n"); \
71                 smb_panic(__location__ ":" #c "." #e "field is not " #type ); \
72                 ret = False; \
73         }\
74         if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
75                 printf(__location__ ":" #r "." #e "field is not " #type "\n"); \
76                 smb_panic(__location__ ":" #r "." #e "field is not " #type ); \
77                 ret = False; \
78         }\
79 } while(0)
80 #else
81 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
82 #endif
83
84 #if 0 /* unused */
85 #define COMPARE_UINT16(c,r,e) do {\
86         _CHECK_FIELD_SIZE(c,r,e,uint16_t); \
87         if (c.e != r.e){\
88                 printf("%s: " #c "." #e "  0x%04X (%u) doesn't match " #r "." #e " 0x%04X (%u)\n",\
89                         __location__, c.e, c.e, r.e, r.e);\
90                 ret = False;\
91         }\
92 } while(0)
93 #endif
94
95 #define COMPARE_UINT32(c,r,e) do {\
96         _CHECK_FIELD_SIZE(c,r,e,uint32_t); \
97         if (c.e != r.e){\
98                 printf("%s: " #c "." #e "  0x%08X (%u) doesn't match " #r "." #e " 0x%08X (%u)\n",\
99                         __location__, c.e, c.e, r.e, r.e);\
100                 ret = False;\
101         }\
102 } while(0)
103
104 #if 0 /* unused */
105 #define COMPARE_UINT64(c,r,e) do {\
106         _CHECK_FIELD_SIZE(c,r,e,uint64_t); \
107         if (c.e != r.e){\
108                 printf("%s: " #c "." #e "  0x%016llX (%llu) doesn't match " #r "." #e " 0x%016llX (%llu)\n",\
109                         __location__, c.e, c.e, r.e, r.e);\
110                 ret = False;\
111         }\
112 } while(0)
113 #endif
114
115 /* TODO: ! */
116 #if 0 /* unused */
117 #define COMPARE_SEC_DESC(c,r,e)
118 #define COMPARE_SPOOLSS_TIME(c,r,e)
119 #endif
120 #define COMPARE_STRING_ARRAY(c,r,e)
121
122 static BOOL test_OpenPrinter_server(struct test_spoolss_context *ctx)
123 {
124         NTSTATUS status;
125         struct spoolss_OpenPrinter op;
126         BOOL ret = True;
127
128         op.in.printername       = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(ctx->p));
129         op.in.datatype          = NULL;
130         op.in.devmode_ctr.devmode= NULL;
131         op.in.access_mask       = 0;
132         op.out.handle           = &ctx->server_handle;
133
134         printf("\nTesting OpenPrinter(%s)\n", op.in.printername);
135
136         status = dcerpc_spoolss_OpenPrinter(ctx->p, ctx, &op);
137         if (!NT_STATUS_IS_OK(status)) {
138                 printf("dcerpc_spoolss_OpenPrinter failed - %s\n", nt_errstr(status));
139                 ret = False;
140         }
141         if (!W_ERROR_IS_OK(op.out.result)) {
142                 printf("OpenPrinter(%s) failed - %s\n",
143                         op.in.printername, win_errstr(op.out.result));
144                 ret = False;
145         }
146
147         return ret;
148 }
149
150 static BOOL test_EnumPorts(struct test_spoolss_context *ctx)
151 {
152         NTSTATUS status;
153         struct spoolss_EnumPorts r;
154         uint16_t levels[] = { 1, 2 };
155         int i, j;
156         BOOL ret = True;
157
158         for (i=0;i<ARRAY_SIZE(levels);i++) {
159                 int level = levels[i];
160                 DATA_BLOB blob;
161
162                 r.in.servername = "";
163                 r.in.level = level;
164                 r.in.buffer = NULL;
165                 r.in.offered = 0;
166
167                 printf("Testing EnumPorts level %u\n", r.in.level);
168
169                 status = dcerpc_spoolss_EnumPorts(ctx->p, ctx, &r);
170                 if (!NT_STATUS_IS_OK(status)) {
171                         printf("dcerpc_spoolss_EnumPorts failed - %s\n", nt_errstr(status));
172                         ret = False;
173                         continue;
174                 }
175                 if (W_ERROR_IS_OK(r.out.result)) {
176                         /* TODO: do some more checks here */
177                         continue;
178                 }
179                 if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
180                         printf("EnumPorts unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n",
181                                 win_errstr(r.out.result));
182                         ret = False;
183                         continue;
184                 }
185
186                 blob = data_blob_talloc(ctx, NULL, r.out.needed);
187                 data_blob_clear(&blob);
188                 r.in.buffer = &blob;
189                 r.in.offered = r.out.needed;
190
191                 status = dcerpc_spoolss_EnumPorts(ctx->p, ctx, &r);
192                 if (!NT_STATUS_IS_OK(status)) {
193                         printf("dcerpc_spoolss_EnumPorts failed - %s\n", nt_errstr(status));
194                         ret = False;
195                         continue;
196                 }
197
198                 if (!W_ERROR_IS_OK(r.out.result)) {
199                         printf("EnumPorts failed - %s\n",
200                                 win_errstr(r.out.result));
201                         ret = False;
202                         continue;
203                 }
204
205                 ctx->port_count[level]  = r.out.count;
206                 ctx->ports[level]       = r.out.info;
207         }
208
209         for (i=1;i<ARRAY_SIZE(levels);i++) {
210                 int level = levels[i];
211                 int old_level = levels[i-1];
212                 if (ctx->port_count[level] != ctx->port_count[old_level]) {
213                         printf("EnumPorts level[%d] returns [%u] ports, but level[%d] returns [%u]\n",
214                                 level, ctx->port_count[level], old_level, ctx->port_count[old_level]);
215                         ret = False;
216                 }
217         }
218         /* if the array sizes are not the same we would maybe segfault in the following code */
219         if (!ret) return ret;
220
221         for (i=0;i<ARRAY_SIZE(levels);i++) {
222                 int level = levels[i];
223                 for (j=0;j<ctx->port_count[level];j++) {
224                         union spoolss_PortInfo *cur = &ctx->ports[level][j];
225                         union spoolss_PortInfo *ref = &ctx->ports[2][j];
226                         switch (level) {
227                         case 1:
228                                 COMPARE_STRING(cur->info1, ref->info2, port_name);
229                                 break;
230                         case 2:
231                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
232                                 break;
233                         }
234                 }
235         }
236
237         return True;
238 }
239
240 static BOOL test_GetPrinterDriverDirectory(struct test_spoolss_context *ctx)
241 {
242         NTSTATUS status;
243         struct spoolss_GetPrinterDriverDirectory r;
244         struct {
245                 uint16_t level;
246                 const char *server;
247         } levels[] = {{
248                         .level  = 1,
249                         .server = NULL
250                 },{
251                         .level  = 1,
252                         .server = ""
253                 },{
254                         .level  = 78,
255                         .server = ""
256                 },{
257                         .level  = 1,
258                         .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(ctx->p))
259                 },{
260                         .level  = 1024,
261                         .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(ctx->p))
262                 }
263         };
264         int i;
265         BOOL ret = True;
266
267         for (i=0;i<ARRAY_SIZE(levels);i++) {
268                 int level = levels[i].level;
269                 DATA_BLOB blob;
270
271                 r.in.server             = levels[i].server;
272                 r.in.environment        = SPOOLSS_ARCHITECTURE_NT_X86;
273                 r.in.level              = level;
274                 r.in.buffer             = NULL;
275                 r.in.offered            = 0;
276
277                 printf("Testing GetPrinterDriverDirectory level %u\n", r.in.level);
278
279                 status = dcerpc_spoolss_GetPrinterDriverDirectory(ctx->p, ctx, &r);
280                 if (!NT_STATUS_IS_OK(status)) {
281                         printf("dcerpc_spoolss_GetPrinterDriverDirectory failed - %s\n", nt_errstr(status));
282                         ret = False;
283                         continue;
284                 }
285                 if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
286                         printf("GetPrinterDriverDirectory unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n",
287                                 win_errstr(r.out.result));
288                         ret = False;
289                         continue;
290                 }
291
292                 blob = data_blob_talloc(ctx, NULL, r.out.needed);
293                 data_blob_clear(&blob);
294                 r.in.buffer = &blob;
295                 r.in.offered = r.out.needed;
296
297                 status = dcerpc_spoolss_GetPrinterDriverDirectory(ctx->p, ctx, &r);
298                 if (!NT_STATUS_IS_OK(status)) {
299                         printf("dcerpc_spoolss_GetPrinterDriverDirectory failed - %s\n", nt_errstr(status));
300                         ret = False;
301                         continue;
302                 }
303
304                 if (!W_ERROR_IS_OK(r.out.result)) {
305                         printf("GetPrinterDriverDirectory failed - %s\n",
306                                 win_errstr(r.out.result));
307                         ret = False;
308                         continue;
309                 }
310         }
311
312         return True;
313 }
314
315 static BOOL test_EnumPrinterDrivers(struct test_spoolss_context *ctx)
316 {
317         NTSTATUS status;
318         struct spoolss_EnumPrinterDrivers r;
319         uint16_t levels[] = { 1, 2, 3, 4, 5, 6 };
320         int i, j;
321         BOOL ret = True;
322
323         for (i=0;i<ARRAY_SIZE(levels);i++) {
324                 int level = levels[i];
325                 DATA_BLOB blob;
326
327                 r.in.server             = "";
328                 r.in.environment        = SPOOLSS_ARCHITECTURE_NT_X86;
329                 r.in.level              = level;
330                 r.in.buffer             = NULL;
331                 r.in.offered            = 0;
332
333                 printf("Testing EnumPrinterDrivers level %u\n", r.in.level);
334
335                 status = dcerpc_spoolss_EnumPrinterDrivers(ctx->p, ctx, &r);
336                 if (!NT_STATUS_IS_OK(status)) {
337                         printf("dcerpc_spoolss_EnumPrinterDrivers failed - %s\n", nt_errstr(status));
338                         ret = False;
339                         continue;
340                 }
341                 if (W_ERROR_IS_OK(r.out.result)) {
342                         /* TODO: do some more checks here */
343                         continue;
344                 }
345                 if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
346                         printf("EnumPrinterDrivers unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n",
347                                 win_errstr(r.out.result));
348                         ret = False;
349                         continue;
350                 }
351
352                 blob = data_blob_talloc(ctx, NULL, r.out.needed);
353                 data_blob_clear(&blob);
354                 r.in.buffer = &blob;
355                 r.in.offered = r.out.needed;
356
357                 status = dcerpc_spoolss_EnumPrinterDrivers(ctx->p, ctx, &r);
358                 if (!NT_STATUS_IS_OK(status)) {
359                         printf("dcerpc_spoolss_EnumPrinterDrivers failed - %s\n", nt_errstr(status));
360                         ret = False;
361                         continue;
362                 }
363
364                 if (!W_ERROR_IS_OK(r.out.result)) {
365                         printf("EnumPrinterDrivers failed - %s\n",
366                                 win_errstr(r.out.result));
367                         ret = False;
368                         continue;
369                 }
370
371                 ctx->driver_count[level]        = r.out.count;
372                 ctx->drivers[level]             = r.out.info;
373         }
374
375         for (i=1;i<ARRAY_SIZE(levels);i++) {
376                 int level = levels[i];
377                 int old_level = levels[i-1];
378                 if (ctx->driver_count[level] != ctx->driver_count[old_level]) {
379                         printf("EnumPrinterDrivers level[%d] returns [%u] drivers, but level[%d] returns [%u]\n",
380                                 level, ctx->driver_count[level], old_level, ctx->driver_count[old_level]);
381                         ret = False;
382                 }
383         }
384         /* if the array sizes are not the same we would maybe segfault in the following code */
385         if (!ret) return ret;
386
387         for (i=0;i<ARRAY_SIZE(levels);i++) {
388                 int level = levels[i];
389                 for (j=0;j<ctx->driver_count[level];j++) {
390                         union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
391                         union spoolss_DriverInfo *ref = &ctx->drivers[6][j];
392                         switch (level) {
393                         case 1:
394                                 COMPARE_STRING(cur->info1, ref->info6, driver_name);
395                                 break;
396                         case 2:
397                                 COMPARE_UINT32(cur->info2, ref->info6, version);
398                                 COMPARE_STRING(cur->info2, ref->info6, driver_name);
399                                 COMPARE_STRING(cur->info2, ref->info6, architecture);
400                                 COMPARE_STRING(cur->info2, ref->info6, driver_path);
401                                 COMPARE_STRING(cur->info2, ref->info6, data_file);
402                                 COMPARE_STRING(cur->info2, ref->info6, config_file);
403                                 break;
404                         case 3:
405                                 COMPARE_UINT32(cur->info3, ref->info6, version);
406                                 COMPARE_STRING(cur->info3, ref->info6, driver_name);
407                                 COMPARE_STRING(cur->info3, ref->info6, architecture);
408                                 COMPARE_STRING(cur->info3, ref->info6, driver_path);
409                                 COMPARE_STRING(cur->info3, ref->info6, data_file);
410                                 COMPARE_STRING(cur->info3, ref->info6, config_file);
411                                 COMPARE_STRING(cur->info3, ref->info6, help_file);
412                                 COMPARE_STRING_ARRAY(cur->info3, ref->info6, dependent_files);
413                                 COMPARE_STRING(cur->info3, ref->info6, monitor_name);
414                                 COMPARE_STRING(cur->info3, ref->info6, default_datatype);
415                                 break;
416                         case 4:
417                                 COMPARE_UINT32(cur->info4, ref->info6, version);
418                                 COMPARE_STRING(cur->info4, ref->info6, driver_name);
419                                 COMPARE_STRING(cur->info4, ref->info6, architecture);
420                                 COMPARE_STRING(cur->info4, ref->info6, driver_path);
421                                 COMPARE_STRING(cur->info4, ref->info6, data_file);
422                                 COMPARE_STRING(cur->info4, ref->info6, config_file);
423                                 COMPARE_STRING(cur->info4, ref->info6, help_file);
424                                 COMPARE_STRING_ARRAY(cur->info4, ref->info6, dependent_files);
425                                 COMPARE_STRING(cur->info4, ref->info6, monitor_name);
426                                 COMPARE_STRING(cur->info4, ref->info6, default_datatype);
427                                 COMPARE_STRING_ARRAY(cur->info4, ref->info6, previous_names);
428                                 break;
429                         case 5:
430                                 COMPARE_UINT32(cur->info5, ref->info6, version);
431                                 COMPARE_STRING(cur->info5, ref->info6, driver_name);
432                                 COMPARE_STRING(cur->info5, ref->info6, architecture);
433                                 COMPARE_STRING(cur->info5, ref->info6, driver_path);
434                                 COMPARE_STRING(cur->info5, ref->info6, data_file);
435                                 COMPARE_STRING(cur->info5, ref->info6, config_file);
436                                 /*COMPARE_UINT32(cur->info5, ref->info6, driver_attributes);*/
437                                 /*COMPARE_UINT32(cur->info5, ref->info6, config_version);*/
438                                 /*TODO: ! COMPARE_UINT32(cur->info5, ref->info6, driver_version); */
439                                 break;
440                         case 6:
441                                 /* level 6 is our reference, and it makes no sense to compare it to itself */
442                                 break;
443                         }
444                 }
445         }
446
447         return ret;
448 }
449
450 static BOOL test_EnumMonitors(struct test_spoolss_context *ctx)
451 {
452         NTSTATUS status;
453         struct spoolss_EnumMonitors r;
454         uint16_t levels[] = { 1, 2 };
455         int i, j;
456         BOOL ret = True;
457
458         for (i=0;i<ARRAY_SIZE(levels);i++) {
459                 int level = levels[i];
460                 DATA_BLOB blob;
461
462                 r.in.servername = "";
463                 r.in.level = level;
464                 r.in.buffer = NULL;
465                 r.in.offered = 0;
466
467                 printf("Testing EnumMonitors level %u\n", r.in.level);
468
469                 status = dcerpc_spoolss_EnumMonitors(ctx->p, ctx, &r);
470                 if (!NT_STATUS_IS_OK(status)) {
471                         printf("dcerpc_spoolss_EnumMonitors failed - %s\n", nt_errstr(status));
472                         ret = False;
473                         continue;
474                 }
475                 if (W_ERROR_IS_OK(r.out.result)) {
476                         /* TODO: do some more checks here */
477                         continue;
478                 }
479                 if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
480                         printf("EnumMonitors unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n",
481                                 win_errstr(r.out.result));
482                         ret = False;
483                         continue;
484                 }
485
486                 blob = data_blob_talloc(ctx, NULL, r.out.needed);
487                 data_blob_clear(&blob);
488                 r.in.buffer = &blob;
489                 r.in.offered = r.out.needed;
490
491                 status = dcerpc_spoolss_EnumMonitors(ctx->p, ctx, &r);
492                 if (!NT_STATUS_IS_OK(status)) {
493                         printf("dcerpc_spoolss_EnumMonitors failed - %s\n", nt_errstr(status));
494                         ret = False;
495                         continue;
496                 }
497
498                 if (!W_ERROR_IS_OK(r.out.result)) {
499                         printf("EnumMonitors failed - %s\n",
500                                 win_errstr(r.out.result));
501                         ret = False;
502                         continue;
503                 }
504
505                 ctx->monitor_count[level]       = r.out.count;
506                 ctx->monitors[level]            = r.out.info;
507         }
508
509         for (i=1;i<ARRAY_SIZE(levels);i++) {
510                 int level = levels[i];
511                 int old_level = levels[i-1];
512                 if (ctx->monitor_count[level] != ctx->monitor_count[old_level]) {
513                         printf("EnumMonitors level[%d] returns [%u] monitors, but level[%d] returns [%u]\n",
514                                 level, ctx->monitor_count[level], old_level, ctx->monitor_count[old_level]);
515                         ret = False;
516                 }
517         }
518         /* if the array sizes are not the same we would maybe segfault in the following code */
519         if (!ret) return ret;
520
521         for (i=0;i<ARRAY_SIZE(levels);i++) {
522                 int level = levels[i];
523                 for (j=0;j<ctx->monitor_count[level];j++) {
524                         union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
525                         union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
526                         switch (level) {
527                         case 1:
528                                 COMPARE_STRING(cur->info1, ref->info2, monitor_name);
529                                 break;
530                         case 2:
531                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
532                                 break;
533                         }
534                 }
535         }
536
537         return ret;
538 }
539
540 static BOOL test_EnumPrintProcessors(struct test_spoolss_context *ctx)
541 {
542         NTSTATUS status;
543         struct spoolss_EnumPrintProcessors r;
544         uint16_t levels[] = { 1 };
545         int i, j;
546         BOOL ret = True;
547
548         for (i=0;i<ARRAY_SIZE(levels);i++) {
549                 int level = levels[i];
550                 DATA_BLOB blob;
551
552                 r.in.servername = "";
553                 r.in.environment = "Windows NT x86";
554                 r.in.level = level;
555                 r.in.buffer = NULL;
556                 r.in.offered = 0;
557
558                 printf("Testing EnumPrintProcessors level %u\n", r.in.level);
559
560                 status = dcerpc_spoolss_EnumPrintProcessors(ctx->p, ctx, &r);
561                 if (!NT_STATUS_IS_OK(status)) {
562                         printf("dcerpc_spoolss_EnumPrintProcessors failed - %s\n", nt_errstr(status));
563                         ret = False;
564                         continue;
565                 }
566                 if (W_ERROR_IS_OK(r.out.result)) {
567                         /* TODO: do some more checks here */
568                         continue;
569                 }
570                 if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
571                         printf("EnumPrintProcessors unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n",
572                                 win_errstr(r.out.result));
573                         ret = False;
574                         continue;
575                 }
576
577                 blob = data_blob_talloc(ctx, NULL, r.out.needed);
578                 data_blob_clear(&blob);
579                 r.in.buffer = &blob;
580                 r.in.offered = r.out.needed;
581
582                 status = dcerpc_spoolss_EnumPrintProcessors(ctx->p, ctx, &r);
583                 if (!NT_STATUS_IS_OK(status)) {
584                         printf("dcerpc_spoolss_EnumPrintProcessors failed - %s\n", nt_errstr(status));
585                         ret = False;
586                         continue;
587                 }
588
589                 if (!W_ERROR_IS_OK(r.out.result)) {
590                         printf("EnumPrintProcessors failed - %s\n",
591                                 win_errstr(r.out.result));
592                         ret = False;
593                         continue;
594                 }
595
596                 ctx->print_processor_count[level]       = r.out.count;
597                 ctx->print_processors[level]            = r.out.info;
598         }
599
600         for (i=1;i<ARRAY_SIZE(levels);i++) {
601                 int level = levels[i];
602                 int old_level = levels[i-1];
603                 if (ctx->print_processor_count[level] != ctx->print_processor_count[old_level]) {
604                         printf("EnumPrintProcessors level[%d] returns [%u] print_processors, but level[%d] returns [%u]\n",
605                                 level, ctx->print_processor_count[level], old_level, ctx->print_processor_count[old_level]);
606                         ret = False;
607                 }
608         }
609         /* if the array sizes are not the same we would maybe segfault in the following code */
610         if (!ret) return ret;
611
612         for (i=0;i<ARRAY_SIZE(levels);i++) {
613                 int level = levels[i];
614                 for (j=0;j<ctx->print_processor_count[level];j++) {
615 #if 0
616                         union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
617                         union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
618 #endif
619                         switch (level) {
620                         case 1:
621                                 /* level 1 is our reference, and it makes no sense to compare it to itself */
622                                 break;
623                         }
624                 }
625         }
626
627         return ret;
628 }
629
630 static BOOL test_EnumPrinters(struct test_spoolss_context *ctx)
631 {
632         struct spoolss_EnumPrinters r;
633         NTSTATUS status;
634         uint16_t levels[] = { 0, 1, 2, 4, 5 };
635         int i, j;
636         BOOL ret = True;
637
638         for (i=0;i<ARRAY_SIZE(levels);i++) {
639                 int level = levels[i];
640                 DATA_BLOB blob;
641
642                 r.in.flags      = PRINTER_ENUM_LOCAL;
643                 r.in.server     = "";
644                 r.in.level      = level;
645                 r.in.buffer     = NULL;
646                 r.in.offered    = 0;
647
648                 printf("\nTesting EnumPrinters level %u\n", r.in.level);
649
650                 status = dcerpc_spoolss_EnumPrinters(ctx->p, ctx, &r);
651                 if (!NT_STATUS_IS_OK(status)) {
652                         printf("dcerpc_spoolss_EnumPrinters failed - %s\n", nt_errstr(status));
653                         ret = False;
654                         continue;
655                 }
656                 if (W_ERROR_IS_OK(r.out.result)) {
657                         /* TODO: do some more checks here */
658                         continue;
659                 }
660                 if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
661                         printf("EnumPrinters unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n",
662                                 win_errstr(r.out.result));
663                         ret = False;
664                         continue;
665                 }
666
667                 blob = data_blob_talloc(ctx, NULL, r.out.needed);
668                 data_blob_clear(&blob);
669                 r.in.buffer = &blob;
670                 r.in.offered = r.out.needed;
671
672                 status = dcerpc_spoolss_EnumPrinters(ctx->p, ctx, &r);
673                 if (!NT_STATUS_IS_OK(status)) {
674                         printf("dcerpc_spoolss_EnumPrinters failed - %s\n", nt_errstr(status));
675                         ret = False;
676                         continue;
677                 }
678
679                 if (!W_ERROR_IS_OK(r.out.result)) {
680                         printf("EnumPrinters failed - %s\n", 
681                                win_errstr(r.out.result));
682                         continue;
683                 }
684
685                 ctx->printer_count[level]       = r.out.count;
686                 ctx->printers[level]            = r.out.info;
687         }
688
689         for (i=1;i<ARRAY_SIZE(levels);i++) {
690                 int level = levels[i];
691                 int old_level = levels[i-1];
692                 if (ctx->printer_count[level] != ctx->printer_count[old_level]) {
693                         printf("EnumPrinters level[%d] returns [%u] printers, but level[%d] returns [%u]\n",
694                                 level, ctx->printer_count[level], old_level, ctx->printer_count[old_level]);
695                         ret = False;
696                 }
697         }
698         /* if the array sizes are not the same we would maybe segfault in the following code */
699         if (!ret) return ret;
700
701         for (i=0;i<ARRAY_SIZE(levels);i++) {
702                 int level = levels[i];
703                 for (j=0;j<ctx->printer_count[level];j++) {
704                         union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
705                         union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
706                         switch (level) {
707                         case 0:
708                                 COMPARE_STRING(cur->info0, ref->info2, printername);
709                                 COMPARE_STRING(cur->info0, ref->info2, servername);
710                                 COMPARE_UINT32(cur->info0, ref->info2, cjobs);
711                                 /*COMPARE_UINT32(cur->info0, ref->info2, total_jobs);
712                                 COMPARE_UINT32(cur->info0, ref->info2, total_bytes);
713                                 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);                
714                                 COMPARE_UINT32(cur->info0, ref->info2, global_counter);
715                                 COMPARE_UINT32(cur->info0, ref->info2, total_pages);
716                                 COMPARE_UINT32(cur->info0, ref->info2, version);
717                                 COMPARE_UINT32(cur->info0, ref->info2, unknown10);
718                                 COMPARE_UINT32(cur->info0, ref->info2, unknown11);
719                                 COMPARE_UINT32(cur->info0, ref->info2, unknown12);
720                                 COMPARE_UINT32(cur->info0, ref->info2, session_counter);
721                                 COMPARE_UINT32(cur->info0, ref->info2, unknown14);
722                                 COMPARE_UINT32(cur->info0, ref->info2, printer_errors);
723                                 COMPARE_UINT32(cur->info0, ref->info2, unknown16);
724                                 COMPARE_UINT32(cur->info0, ref->info2, unknown17);
725                                 COMPARE_UINT32(cur->info0, ref->info2, unknown18);
726                                 COMPARE_UINT32(cur->info0, ref->info2, unknown19);
727                                 COMPARE_UINT32(cur->info0, ref->info2, change_id);
728                                 COMPARE_UINT32(cur->info0, ref->info2, unknown21);*/
729                                 COMPARE_UINT32(cur->info0, ref->info2, status);
730                                 /*COMPARE_UINT32(cur->info0, ref->info2, unknown23);
731                                 COMPARE_UINT32(cur->info0, ref->info2, c_setprinter);
732                                 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
733                                 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
734                                 COMPARE_UINT32(cur->info0, ref->info2, unknown27);
735                                 COMPARE_UINT32(cur->info0, ref->info2, unknown28);
736                                 COMPARE_UINT32(cur->info0, ref->info2, unknown29);*/
737                                 break;
738                         case 1:
739                                 /*COMPARE_UINT32(cur->info1, ref->info2, flags);*/
740                                 /*COMPARE_STRING(cur->info1, ref->info2, name);*/
741                                 /*COMPARE_STRING(cur->info1, ref->info2, description);*/
742                                 COMPARE_STRING(cur->info1, ref->info2, comment);
743                                 break;
744                         case 2:
745                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
746                                 break;
747                         case 4:
748                                 COMPARE_STRING(cur->info4, ref->info2, printername);
749                                 COMPARE_STRING(cur->info4, ref->info2, servername);
750                                 COMPARE_UINT32(cur->info4, ref->info2, attributes);
751                                 break;
752                         case 5:
753                                 COMPARE_STRING(cur->info5, ref->info2, printername);
754                                 COMPARE_STRING(cur->info5, ref->info2, portname);
755                                 COMPARE_UINT32(cur->info5, ref->info2, attributes);
756                                 /*COMPARE_UINT32(cur->info5, ref->info2, device_not_selected_timeout);
757                                 COMPARE_UINT32(cur->info5, ref->info2, transmission_retry_timeout);*/
758                                 break;
759                         }
760                 }
761         }
762
763         /* TODO:
764          *      - verify that the port of a printer was in the list returned by EnumPorts
765          */
766
767         return ret;
768 }
769
770 static BOOL test_GetPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
771                      struct policy_handle *handle)
772 {
773         NTSTATUS status;
774         struct spoolss_GetPrinter r;
775         uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
776         int i;
777         BOOL ret = True;
778         
779         for (i=0;i<ARRAY_SIZE(levels);i++) {
780                 r.in.handle = handle;
781                 r.in.level = levels[i];
782                 r.in.buffer = NULL;
783                 r.in.offered = 0;
784
785                 printf("Testing GetPrinter level %u\n", r.in.level);
786
787                 status = dcerpc_spoolss_GetPrinter(p, mem_ctx, &r);
788                 if (!NT_STATUS_IS_OK(status)) {
789                         printf("GetPrinter failed - %s\n", nt_errstr(status));
790                         ret = False;
791                         continue;
792                 }
793                 
794                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
795                         DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
796                         data_blob_clear(&blob);
797                         r.in.buffer = &blob;
798                         r.in.offered = r.out.needed;
799                         status = dcerpc_spoolss_GetPrinter(p, mem_ctx, &r);
800                 }
801                 
802                 if (!NT_STATUS_IS_OK(status)) {
803                         printf("GetPrinter failed - %s\n", nt_errstr(status));
804                         ret = False;
805                         continue;
806                 }
807
808                 if (!W_ERROR_IS_OK(r.out.result)) {
809                         printf("GetPrinter failed - %s\n", 
810                                win_errstr(r.out.result));
811                         ret = False;
812                         continue;
813                 }
814         }
815
816         return ret;
817 }
818
819
820 static BOOL test_ClosePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
821                        struct policy_handle *handle)
822 {
823         NTSTATUS status;
824         struct spoolss_ClosePrinter r;
825
826         r.in.handle = handle;
827         r.out.handle = handle;
828
829         printf("Testing ClosePrinter\n");
830
831         status = dcerpc_spoolss_ClosePrinter(p, mem_ctx, &r);
832         if (!NT_STATUS_IS_OK(status)) {
833                 printf("ClosePrinter failed - %s\n", nt_errstr(status));
834                 return False;
835         }
836
837         return True;
838 }
839
840 static BOOL test_GetForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
841                          struct policy_handle *handle, 
842                          const char *form_name)
843 {
844         NTSTATUS status;
845         struct spoolss_GetForm r;
846
847         r.in.handle = handle;
848         r.in.form_name = form_name;
849         r.in.level = 1;
850         r.in.buffer = NULL;
851         r.in.offered = 0;
852
853         printf("Testing GetForm\n");
854
855         status = dcerpc_spoolss_GetForm(p, mem_ctx, &r);
856         if (!NT_STATUS_IS_OK(status)) {
857                 printf("GetForm failed - %s\n", nt_errstr(status));
858                 return False;
859         }
860
861         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
862                 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
863                 data_blob_clear(&blob);
864                 r.in.buffer = &blob;
865                 r.in.offered = r.out.needed;
866                 status = dcerpc_spoolss_GetForm(p, mem_ctx, &r);
867                 if (!NT_STATUS_IS_OK(status)) {
868                         printf("GetForm failed - %s\n",
869                                 nt_errstr(status));
870                         return False;
871                 }
872
873                 if (!W_ERROR_IS_OK(r.out.result)) {
874                         printf("GetForm failed - %s\n",
875                                 win_errstr(r.out.result));
876                         return False;
877                 }
878
879                 if (!r.out.info) {
880                         printf("No form info returned\n");
881                         return False;
882                 }
883         }
884
885
886         if (!W_ERROR_IS_OK(r.out.result)) {
887                 printf("GetForm failed - %s\n",
888                         win_errstr(r.out.result));
889                 return False;
890         }
891
892         return True;
893 }
894
895 static BOOL test_EnumForms(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
896                     struct policy_handle *handle, BOOL print_server)
897 {
898         NTSTATUS status;
899         struct spoolss_EnumForms r;
900         BOOL ret = True;
901
902         r.in.handle = handle;
903         r.in.level = 1;
904         r.in.buffer = NULL;
905         r.in.offered = 0;
906
907         printf("Testing EnumForms\n");
908
909         status = dcerpc_spoolss_EnumForms(p, mem_ctx, &r);
910         if (!NT_STATUS_IS_OK(status)) {
911                 printf("EnumForms failed - %s\n", nt_errstr(status));
912                 return False;
913         }
914
915         if (print_server && W_ERROR_EQUAL(r.out.result,WERR_BADFID)) {
916                 printf("EnumForms on the PrintServer isn't supported by test server (NT4)\n");
917                 return True;
918         }
919
920         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
921                 union spoolss_FormInfo *info;
922                 int j;
923                 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
924                 data_blob_clear(&blob);
925                 r.in.buffer = &blob;
926                 r.in.offered = r.out.needed;
927
928                 status = dcerpc_spoolss_EnumForms(p, mem_ctx, &r);
929
930                 if (!r.out.info) {
931                         printf("No forms returned\n");
932                         return False;
933                 }
934
935                 info = r.out.info;
936
937                 for (j = 0; j < r.out.count; j++) {
938                         if (!print_server) ret &= test_GetForm(p, mem_ctx, handle, info[j].info1.form_name);
939                 }
940         }
941
942         if (!NT_STATUS_IS_OK(status)) {
943                 printf("EnumForms failed - %s\n", nt_errstr(status));
944                 return False;
945         }
946
947         if (!W_ERROR_IS_OK(r.out.result)) {
948                 printf("EnumForms failed - %s\n", win_errstr(r.out.result));
949                 return False;
950         }
951
952         return True;
953 }
954
955 static BOOL test_DeleteForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
956                             struct policy_handle *handle, 
957                             const char *form_name)
958 {
959         NTSTATUS status;
960         struct spoolss_DeleteForm r;
961
962         r.in.handle = handle;
963         r.in.form_name = form_name;
964
965         status = dcerpc_spoolss_DeleteForm(p, mem_ctx, &r);
966
967         if (!NT_STATUS_IS_OK(status)) {
968                 printf("DeleteForm failed - %s\n", nt_errstr(status));
969                 return False;
970         }
971
972         if (!W_ERROR_IS_OK(r.out.result)) {
973                 printf("DeleteForm failed - %s\n", win_errstr(r.out.result));
974                 return False;
975         }
976
977         return True;
978 }
979
980 static BOOL test_AddForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
981                   struct policy_handle *handle, BOOL print_server)
982 {
983         struct spoolss_AddForm r;
984         struct spoolss_AddFormInfo1 addform;
985         const char *form_name = "testform3";
986         NTSTATUS status;
987         BOOL ret = True;
988
989         r.in.handle     = handle;
990         r.in.level      = 1;
991         r.in.info.info1 = &addform;
992         addform.flags           = SPOOLSS_FORM_USER;
993         addform.form_name       = form_name;
994         addform.size.width      = 50;
995         addform.size.height     = 25;
996         addform.area.left       = 5;
997         addform.area.top        = 10;
998         addform.area.right      = 45;
999         addform.area.bottom     = 15;
1000
1001         status = dcerpc_spoolss_AddForm(p, mem_ctx, &r);
1002
1003         if (!NT_STATUS_IS_OK(status)) {
1004                 printf("AddForm failed - %s\n", nt_errstr(status));
1005                 return False;
1006         }
1007
1008         if (!W_ERROR_IS_OK(r.out.result)) {
1009                 printf("AddForm failed - %s\n", win_errstr(r.out.result));
1010                 goto done;
1011         }
1012
1013         if (!print_server) ret &= test_GetForm(p, mem_ctx, handle, form_name);
1014
1015         {
1016                 struct spoolss_SetForm sf;
1017                 struct spoolss_AddFormInfo1 setform;
1018
1019                 sf.in.handle    = handle;
1020                 sf.in.form_name = form_name;
1021                 sf.in.level     = 1;
1022                 sf.in.info.info1= &setform;
1023                 setform.flags           = addform.flags;
1024                 setform.form_name       = addform.form_name;
1025                 setform.size            = addform.size;
1026                 setform.area            = addform.area;
1027
1028                 setform.size.width      = 1234;
1029
1030                 status = dcerpc_spoolss_SetForm(p, mem_ctx, &sf);
1031
1032                 if (!NT_STATUS_IS_OK(status)) {
1033                         printf("SetForm failed - %s\n", nt_errstr(status));
1034                         ret = False;
1035                         goto done;
1036                 }
1037
1038                 if (!W_ERROR_IS_OK(r.out.result)) {
1039                         printf("SetForm failed - %s\n", 
1040                                win_errstr(r.out.result));
1041                         ret = False;
1042                         goto done;
1043                 }
1044         }
1045
1046         if (!print_server) ret &= test_GetForm(p, mem_ctx, handle, form_name);
1047
1048  done:
1049         if (!test_DeleteForm(p, mem_ctx, handle, form_name)) {
1050                 printf("DeleteForm failed\n");
1051                 ret = False;
1052         }
1053
1054         return ret;
1055 }
1056
1057 static BOOL test_EnumPorts_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1058 {
1059         NTSTATUS status;
1060         struct spoolss_EnumPorts r;
1061
1062         r.in.servername = talloc_asprintf(mem_ctx, "\\\\%s", 
1063                                           dcerpc_server_name(p));
1064         r.in.level = 2;
1065         r.in.buffer = NULL;
1066         r.in.offered = 0;
1067
1068         printf("Testing EnumPorts\n");
1069
1070         status = dcerpc_spoolss_EnumPorts(p, mem_ctx, &r);
1071
1072         if (!NT_STATUS_IS_OK(status)) {
1073                 printf("EnumPorts failed - %s\n", nt_errstr(status));
1074                 return False;
1075         }
1076
1077         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1078                 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
1079                 data_blob_clear(&blob);
1080                 r.in.buffer = &blob;
1081                 r.in.offered = r.out.needed;
1082
1083                 status = dcerpc_spoolss_EnumPorts(p, mem_ctx, &r);
1084                 if (!NT_STATUS_IS_OK(status)) {
1085                         printf("EnumPorts failed - %s\n", nt_errstr(status));
1086                         return False;
1087                 }
1088
1089                 if (!r.out.info) {
1090                         printf("No ports returned\n");
1091                         return False;
1092                 }
1093         }
1094
1095         return True;
1096 }
1097
1098 static BOOL test_AddPort(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1099 {
1100         NTSTATUS status;
1101         struct spoolss_AddPort r;
1102
1103         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", 
1104                                            dcerpc_server_name(p));
1105         r.in.unknown = 0;
1106         r.in.monitor_name = "foo";
1107
1108         printf ("Testing AddPort\n");
1109
1110         status = dcerpc_spoolss_AddPort(p, mem_ctx, &r);
1111
1112         if (!NT_STATUS_IS_OK(status)) {
1113                 printf("AddPort failed - %s\n", nt_errstr(status));
1114                 return False;
1115         }
1116
1117         /* win2k3 returns WERR_NOT_SUPPORTED */
1118
1119 #if 0
1120
1121         if (!W_ERROR_IS_OK(r.out.result)) {
1122                 printf("AddPort failed - %s\n", win_errstr(r.out.result));
1123                 return False;
1124         }
1125
1126 #endif
1127
1128         return True;
1129 }
1130
1131 static BOOL test_GetJob(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1132                   struct policy_handle *handle, uint32_t job_id)
1133 {
1134         NTSTATUS status;
1135         struct spoolss_GetJob r;
1136
1137         r.in.handle = handle;
1138         r.in.job_id = job_id;
1139         r.in.level = 1;
1140         r.in.buffer = NULL;
1141         r.in.offered = 0;
1142
1143         printf("Testing GetJob\n");
1144
1145         status = dcerpc_spoolss_GetJob(p, mem_ctx, &r);
1146         if (!NT_STATUS_IS_OK(status)) {
1147                 printf("GetJob failed - %s\n", nt_errstr(status));
1148                 return False;
1149         }
1150
1151         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1152                 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
1153                 data_blob_clear(&blob);
1154                 r.in.buffer = &blob;
1155                 r.in.offered = r.out.needed;
1156
1157                 status = dcerpc_spoolss_GetJob(p, mem_ctx, &r);
1158
1159                 if (!r.out.info) {
1160                         printf("No job info returned\n");
1161                         return False;
1162                 }
1163         }
1164
1165         return True;
1166 }
1167
1168 static BOOL test_SetJob(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1169                  struct policy_handle *handle, uint32_t job_id, enum spoolss_JobControl command)
1170 {
1171         NTSTATUS status;
1172         struct spoolss_SetJob r;
1173
1174         r.in.handle     = handle;
1175         r.in.job_id     = job_id;
1176         r.in.ctr        = NULL;
1177         r.in.command    = command;
1178
1179         printf("Testing SetJob\n");
1180
1181         status = dcerpc_spoolss_SetJob(p, mem_ctx, &r);
1182         if (!NT_STATUS_IS_OK(status)) {
1183                 printf("SetJob failed - %s\n", nt_errstr(status));
1184                 return False;
1185         }
1186         if (!W_ERROR_IS_OK(r.out.result)) {
1187                 printf("SetJob failed - %s\n", win_errstr(r.out.result));
1188                 return False;
1189         }
1190
1191         return True;
1192 }
1193
1194 static BOOL test_EnumJobs(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1195                    struct policy_handle *handle)
1196 {
1197         NTSTATUS status;
1198         struct spoolss_EnumJobs r;
1199
1200         r.in.handle = handle;
1201         r.in.firstjob = 0;
1202         r.in.numjobs = 0xffffffff;
1203         r.in.level = 1;
1204         r.in.buffer = NULL;
1205         r.in.offered = 0;
1206
1207         printf("Testing EnumJobs\n");
1208
1209         status = dcerpc_spoolss_EnumJobs(p, mem_ctx, &r);
1210
1211         if (!NT_STATUS_IS_OK(status)) {
1212                 printf("EnumJobs failed - %s\n", nt_errstr(status));
1213                 return False;
1214         }
1215
1216         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1217                 union spoolss_JobInfo *info;
1218                 int j;
1219                 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
1220                 data_blob_clear(&blob);
1221                 r.in.buffer = &blob;
1222                 r.in.offered = r.out.needed;
1223
1224                 status = dcerpc_spoolss_EnumJobs(p, mem_ctx, &r);
1225
1226                 if (!r.out.info) {
1227                         printf("No jobs returned\n");
1228                         return True;
1229                 }
1230
1231                 info = r.out.info;
1232
1233                 for (j = 0; j < r.out.count; j++) {
1234                         test_GetJob(p, mem_ctx, handle, info[j].info1.job_id);
1235                         test_SetJob(p, mem_ctx, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
1236                         test_SetJob(p, mem_ctx, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
1237                 }
1238
1239         } else if (!W_ERROR_IS_OK(r.out.result)) {
1240                 printf("EnumJobs failed - %s\n", win_errstr(r.out.result));
1241                 return False;
1242         }
1243
1244         return True;
1245 }
1246
1247 static BOOL test_DoPrintTest(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1248                    struct policy_handle *handle)
1249 {
1250         BOOL ret = True;
1251         NTSTATUS status;
1252         struct spoolss_StartDocPrinter s;
1253         struct spoolss_DocumentInfo1 info1;
1254         struct spoolss_StartPagePrinter sp;
1255         struct spoolss_WritePrinter w;
1256         struct spoolss_EndPagePrinter ep;
1257         struct spoolss_EndDocPrinter e;
1258         int i;
1259         uint32_t job_id;
1260
1261         printf("Testing StartDocPrinter\n");
1262
1263         s.in.handle             = handle;
1264         s.in.level              = 1;
1265         s.in.info.info1         = &info1;
1266         info1.document_name     = "TorturePrintJob";
1267         info1.output_file       = NULL;
1268         info1.datatype          = "RAW";
1269
1270         status = dcerpc_spoolss_StartDocPrinter(p, mem_ctx, &s);
1271         if (!NT_STATUS_IS_OK(status)) {
1272                 printf("dcerpc_spoolss_StartDocPrinter failed - %s\n", nt_errstr(status));
1273                 return False;
1274         }
1275         if (!W_ERROR_IS_OK(s.out.result)) {
1276                 printf("StartDocPrinter failed - %s\n", win_errstr(s.out.result));
1277                 return False;
1278         }
1279
1280         job_id = s.out.job_id;
1281
1282         for (i=1; i < 4; i++) {
1283                 printf("Testing StartPagePrinter: Page[%d]\n", i);
1284
1285                 sp.in.handle            = handle;
1286
1287                 status = dcerpc_spoolss_StartPagePrinter(p, mem_ctx, &sp);
1288                 if (!NT_STATUS_IS_OK(status)) {
1289                         printf("dcerpc_spoolss_StartPagePrinter failed - %s\n", nt_errstr(status));
1290                         return False;
1291                 }
1292                 if (!W_ERROR_IS_OK(sp.out.result)) {
1293                         printf("StartPagePrinter failed - %s\n", win_errstr(sp.out.result));
1294                         return False;
1295                 }
1296
1297                 printf("Testing WritePrinter: Page[%d]\n", i);
1298
1299                 w.in.handle             = handle;
1300                 w.in.data               = data_blob_string_const(talloc_asprintf(mem_ctx,"TortureTestPage: %d\nData\n",i));
1301
1302                 status = dcerpc_spoolss_WritePrinter(p, mem_ctx, &w);
1303                 if (!NT_STATUS_IS_OK(status)) {
1304                         printf("dcerpc_spoolss_WritePrinter failed - %s\n", nt_errstr(status));
1305                         return False;
1306                 }
1307                 if (!W_ERROR_IS_OK(w.out.result)) {
1308                         printf("WritePrinter failed - %s\n", win_errstr(w.out.result));
1309                         return False;
1310                 }
1311
1312                 printf("Testing EndPagePrinter: Page[%d]\n", i);
1313
1314                 ep.in.handle            = handle;
1315
1316                 status = dcerpc_spoolss_EndPagePrinter(p, mem_ctx, &ep);
1317                 if (!NT_STATUS_IS_OK(status)) {
1318                         printf("dcerpc_spoolss_EndPagePrinter failed - %s\n", nt_errstr(status));
1319                         return False;
1320                 }
1321                 if (!W_ERROR_IS_OK(ep.out.result)) {
1322                         printf("EndPagePrinter failed - %s\n", win_errstr(ep.out.result));
1323                         return False;
1324                 }
1325         }
1326
1327         printf("Testing EndDocPrinter\n");
1328
1329         e.in.handle = handle;
1330
1331         status = dcerpc_spoolss_EndDocPrinter(p, mem_ctx, &e);
1332         if (!NT_STATUS_IS_OK(status)) {
1333                 printf("dcerpc_spoolss_EndDocPrinter failed - %s\n", nt_errstr(status));
1334                 return False;
1335         }
1336         if (!W_ERROR_IS_OK(e.out.result)) {
1337                 printf("EndDocPrinter failed - %s\n", win_errstr(e.out.result));
1338                 return False;
1339         }
1340
1341         ret &= test_EnumJobs(p, mem_ctx, handle);
1342
1343         ret &= test_SetJob(p, mem_ctx, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
1344
1345         return ret;
1346 }
1347
1348 static BOOL test_PausePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1349                    struct policy_handle *handle)
1350 {
1351         NTSTATUS status;
1352         struct spoolss_SetPrinter r;
1353
1354         r.in.handle             = handle;
1355         r.in.level              = 0;
1356         r.in.info.info1         = NULL;
1357         r.in.devmode_ctr.devmode= NULL;
1358         r.in.secdesc_ctr.sd     = NULL;
1359         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
1360
1361         printf("Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1362
1363         status = dcerpc_spoolss_SetPrinter(p, mem_ctx, &r);
1364
1365         if (!NT_STATUS_IS_OK(status)) {
1366                 printf("SetPrinter failed - %s\n", nt_errstr(status));
1367                 return False;
1368         }
1369
1370         if (!W_ERROR_IS_OK(r.out.result)) {
1371                 printf("SetPrinter failed - %s\n", win_errstr(r.out.result));
1372                 return False;
1373         }
1374
1375         return True;
1376 }
1377
1378 static BOOL test_ResumePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1379                    struct policy_handle *handle)
1380 {
1381         NTSTATUS status;
1382         struct spoolss_SetPrinter r;
1383
1384         r.in.handle             = handle;
1385         r.in.level              = 0;
1386         r.in.info.info1         = NULL;
1387         r.in.devmode_ctr.devmode= NULL;
1388         r.in.secdesc_ctr.sd     = NULL;
1389         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
1390
1391         printf("Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
1392
1393         status = dcerpc_spoolss_SetPrinter(p, mem_ctx, &r);
1394
1395         if (!NT_STATUS_IS_OK(status)) {
1396                 printf("SetPrinter failed - %s\n", nt_errstr(status));
1397                 return False;
1398         }
1399
1400         if (!W_ERROR_IS_OK(r.out.result)) {
1401                 printf("SetPrinter failed - %s\n", win_errstr(r.out.result));
1402                 return False;
1403         }
1404
1405         return True;
1406 }
1407
1408 static BOOL test_GetPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1409                                 struct policy_handle *handle, 
1410                                 const char *value_name)
1411 {
1412         NTSTATUS status;
1413         struct spoolss_GetPrinterData r;
1414
1415         r.in.handle = handle;
1416         r.in.value_name = value_name;
1417         r.in.offered = 0;
1418
1419         printf("Testing GetPrinterData\n");
1420
1421         status = dcerpc_spoolss_GetPrinterData(p, mem_ctx, &r);
1422         if (!NT_STATUS_IS_OK(status)) {
1423                 printf("GetPrinterData failed - %s\n", nt_errstr(status));
1424                 return False;
1425         }
1426
1427         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1428                 r.in.offered = r.out.needed;
1429
1430                 status = dcerpc_spoolss_GetPrinterData(p, mem_ctx, &r);
1431                 if (!NT_STATUS_IS_OK(status)) {
1432                         printf("GetPrinterData failed - %s\n", 
1433                                nt_errstr(status));
1434                         return False;
1435                 }
1436
1437                 if (!W_ERROR_IS_OK(r.out.result)) {
1438                         printf("GetPrinterData failed - %s\n", 
1439                                win_errstr(r.out.result));
1440                         return False;
1441                 }
1442         }
1443
1444         return True;
1445 }
1446
1447 static BOOL test_GetPrinterDataEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1448                                   struct policy_handle *handle, 
1449                                   const char *key_name,
1450                                   const char *value_name)
1451 {
1452         NTSTATUS status;
1453         struct spoolss_GetPrinterDataEx r;
1454
1455         r.in.handle = handle;
1456         r.in.key_name = key_name;
1457         r.in.value_name = value_name;
1458         r.in.offered = 0;
1459
1460         printf("Testing GetPrinterDataEx\n");
1461
1462         status = dcerpc_spoolss_GetPrinterDataEx(p, mem_ctx, &r);
1463         if (!NT_STATUS_IS_OK(status)) {
1464                 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
1465                     p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1466                         printf("GetPrinterDataEx not supported by server\n");
1467                         return True;
1468                 }
1469                 printf("GetPrinterDataEx failed - %s\n", nt_errstr(status));
1470                 return False;
1471         }
1472
1473         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1474                 r.in.offered = r.out.needed;
1475
1476                 status = dcerpc_spoolss_GetPrinterDataEx(p, mem_ctx, &r);
1477                 if (!NT_STATUS_IS_OK(status)) {
1478                         printf("GetPrinterDataEx failed - %s\n", 
1479                                nt_errstr(status));
1480                         return False;
1481                 }
1482
1483                 if (!W_ERROR_IS_OK(r.out.result)) {
1484                         printf("GetPrinterDataEx failed - %s\n", 
1485                                win_errstr(r.out.result));
1486                         return False;
1487                 }
1488         }
1489
1490         return True;
1491 }
1492
1493 static BOOL test_EnumPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1494                                  struct policy_handle *handle)
1495 {
1496         NTSTATUS status;
1497         struct spoolss_EnumPrinterData r;
1498
1499         r.in.handle = handle;
1500         r.in.enum_index = 0;
1501
1502         do {
1503                 uint32_t data_size;
1504                 
1505                 r.in.value_offered = 0;
1506                 data_size = 0;
1507                 r.in.data_size = &data_size;
1508                 r.out.data_size = &data_size;
1509
1510                 printf("Testing EnumPrinterData\n");
1511
1512                 status = dcerpc_spoolss_EnumPrinterData(p, mem_ctx, &r);
1513
1514                 if (!NT_STATUS_IS_OK(status)) {
1515                         printf("EnumPrinterData failed - %s\n", nt_errstr(status));
1516                         return False;
1517                 }
1518
1519                 r.in.value_offered = r.out.value_needed;
1520
1521                 status = dcerpc_spoolss_EnumPrinterData(p, mem_ctx, &r);
1522
1523                 if (!NT_STATUS_IS_OK(status)) {
1524                         printf("EnumPrinterData failed - %s\n", nt_errstr(status));
1525                         return False;
1526                 }
1527                 
1528                 test_GetPrinterData(p, mem_ctx, handle, r.out.value_name);
1529
1530                 test_GetPrinterDataEx(
1531                         p, mem_ctx, handle, "PrinterDriverData", 
1532                         r.out.value_name);
1533
1534                 r.in.enum_index++;
1535
1536         } while (W_ERROR_IS_OK(r.out.result));
1537
1538         return True;
1539 }
1540
1541 static BOOL test_EnumPrinterDataEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1542                                    struct policy_handle *handle)
1543 {
1544         NTSTATUS status;
1545         struct spoolss_EnumPrinterDataEx r;
1546
1547         r.in.handle = handle;
1548         r.in.key_name = "PrinterDriverData";
1549         r.in.offered = 0;
1550
1551         printf("Testing EnumPrinterDataEx\n");
1552
1553         status = dcerpc_spoolss_EnumPrinterDataEx(p, mem_ctx, &r);
1554         if (!NT_STATUS_IS_OK(status)) {
1555                 printf("EnumPrinterDataEx failed - %s\n", nt_errstr(status));
1556                 return False;
1557         }
1558
1559         r.in.offered = r.out.needed;
1560
1561         status = dcerpc_spoolss_EnumPrinterDataEx(p, mem_ctx, &r);
1562
1563         if (!NT_STATUS_IS_OK(status)) {
1564                 printf("EnumPrinterDataEx failed - %s\n", nt_errstr(status));
1565                 return False;
1566         }
1567
1568         return True;
1569 }
1570
1571
1572 static BOOL test_DeletePrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1573                                    struct policy_handle *handle, 
1574                                    const char *value_name)
1575 {
1576         NTSTATUS status;
1577         struct spoolss_DeletePrinterData r;
1578
1579         r.in.handle = handle;
1580         r.in.value_name = value_name;
1581
1582         printf("Testing DeletePrinterData\n");
1583
1584         status = dcerpc_spoolss_DeletePrinterData(p, mem_ctx, &r);
1585
1586         if (!NT_STATUS_IS_OK(status)) {
1587                 printf("DeletePrinterData failed - %s\n", nt_errstr(status));
1588                 return False;
1589         }
1590
1591         return True;
1592 }
1593
1594 static BOOL test_SetPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1595                          struct policy_handle *handle)
1596 {
1597         NTSTATUS status;
1598         struct spoolss_SetPrinterData r;
1599         const char *value_name = "spottyfoot";
1600         
1601         r.in.handle = handle;
1602         r.in.value_name = value_name;
1603         r.in.type = SPOOLSS_PRINTER_DATA_TYPE_STRING;
1604         r.in.data.string = "dog";
1605
1606         printf("Testing SetPrinterData\n");
1607
1608         status = dcerpc_spoolss_SetPrinterData(p, mem_ctx, &r);
1609
1610         if (!NT_STATUS_IS_OK(status)) {
1611                 printf("SetPrinterData failed - %s\n", nt_errstr(status));
1612                 return False;
1613         }
1614
1615         if (!test_GetPrinterData(p, mem_ctx, handle, value_name)) {
1616                 return False;
1617         }
1618
1619         if (!test_DeletePrinterData(p, mem_ctx, handle, value_name)) {
1620                 return False;
1621         }
1622
1623         return True;
1624 }
1625
1626 static BOOL test_SecondaryClosePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1627                                        struct policy_handle *handle)
1628 {
1629         NTSTATUS status;
1630         struct dcerpc_binding *b;
1631         struct dcerpc_pipe *p2;
1632         BOOL ret = True;
1633
1634         /* only makes sense on SMB */
1635         if (p->conn->transport.transport != NCACN_NP) {
1636                 return True;
1637         }
1638
1639         printf("testing close on secondary pipe\n");
1640
1641         status = dcerpc_parse_binding(mem_ctx, p->conn->binding_string, &b);
1642         if (!NT_STATUS_IS_OK(status)) {
1643                 printf("Failed to parse dcerpc binding '%s'\n", p->conn->binding_string);
1644                 return False;
1645         }
1646
1647         status = dcerpc_secondary_connection(p, &p2, b);
1648         if (!NT_STATUS_IS_OK(status)) {
1649                 printf("Failed to create secondary connection\n");
1650                 return False;
1651         }
1652
1653         status = dcerpc_bind_auth_none(p2, &dcerpc_table_spoolss);
1654         if (!NT_STATUS_IS_OK(status)) {
1655                 printf("Failed to create bind on secondary connection\n");
1656                 talloc_free(p2);
1657
1658                 return False;
1659         }
1660
1661         if (test_ClosePrinter(p2, mem_ctx, handle)) {
1662                 printf("ERROR: Allowed close on secondary connection!\n");
1663                 ret = False;
1664         }
1665
1666         if (p2->last_fault_code != DCERPC_FAULT_CONTEXT_MISMATCH) {
1667                 printf("Unexpected fault code 0x%x - expected 0x%x\n",
1668                        p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH);
1669                 ret = False;
1670         }
1671
1672         talloc_free(p2);
1673
1674         return ret;
1675 }
1676
1677 static BOOL test_OpenPrinter_badname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, const char *name)
1678 {
1679         NTSTATUS status;
1680         struct spoolss_OpenPrinter op;
1681         struct spoolss_OpenPrinterEx opEx;
1682         struct policy_handle handle;
1683         BOOL ret = True;
1684
1685         op.in.printername       = name;
1686         op.in.datatype          = NULL;
1687         op.in.devmode_ctr.devmode= NULL;
1688         op.in.access_mask       = 0;
1689         op.out.handle           = &handle;
1690
1691         printf("\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
1692
1693         status = dcerpc_spoolss_OpenPrinter(p, mem_ctx, &op);
1694         if (!NT_STATUS_IS_OK(status)) {
1695                 printf("OpenPrinter failed - %s\n", nt_errstr(status));
1696                 ret = False;
1697         }
1698         if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
1699                 printf("OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
1700                         name, win_errstr(op.out.result));
1701         }
1702
1703         if (W_ERROR_IS_OK(op.out.result)) {
1704                 ret &=test_ClosePrinter(p, mem_ctx, &handle);
1705         }
1706
1707         opEx.in.printername             = name;
1708         opEx.in.datatype                = NULL;
1709         opEx.in.devmode_ctr.devmode     = NULL;
1710         opEx.in.access_mask             = 0;
1711         opEx.in.level                   = 1;
1712         opEx.in.userlevel.level1        = NULL;
1713         opEx.out.handle                 = &handle;
1714
1715         printf("\nTesting OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
1716
1717         status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &opEx);
1718         if (!NT_STATUS_IS_OK(status)) {
1719                 printf("OpenPrinter failed - %s\n", nt_errstr(status));
1720                 ret = False;
1721         }
1722         if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,opEx.out.result)) {
1723                 printf("OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
1724                         name, win_errstr(opEx.out.result));
1725         }
1726
1727         if (W_ERROR_IS_OK(opEx.out.result)) {
1728                 ret &=test_ClosePrinter(p, mem_ctx, &handle);
1729         }
1730
1731         return ret;
1732 }
1733
1734 static BOOL test_OpenPrinter_badnames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1735 {
1736         BOOL ret = True;
1737         char *name;
1738
1739         ret &= test_OpenPrinter_badname(p, mem_ctx, "__INVALID_PRINTER__");
1740         ret &= test_OpenPrinter_badname(p, mem_ctx, "\\\\__INVALID_HOST__");
1741         ret &= test_OpenPrinter_badname(p, mem_ctx, "");
1742         ret &= test_OpenPrinter_badname(p, mem_ctx, "\\\\\\");
1743         ret &= test_OpenPrinter_badname(p, mem_ctx, "\\\\\\__INVALID_PRINTER__");
1744
1745         name = talloc_asprintf(mem_ctx, "\\\\%s\\", dcerpc_server_name(p));
1746         ret &= test_OpenPrinter_badname(p, mem_ctx, name);
1747         talloc_free(name);
1748
1749         name = talloc_asprintf(mem_ctx, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p));
1750         ret &= test_OpenPrinter_badname(p, mem_ctx, name);
1751         talloc_free(name);
1752
1753         return ret;
1754 }
1755
1756 static BOOL test_OpenPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1757                              const char *name)
1758 {
1759         NTSTATUS status;
1760         struct spoolss_OpenPrinter r;
1761         struct policy_handle handle;
1762         BOOL ret = True;
1763
1764         r.in.printername        = talloc_asprintf(mem_ctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
1765         r.in.datatype           = NULL;
1766         r.in.devmode_ctr.devmode= NULL;
1767         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
1768         r.out.handle            = &handle;
1769
1770         printf("\nTesting OpenPrinter(%s)\n", r.in.printername);
1771
1772         status = dcerpc_spoolss_OpenPrinter(p, mem_ctx, &r);
1773
1774         if (!NT_STATUS_IS_OK(status)) {
1775                 printf("OpenPrinter failed - %s\n", nt_errstr(status));
1776                 return False;
1777         }
1778
1779         if (!W_ERROR_IS_OK(r.out.result)) {
1780                 printf("OpenPrinter failed - %s\n", win_errstr(r.out.result));
1781                 return False;
1782         }
1783
1784         if (!test_GetPrinter(p, mem_ctx, &handle)) {
1785                 ret = False;
1786         }
1787
1788         if (!test_SecondaryClosePrinter(p, mem_ctx, &handle)) {
1789                 ret = False;
1790         }
1791
1792         if (!test_ClosePrinter(p, mem_ctx, &handle)) {
1793                 ret = False;
1794         }
1795
1796         return ret;
1797 }
1798
1799 static BOOL call_OpenPrinterEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1800                                const char *name, struct policy_handle *handle)
1801 {
1802         struct spoolss_OpenPrinterEx r;
1803         struct spoolss_UserLevel1 userlevel1;
1804         NTSTATUS status;
1805
1806         if (name && name[0]) {
1807                 r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s", 
1808                                                    dcerpc_server_name(p), name);
1809         } else {
1810                 r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s", 
1811                                                    dcerpc_server_name(p));
1812         }
1813
1814         r.in.datatype           = NULL;
1815         r.in.devmode_ctr.devmode= NULL;
1816         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
1817         r.in.level              = 1;
1818         r.in.userlevel.level1   = &userlevel1;
1819         r.out.handle = handle;
1820
1821         userlevel1.size = 1234;
1822         userlevel1.client = "hello";
1823         userlevel1.user = "spottyfoot!";
1824         userlevel1.build = 1;
1825         userlevel1.major = 2;
1826         userlevel1.minor = 3;
1827         userlevel1.processor = 4;
1828
1829         printf("Testing OpenPrinterEx(%s)\n", r.in.printername);
1830
1831         status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &r);
1832
1833         if (!NT_STATUS_IS_OK(status)) {
1834                 printf("OpenPrinterEx failed - %s\n", nt_errstr(status));
1835                 return False;
1836         }
1837         
1838         if (!W_ERROR_IS_OK(r.out.result)) {
1839                 printf("OpenPrinterEx failed - %s\n", win_errstr(r.out.result));
1840                 return False;
1841         }
1842
1843         return True;
1844 }
1845
1846 static BOOL test_OpenPrinterEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1847                                const char *name)
1848 {
1849         struct policy_handle handle;
1850         BOOL ret = True;
1851
1852         if (!call_OpenPrinterEx(p, mem_ctx, name, &handle)) {
1853                 return False;
1854         }
1855
1856         if (!test_GetPrinter(p, mem_ctx, &handle)) {
1857                 ret = False;
1858         }
1859
1860         if (!test_EnumForms(p, mem_ctx, &handle, False)) {
1861                 ret = False;
1862         }
1863
1864         if (!test_AddForm(p, mem_ctx, &handle, False)) {
1865                 ret = False;
1866         }
1867
1868         if (!test_EnumPrinterData(p, mem_ctx, &handle)) {
1869                 ret = False;
1870         }
1871
1872         if (!test_EnumPrinterDataEx(p, mem_ctx, &handle)) {
1873                 ret = False;
1874         }
1875
1876         if (!test_PausePrinter(p, mem_ctx, &handle)) {
1877                 ret = False;
1878         }
1879
1880         if (!test_DoPrintTest(p, mem_ctx, &handle)) {
1881                 ret = False;
1882         }
1883
1884         if (!test_ResumePrinter(p, mem_ctx, &handle)) {
1885                 ret = False;
1886         }
1887
1888         if (!test_SetPrinterData(p, mem_ctx, &handle)) {
1889                 ret = False;
1890         }
1891
1892         if (!test_SecondaryClosePrinter(p, mem_ctx, &handle)) {
1893                 ret = False;
1894         }
1895
1896         if (!test_ClosePrinter(p, mem_ctx, &handle)) {
1897                 ret = False;
1898         }
1899         
1900         return ret;
1901 }
1902
1903 static BOOL test_EnumPrinters_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1904 {
1905         struct spoolss_EnumPrinters r;
1906         NTSTATUS status;
1907         uint16_t levels[] = {1, 2, 4, 5};
1908         int i;
1909         BOOL ret = True;
1910
1911         for (i=0;i<ARRAY_SIZE(levels);i++) {
1912                 union spoolss_PrinterInfo *info;
1913                 int j;
1914
1915                 r.in.flags      = PRINTER_ENUM_LOCAL;
1916                 r.in.server     = "";
1917                 r.in.level      = levels[i];
1918                 r.in.buffer     = NULL;
1919                 r.in.offered    = 0;
1920
1921                 printf("\nTesting EnumPrinters level %u\n", r.in.level);
1922
1923                 status = dcerpc_spoolss_EnumPrinters(p, mem_ctx, &r);
1924                 if (!NT_STATUS_IS_OK(status)) {
1925                         printf("EnumPrinters failed - %s\n", nt_errstr(status));
1926                         ret = False;
1927                         continue;
1928                 }
1929
1930                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1931                         DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
1932                         data_blob_clear(&blob);
1933                         r.in.buffer = &blob;
1934                         r.in.offered = r.out.needed;
1935                         status = dcerpc_spoolss_EnumPrinters(p, mem_ctx, &r);
1936                 }
1937
1938                 if (!NT_STATUS_IS_OK(status)) {
1939                         printf("EnumPrinters failed - %s\n", 
1940                                nt_errstr(status));
1941                         continue;
1942                 }
1943
1944                 if (!W_ERROR_IS_OK(r.out.result)) {
1945                         printf("EnumPrinters failed - %s\n", 
1946                                win_errstr(r.out.result));
1947                         continue;
1948                 }
1949
1950                 if (!r.out.info) {
1951                         printf("No printers returned\n");
1952                         continue;
1953                 }
1954
1955                 info = r.out.info;
1956
1957                 for (j=0;j<r.out.count;j++) {
1958                         if (r.in.level == 1) {
1959                                 /* the names appear to be comma-separated name lists? */
1960                                 char *name = talloc_strdup(mem_ctx, info[j].info1.name);
1961                                 char *comma = strchr(name, ',');
1962                                 if (comma) *comma = 0;
1963                                 if (!test_OpenPrinter(p, mem_ctx, name)) {
1964                                         ret = False;
1965                                 }
1966                                 if (!test_OpenPrinterEx(p, mem_ctx, name)) {
1967                                         ret = False;
1968                                 }
1969                         }
1970                 }
1971         }
1972
1973         return ret;
1974 }
1975
1976 #if 0
1977 static BOOL test_GetPrinterDriver2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1978                                    struct policy_handle *handle, 
1979                                    const char *driver_name)
1980 {
1981         NTSTATUS status;
1982         struct spoolss_GetPrinterDriver2 r;
1983
1984         r.in.handle = handle;
1985         r.in.architecture = "W32X86";
1986         r.in.level = 1;
1987         r.in.buffer = NULL;
1988         r.in.offered = 0;
1989         r.in.client_major_version = 0;
1990         r.in.client_minor_version = 0;
1991
1992         printf("Testing GetPrinterDriver2\n");
1993
1994         status = dcerpc_spoolss_GetPrinterDriver2(p, mem_ctx, &r);
1995         if (!NT_STATUS_IS_OK(status)) {
1996                 printf("GetPrinterDriver2 failed - %s\n", nt_errstr(status));
1997                 return False;
1998         }
1999
2000         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2001                 r.in.offered = r.out.needed;
2002                 status = dcerpc_spoolss_GetPrinterDriver2(p, mem_ctx, &r);
2003         }
2004                 
2005         if (!NT_STATUS_IS_OK(status)) {
2006                 printf("GetPrinterDriver2 failed - %s\n", 
2007                        nt_errstr(status));
2008                 return False;
2009         }
2010
2011         if (!W_ERROR_IS_OK(r.out.result)) {
2012                 printf("GetPrinterDriver2 failed - %s\n", 
2013                        win_errstr(r.out.result));
2014                 return False;
2015         }
2016
2017         return True;
2018 }
2019 #endif
2020
2021 static BOOL test_EnumPrinterDrivers_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
2022 {
2023         struct spoolss_EnumPrinterDrivers r;
2024         NTSTATUS status;
2025         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
2026         int i;
2027         BOOL ret = True;
2028
2029         for (i=0;i<ARRAY_SIZE(levels);i++) {
2030
2031                 r.in.server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
2032                 r.in.environment = "Windows NT x86";
2033                 r.in.level = levels[i];
2034                 r.in.buffer = NULL;
2035                 r.in.offered = 0;
2036
2037                 printf("\nTesting EnumPrinterDrivers level %u\n", r.in.level);
2038
2039                 status = dcerpc_spoolss_EnumPrinterDrivers(p, mem_ctx, &r);
2040
2041                 if (!NT_STATUS_IS_OK(status)) {
2042                         printf("EnumPrinterDrivers failed - %s\n", 
2043                                nt_errstr(status));
2044                         ret = False;
2045                         continue;
2046                 }
2047
2048                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2049                         DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
2050                         data_blob_clear(&blob);
2051                         r.in.buffer = &blob;
2052                         r.in.offered = r.out.needed;
2053                         status = dcerpc_spoolss_EnumPrinterDrivers(p, mem_ctx, &r);
2054                 }
2055
2056                 if (!NT_STATUS_IS_OK(status)) {
2057                         printf("EnumPrinterDrivers failed - %s\n", 
2058                                nt_errstr(status));
2059                         ret = False;
2060                         break;
2061                 }
2062
2063                 if (!W_ERROR_IS_OK(r.out.result)) {
2064                         printf("EnumPrinterDrivers failed - %s\n", 
2065                                win_errstr(r.out.result));
2066                         ret = False;
2067                         break;
2068                 }
2069
2070                 if (!r.out.info) {
2071                         printf("No printer drivers returned\n");
2072                         break;
2073                 }
2074         }
2075
2076         return ret;
2077 }
2078
2079 BOOL torture_rpc_spoolss(struct torture_context *torture)
2080 {
2081         NTSTATUS status;
2082         struct dcerpc_pipe *p;
2083         TALLOC_CTX *mem_ctx;
2084         BOOL ret = True;
2085         struct test_spoolss_context *ctx;
2086
2087         mem_ctx = talloc_init("torture_rpc_spoolss");
2088
2089         status = torture_rpc_connection(mem_ctx, &p, &dcerpc_table_spoolss);
2090         if (!NT_STATUS_IS_OK(status)) {
2091                 talloc_free(mem_ctx);
2092                 return False;
2093         }
2094
2095         ctx = talloc_zero(mem_ctx, struct test_spoolss_context);
2096         ctx->p  = p;
2097
2098         ret &= test_OpenPrinter_server(ctx);
2099
2100         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "W3SvcInstalled");
2101         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "BeepEnabled");
2102         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "EventLog");
2103         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "NetPopup");
2104         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "NetPopupToComputer");
2105         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "MajorVersion");
2106         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "MinorVersion");
2107         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "DefaultSpoolDirectory");
2108         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "Architecture");
2109         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "DsPresent");
2110         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "OSVersion");
2111         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "OSVersionEx");
2112         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "DNSMachineName");
2113
2114         ret &= test_EnumForms(ctx->p, ctx, &ctx->server_handle, True);
2115
2116         ret &= test_AddForm(ctx->p, ctx, &ctx->server_handle, True);
2117
2118         ret &= test_EnumPorts(ctx);
2119
2120         ret &= test_GetPrinterDriverDirectory(ctx);
2121
2122         ret &= test_EnumPrinterDrivers(ctx);
2123
2124         ret &= test_EnumMonitors(ctx);
2125
2126         ret &= test_EnumPrintProcessors(ctx);
2127
2128         ret &= test_EnumPrinters(ctx);
2129
2130         ret &= test_OpenPrinter_badnames(p, mem_ctx);
2131
2132         ret &= test_AddPort(p, mem_ctx);
2133
2134         ret &= test_EnumPorts_old(p, mem_ctx);
2135
2136         ret &= test_EnumPrinters_old(p, mem_ctx);
2137
2138         ret &= test_EnumPrinterDrivers_old(p, mem_ctx);
2139
2140         talloc_free(mem_ctx);
2141
2142         return ret;
2143 }