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