r7650: fixed a typo
[kai/samba-autobuild/.git] / source4 / torture / rpc / spoolss.c
1 /* 
2    Unix SMB/CIFS implementation.
3    test suite for spoolss rpc operations
4
5    Copyright (C) Tim Potter 2003
6    Copyright (C) Stefan Metzmacher 2005
7    
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 "librpc/gen_ndr/ndr_spoolss.h"
25
26 struct test_spoolss_context {
27         struct dcerpc_pipe *p;
28
29         /* print server handle */
30         struct policy_handle server_handle;
31
32         /* for EnumPorts */
33         uint32_t port_count[3];
34         union spoolss_PortInfo *ports[3];
35
36         /* for EnumPrinterDrivers */
37         uint32_t driver_count[7];
38         union spoolss_DriverInfo *drivers[7];
39
40         /* for EnumMonitors */
41         uint32_t monitor_count[3];
42         union spoolss_MonitorInfo *monitors[3];
43
44         /* for EnumPrintProcessors */
45         uint32_t print_processor_count[2];
46         union spoolss_PrintProcessorInfo *print_processors[2];
47
48         /* for EnumPrinters */
49         uint32_t printer_count[6];
50         union spoolss_PrinterInfo *printers[6];
51 };
52
53 #define COMPARE_STRING(c,r,e) do {\
54         BOOL _ok = True;\
55         if (c.e && !r.e) _ok = False;\
56         if (!c.e && r.e) _ok = False;\
57         if (c.e && r.e && strcmp_safe(c.e, r.e) != 0) _ok = False;\
58         if (!_ok){\
59                 printf("%s: " #c "." #e " [%s] doesn't match " #r "." #e " [%s]\n",\
60                         __location__, c.e, r.e);\
61                 ret = False;\
62         }\
63 } while(0)
64
65 #define COMPARE_UINT16(c,r,e) do {\
66         if (c.e != r.e){\
67                 printf("%s: " #c "." #e "  0x%08X (%u) doesn't match " #r "." #e " 0x%08X (%u)\n",\
68                         __location__, c.e, c.e, r.e, r.e);\
69                 ret = False;\
70         }\
71 } while(0)
72
73 #define COMPARE_UINT32(c,r,e) do {\
74         if (c.e != r.e){\
75                 printf("%s: " #c "." #e "  0x%04X (%u) doesn't match " #r "." #e " 0x%04X (%u)\n",\
76                         __location__, c.e, c.e, r.e, r.e);\
77                 ret = False;\
78         }\
79 } while(0)
80
81 #define COMPARE_UINT64(c,r,e) do {\
82         if (c.e != r.e){\
83                 printf("%s: " #c "." #e "  0x%08X%08X (%llu) doesn't match " #r "." #e " 0x%08X%08X (%llu)\n",\
84                         __location__, (uint32_t)(c.e >> 32), (uint32_t)(c.e & 0xFFFFFFFF), c.e,\
85                         (uint32_t)(r.e >> 32), (uint32_t)(r.e & 0xFFFFFFFF), r.e);\
86                 ret = False;\
87         }\
88 } while(0)
89
90 /* TODO: ! */
91 #define COMPARE_SEC_DESC(c,r,e)
92 #define COMPARE_SPOOLSS_TIME(c,r,e)
93 #define COMPARE_STRING_ARRAY(c,r,e)
94
95 static BOOL test_OpenPrinter_server(struct test_spoolss_context *ctx)
96 {
97         NTSTATUS status;
98         struct spoolss_OpenPrinter op;
99         BOOL ret = True;
100
101         op.in.printername       = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(ctx->p));
102         op.in.datatype          = NULL;
103         op.in.devmode_ctr.size  = 0;
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
842                 if (!r.out.info) {
843                         printf("No form info returned\n");
844                         return False;
845                 }
846         }
847
848         return True;
849 }
850
851 static BOOL test_EnumForms(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
852                     struct policy_handle *handle, BOOL print_server)
853 {
854         NTSTATUS status;
855         struct spoolss_EnumForms r;
856
857         r.in.handle = handle;
858         r.in.level = 1;
859         r.in.buffer = NULL;
860         r.in.offered = 0;
861
862         printf("Testing EnumForms\n");
863
864         status = dcerpc_spoolss_EnumForms(p, mem_ctx, &r);
865         if (!NT_STATUS_IS_OK(status)) {
866                 printf("EnumForms failed - %s\n", nt_errstr(status));
867                 return False;
868         }
869
870         if (print_server && W_ERROR_EQUAL(r.out.result,WERR_BADFID)) {
871                 printf("EnumForms on the PrintServer isn't supported by test server (NT4)\n");
872                 return True;
873         }
874
875         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
876                 union spoolss_FormInfo *info;
877                 int j;
878                 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
879                 data_blob_clear(&blob);
880                 r.in.buffer = &blob;
881                 r.in.offered = r.out.needed;
882
883                 status = dcerpc_spoolss_EnumForms(p, mem_ctx, &r);
884
885                 if (!r.out.info) {
886                         printf("No forms returned\n");
887                         return False;
888                 }
889
890                 info = r.out.info;
891
892                 for (j = 0; j < r.out.count; j++) {
893                         test_GetForm(p, mem_ctx, handle, info[j].info1.form_name);
894                 }
895         }
896
897         if (!NT_STATUS_IS_OK(status)) {
898                 printf("EnumForms failed - %s\n", nt_errstr(status));
899                 return False;
900         }
901
902         if (!W_ERROR_IS_OK(r.out.result)) {
903                 printf("EnumForms failed - %s\n", win_errstr(r.out.result));
904                 return False;
905         }
906
907         return True;
908 }
909
910 static BOOL test_DeleteForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
911                             struct policy_handle *handle, 
912                             const char *form_name)
913 {
914         NTSTATUS status;
915         struct spoolss_DeleteForm r;
916
917         r.in.handle = handle;
918         r.in.form_name = form_name;
919
920         status = dcerpc_spoolss_DeleteForm(p, mem_ctx, &r);
921
922         if (!NT_STATUS_IS_OK(status)) {
923                 printf("DeleteForm failed - %s\n", nt_errstr(status));
924                 return False;
925         }
926
927         if (!W_ERROR_IS_OK(r.out.result)) {
928                 printf("DeleteForm failed - %s\n", win_errstr(r.out.result));
929                 return False;
930         }
931
932         return True;
933 }
934
935 static BOOL test_AddForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
936                   struct policy_handle *handle)
937 {
938         struct spoolss_AddForm r;
939         struct spoolss_AddFormInfo1 addform;
940         const char *form_name = "testform3";
941         NTSTATUS status;
942         BOOL ret = True;
943
944         r.in.handle     = handle;
945         r.in.level      = 1;
946         r.in.info.info1 = &addform;
947         addform.flags           = SPOOLSS_FORM_USER;
948         addform.form_name       = form_name;
949         addform.size.width      = 50;
950         addform.size.height     = 25;
951         addform.area.left       = 5;
952         addform.area.top        = 10;
953         addform.area.right      = 45;
954         addform.area.bottom     = 15;
955
956         status = dcerpc_spoolss_AddForm(p, mem_ctx, &r);
957
958         if (!NT_STATUS_IS_OK(status)) {
959                 printf("AddForm failed - %s\n", nt_errstr(status));
960                 return False;
961         }
962
963         if (!W_ERROR_IS_OK(r.out.result)) {
964                 printf("AddForm failed - %s\n", nt_errstr(status));
965                 goto done;
966         }
967
968         {
969                 struct spoolss_SetForm sf;
970                 struct spoolss_AddFormInfo1 setform;
971
972                 sf.in.handle    = handle;
973                 sf.in.form_name = form_name;
974                 sf.in.level     = 1;
975                 sf.in.info.info1= &setform;
976                 setform.flags           = addform.flags;
977                 setform.form_name       = addform.form_name;
978                 setform.size            = addform.size;
979                 setform.area            = addform.area;
980
981                 setform.size.width      = 1234;
982
983                 status = dcerpc_spoolss_SetForm(p, mem_ctx, &sf);
984
985                 if (!NT_STATUS_IS_OK(status)) {
986                         printf("SetForm failed - %s\n", nt_errstr(status));
987                         ret = False;
988                         goto done;
989                 }
990
991                 if (!W_ERROR_IS_OK(r.out.result)) {
992                         printf("SetForm failed - %s\n", 
993                                win_errstr(r.out.result));
994                         ret = False;
995                         goto done;
996                 }
997         }
998
999  done:
1000         if (!test_DeleteForm(p, mem_ctx, handle, form_name)) {
1001                 printf("DeleteForm failed\n");
1002                 ret = False;
1003         }
1004
1005         return ret;
1006 }
1007
1008 static BOOL test_EnumPorts_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1009 {
1010         NTSTATUS status;
1011         struct spoolss_EnumPorts r;
1012
1013         r.in.servername = talloc_asprintf(mem_ctx, "\\\\%s", 
1014                                           dcerpc_server_name(p));
1015         r.in.level = 2;
1016         r.in.buffer = NULL;
1017         r.in.offered = 0;
1018
1019         printf("Testing EnumPorts\n");
1020
1021         status = dcerpc_spoolss_EnumPorts(p, mem_ctx, &r);
1022
1023         if (!NT_STATUS_IS_OK(status)) {
1024                 printf("EnumPorts failed - %s\n", nt_errstr(status));
1025                 return False;
1026         }
1027
1028         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1029                 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
1030                 data_blob_clear(&blob);
1031                 r.in.buffer = &blob;
1032                 r.in.offered = r.out.needed;
1033
1034                 status = dcerpc_spoolss_EnumPorts(p, mem_ctx, &r);
1035                 if (!NT_STATUS_IS_OK(status)) {
1036                         printf("EnumPorts failed - %s\n", nt_errstr(status));
1037                         return False;
1038                 }
1039
1040                 if (!r.out.info) {
1041                         printf("No ports returned\n");
1042                         return False;
1043                 }
1044         }
1045
1046         return True;
1047 }
1048
1049 static BOOL test_AddPort(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1050 {
1051         NTSTATUS status;
1052         struct spoolss_AddPort r;
1053
1054         r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", 
1055                                            dcerpc_server_name(p));
1056         r.in.unknown = 0;
1057         r.in.monitor_name = "foo";
1058
1059         printf ("Testing AddPort\n");
1060
1061         status = dcerpc_spoolss_AddPort(p, mem_ctx, &r);
1062
1063         if (!NT_STATUS_IS_OK(status)) {
1064                 printf("AddPort failed - %s\n", nt_errstr(status));
1065                 return False;
1066         }
1067
1068         /* win2k3 returns WERR_NOT_SUPPORTED */
1069
1070 #if 0
1071
1072         if (!W_ERROR_IS_OK(r.out.result)) {
1073                 printf("AddPort failed - %s\n", win_errstr(r.out.result));
1074                 return False;
1075         }
1076
1077 #endif
1078
1079         return True;
1080 }
1081
1082 static BOOL test_GetJob(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1083                   struct policy_handle *handle, uint32_t job_id)
1084 {
1085         NTSTATUS status;
1086         struct spoolss_GetJob r;
1087
1088         r.in.handle = handle;
1089         r.in.job_id = job_id;
1090         r.in.level = 1;
1091         r.in.buffer = NULL;
1092         r.in.offered = 0;
1093
1094         printf("Testing GetJob\n");
1095
1096         status = dcerpc_spoolss_GetJob(p, mem_ctx, &r);
1097         if (!NT_STATUS_IS_OK(status)) {
1098                 printf("GetJob failed - %s\n", nt_errstr(status));
1099                 return False;
1100         }
1101
1102         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1103                 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
1104                 data_blob_clear(&blob);
1105                 r.in.buffer = &blob;
1106                 r.in.offered = r.out.needed;
1107
1108                 status = dcerpc_spoolss_GetJob(p, mem_ctx, &r);
1109
1110                 if (!r.out.info) {
1111                         printf("No job info returned\n");
1112                         return False;
1113                 }
1114         }
1115
1116         return True;
1117 }
1118
1119 static BOOL test_SetJob(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1120                  struct policy_handle *handle, uint32_t job_id, enum spoolss_JobControl command)
1121 {
1122         NTSTATUS status;
1123         struct spoolss_SetJob r;
1124
1125         r.in.handle     = handle;
1126         r.in.job_id     = job_id;
1127         r.in.ctr        = NULL;
1128         r.in.command    = command;
1129
1130         printf("Testing SetJob\n");
1131
1132         status = dcerpc_spoolss_SetJob(p, mem_ctx, &r);
1133         if (!NT_STATUS_IS_OK(status)) {
1134                 printf("SetJob failed - %s\n", nt_errstr(status));
1135                 return False;
1136         }
1137         if (!W_ERROR_IS_OK(r.out.result)) {
1138                 printf("SetJob failed - %s\n", win_errstr(r.out.result));
1139                 return False;
1140         }
1141
1142         return True;
1143 }
1144
1145 static BOOL test_EnumJobs(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1146                    struct policy_handle *handle)
1147 {
1148         NTSTATUS status;
1149         struct spoolss_EnumJobs r;
1150
1151         r.in.handle = handle;
1152         r.in.firstjob = 0;
1153         r.in.numjobs = 0xffffffff;
1154         r.in.level = 1;
1155         r.in.buffer = NULL;
1156         r.in.offered = 0;
1157
1158         printf("Testing EnumJobs\n");
1159
1160         status = dcerpc_spoolss_EnumJobs(p, mem_ctx, &r);
1161
1162         if (!NT_STATUS_IS_OK(status)) {
1163                 printf("EnumJobs failed - %s\n", nt_errstr(status));
1164                 return False;
1165         }
1166
1167         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1168                 union spoolss_JobInfo *info;
1169                 int j;
1170                 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
1171                 data_blob_clear(&blob);
1172                 r.in.buffer = &blob;
1173                 r.in.offered = r.out.needed;
1174
1175                 status = dcerpc_spoolss_EnumJobs(p, mem_ctx, &r);
1176
1177                 if (!r.out.info) {
1178                         printf("No jobs returned\n");
1179                         return True;
1180                 }
1181
1182                 info = r.out.info;
1183
1184                 for (j = 0; j < r.out.count; j++) {
1185                         test_GetJob(p, mem_ctx, handle, info[j].info1.job_id);
1186                         test_SetJob(p, mem_ctx, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
1187                         test_SetJob(p, mem_ctx, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
1188                 }
1189
1190         } else if (!W_ERROR_IS_OK(r.out.result)) {
1191                 printf("EnumJobs failed - %s\n", win_errstr(r.out.result));
1192                 return False;
1193         }
1194
1195         return True;
1196 }
1197
1198 static BOOL test_DoPrintTest(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1199                    struct policy_handle *handle)
1200 {
1201         BOOL ret = True;
1202         NTSTATUS status;
1203         struct spoolss_StartDocPrinter s;
1204         struct spoolss_DocumentInfo1 info1;
1205         struct spoolss_StartPagePrinter sp;
1206         struct spoolss_WritePrinter w;
1207         struct spoolss_EndPagePrinter ep;
1208         struct spoolss_EndDocPrinter e;
1209         int i;
1210         uint32_t job_id;
1211
1212         printf("Testing StartDocPrinter\n");
1213
1214         s.in.handle             = handle;
1215         s.in.level              = 1;
1216         s.in.info.info1         = &info1;
1217         info1.document_name     = "TorturePrintJob";
1218         info1.output_file       = NULL;
1219         info1.datatype          = "RAW";
1220
1221         status = dcerpc_spoolss_StartDocPrinter(p, mem_ctx, &s);
1222         if (!NT_STATUS_IS_OK(status)) {
1223                 printf("dcerpc_spoolss_StartDocPrinter failed - %s\n", nt_errstr(status));
1224                 return False;
1225         }
1226         if (!W_ERROR_IS_OK(s.out.result)) {
1227                 printf("StartDocPrinter failed - %s\n", win_errstr(s.out.result));
1228                 return False;
1229         }
1230
1231         job_id = s.out.job_id;
1232
1233         for (i=1; i < 4; i++) {
1234                 printf("Testing StartPagePrinter: Page[%d]\n", i);
1235
1236                 sp.in.handle            = handle;
1237
1238                 status = dcerpc_spoolss_StartPagePrinter(p, mem_ctx, &sp);
1239                 if (!NT_STATUS_IS_OK(status)) {
1240                         printf("dcerpc_spoolss_StartPagePrinter failed - %s\n", nt_errstr(status));
1241                         return False;
1242                 }
1243                 if (!W_ERROR_IS_OK(sp.out.result)) {
1244                         printf("StartPagePrinter failed - %s\n", win_errstr(sp.out.result));
1245                         return False;
1246                 }
1247
1248                 printf("Testing WritePrinter: Page[%d]\n", i);
1249
1250                 w.in.handle             = handle;
1251                 w.in.data               = data_blob_string_const(talloc_asprintf(mem_ctx,"TortureTestPage: %d\nData\n",i));
1252
1253                 status = dcerpc_spoolss_WritePrinter(p, mem_ctx, &w);
1254                 if (!NT_STATUS_IS_OK(status)) {
1255                         printf("dcerpc_spoolss_WritePrinter failed - %s\n", nt_errstr(status));
1256                         return False;
1257                 }
1258                 if (!W_ERROR_IS_OK(w.out.result)) {
1259                         printf("WritePrinter failed - %s\n", win_errstr(w.out.result));
1260                         return False;
1261                 }
1262
1263                 printf("Testing EndPagePrinter: Page[%d]\n", i);
1264
1265                 ep.in.handle            = handle;
1266
1267                 status = dcerpc_spoolss_EndPagePrinter(p, mem_ctx, &ep);
1268                 if (!NT_STATUS_IS_OK(status)) {
1269                         printf("dcerpc_spoolss_EndPagePrinter failed - %s\n", nt_errstr(status));
1270                         return False;
1271                 }
1272                 if (!W_ERROR_IS_OK(ep.out.result)) {
1273                         printf("EndPagePrinter failed - %s\n", win_errstr(ep.out.result));
1274                         return False;
1275                 }
1276         }
1277
1278         printf("Testing EndDocPrinter\n");
1279
1280         e.in.handle = handle;
1281
1282         status = dcerpc_spoolss_EndDocPrinter(p, mem_ctx, &e);
1283         if (!NT_STATUS_IS_OK(status)) {
1284                 printf("dcerpc_spoolss_EndDocPrinter failed - %s\n", nt_errstr(status));
1285                 return False;
1286         }
1287         if (!W_ERROR_IS_OK(e.out.result)) {
1288                 printf("EndDocPrinter failed - %s\n", win_errstr(e.out.result));
1289                 return False;
1290         }
1291
1292         ret &= test_EnumJobs(p, mem_ctx, handle);
1293
1294         ret &= test_SetJob(p, mem_ctx, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
1295
1296         return ret;
1297 }
1298
1299 static BOOL test_PausePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1300                    struct policy_handle *handle)
1301 {
1302         NTSTATUS status;
1303         struct spoolss_SetPrinter r;
1304
1305         r.in.handle             = handle;
1306         r.in.level              = 0;
1307         r.in.info.info1         = NULL;
1308         r.in.devmode_ctr.size   = 0;
1309         r.in.devmode_ctr.devmode= NULL;
1310         r.in.secdesc_ctr.size   = 0;
1311         r.in.secdesc_ctr.sd     = NULL;
1312         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
1313
1314         printf("Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1315
1316         status = dcerpc_spoolss_SetPrinter(p, mem_ctx, &r);
1317
1318         if (!NT_STATUS_IS_OK(status)) {
1319                 printf("SetPrinter failed - %s\n", nt_errstr(status));
1320                 return False;
1321         }
1322
1323         if (!W_ERROR_IS_OK(r.out.result)) {
1324                 printf("SetPrinter failed - %s\n", win_errstr(r.out.result));
1325                 return False;
1326         }
1327
1328         return True;
1329 }
1330
1331 static BOOL test_ResumePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1332                    struct policy_handle *handle)
1333 {
1334         NTSTATUS status;
1335         struct spoolss_SetPrinter r;
1336
1337         r.in.handle             = handle;
1338         r.in.level              = 0;
1339         r.in.info.info1         = NULL;
1340         r.in.devmode_ctr.size   = 0;
1341         r.in.devmode_ctr.devmode= NULL;
1342         r.in.secdesc_ctr.size   = 0;
1343         r.in.secdesc_ctr.sd     = NULL;
1344         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
1345
1346         printf("Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
1347
1348         status = dcerpc_spoolss_SetPrinter(p, mem_ctx, &r);
1349
1350         if (!NT_STATUS_IS_OK(status)) {
1351                 printf("SetPrinter failed - %s\n", nt_errstr(status));
1352                 return False;
1353         }
1354
1355         if (!W_ERROR_IS_OK(r.out.result)) {
1356                 printf("SetPrinter failed - %s\n", win_errstr(r.out.result));
1357                 return False;
1358         }
1359
1360         return True;
1361 }
1362
1363 static BOOL test_GetPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1364                                 struct policy_handle *handle, 
1365                                 const char *value_name)
1366 {
1367         NTSTATUS status;
1368         struct spoolss_GetPrinterData r;
1369
1370         r.in.handle = handle;
1371         r.in.value_name = value_name;
1372         r.in.offered = 0;
1373
1374         printf("Testing GetPrinterData\n");
1375
1376         status = dcerpc_spoolss_GetPrinterData(p, mem_ctx, &r);
1377         if (!NT_STATUS_IS_OK(status)) {
1378                 printf("GetPrinterData failed - %s\n", nt_errstr(status));
1379                 return False;
1380         }
1381
1382         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1383                 r.in.offered = r.out.needed;
1384
1385                 status = dcerpc_spoolss_GetPrinterData(p, mem_ctx, &r);
1386                 if (!NT_STATUS_IS_OK(status)) {
1387                         printf("GetPrinterData failed - %s\n", 
1388                                nt_errstr(status));
1389                         return False;
1390                 }
1391
1392                 if (!W_ERROR_IS_OK(r.out.result)) {
1393                         printf("GetPrinterData failed - %s\n", 
1394                                win_errstr(r.out.result));
1395                         return False;
1396                 }
1397         }
1398
1399         return True;
1400 }
1401
1402 static BOOL test_GetPrinterDataEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1403                                   struct policy_handle *handle, 
1404                                   const char *key_name,
1405                                   const char *value_name)
1406 {
1407         NTSTATUS status;
1408         struct spoolss_GetPrinterDataEx r;
1409
1410         r.in.handle = handle;
1411         r.in.key_name = key_name;
1412         r.in.value_name = value_name;
1413         r.in.offered = 0;
1414
1415         printf("Testing GetPrinterDataEx\n");
1416
1417         status = dcerpc_spoolss_GetPrinterDataEx(p, mem_ctx, &r);
1418         if (!NT_STATUS_IS_OK(status)) {
1419                 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
1420                     p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1421                         printf("GetPrinterDataEx not supported by server\n");
1422                         return True;
1423                 }
1424                 printf("GetPrinterDataEx failed - %s\n", nt_errstr(status));
1425                 return False;
1426         }
1427
1428         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1429                 r.in.offered = r.out.needed;
1430
1431                 status = dcerpc_spoolss_GetPrinterDataEx(p, mem_ctx, &r);
1432                 if (!NT_STATUS_IS_OK(status)) {
1433                         printf("GetPrinterDataEx failed - %s\n", 
1434                                nt_errstr(status));
1435                         return False;
1436                 }
1437
1438                 if (!W_ERROR_IS_OK(r.out.result)) {
1439                         printf("GetPrinterDataEx failed - %s\n", 
1440                                win_errstr(r.out.result));
1441                         return False;
1442                 }
1443         }
1444
1445         return True;
1446 }
1447
1448 static BOOL test_EnumPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1449                                  struct policy_handle *handle)
1450 {
1451         NTSTATUS status;
1452         struct spoolss_EnumPrinterData r;
1453
1454         r.in.handle = handle;
1455         r.in.enum_index = 0;
1456
1457         do {
1458                 uint32_t data_size;
1459                 
1460                 r.in.value_offered = 0;
1461                 data_size = 0;
1462                 r.in.data_size = &data_size;
1463                 r.out.data_size = &data_size;
1464
1465                 printf("Testing EnumPrinterData\n");
1466
1467                 status = dcerpc_spoolss_EnumPrinterData(p, mem_ctx, &r);
1468
1469                 if (!NT_STATUS_IS_OK(status)) {
1470                         printf("EnumPrinterData failed - %s\n", nt_errstr(status));
1471                         return False;
1472                 }
1473
1474                 r.in.value_offered = r.out.value_needed;
1475
1476                 status = dcerpc_spoolss_EnumPrinterData(p, mem_ctx, &r);
1477
1478                 if (!NT_STATUS_IS_OK(status)) {
1479                         printf("EnumPrinterData failed - %s\n", nt_errstr(status));
1480                         return False;
1481                 }
1482                 
1483                 test_GetPrinterData(p, mem_ctx, handle, r.out.value_name);
1484
1485                 test_GetPrinterDataEx(
1486                         p, mem_ctx, handle, "PrinterDriverData", 
1487                         r.out.value_name);
1488
1489                 r.in.enum_index++;
1490
1491         } while (W_ERROR_IS_OK(r.out.result));
1492
1493         return True;
1494 }
1495
1496 static BOOL test_EnumPrinterDataEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1497                                    struct policy_handle *handle)
1498 {
1499         NTSTATUS status;
1500         struct spoolss_EnumPrinterDataEx r;
1501
1502         r.in.handle = handle;
1503         r.in.key_name = "PrinterDriverData";
1504         r.in.offered = 0;
1505
1506         printf("Testing EnumPrinterDataEx\n");
1507
1508         status = dcerpc_spoolss_EnumPrinterDataEx(p, mem_ctx, &r);
1509         if (!NT_STATUS_IS_OK(status)) {
1510                 printf("EnumPrinterDataEx failed - %s\n", nt_errstr(status));
1511                 return False;
1512         }
1513
1514         r.in.offered = r.out.needed;
1515
1516         status = dcerpc_spoolss_EnumPrinterDataEx(p, mem_ctx, &r);
1517
1518         if (!NT_STATUS_IS_OK(status)) {
1519                 printf("EnumPrinterDataEx failed - %s\n", nt_errstr(status));
1520                 return False;
1521         }
1522
1523         return True;
1524 }
1525
1526
1527 static BOOL test_DeletePrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1528                                    struct policy_handle *handle, 
1529                                    const char *value_name)
1530 {
1531         NTSTATUS status;
1532         struct spoolss_DeletePrinterData r;
1533
1534         r.in.handle = handle;
1535         r.in.value_name = value_name;
1536
1537         printf("Testing DeletePrinterData\n");
1538
1539         status = dcerpc_spoolss_DeletePrinterData(p, mem_ctx, &r);
1540
1541         if (!NT_STATUS_IS_OK(status)) {
1542                 printf("DeletePrinterData failed - %s\n", nt_errstr(status));
1543                 return False;
1544         }
1545
1546         return True;
1547 }
1548
1549 static BOOL test_SetPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1550                          struct policy_handle *handle)
1551 {
1552         NTSTATUS status;
1553         struct spoolss_SetPrinterData r;
1554         const char *value_name = "spottyfoot";
1555         
1556         r.in.handle = handle;
1557         r.in.value_name = value_name;
1558         r.in.type = SPOOLSS_PRINTER_DATA_TYPE_STRING;
1559         r.in.data.string = "dog";
1560
1561         printf("Testing SetPrinterData\n");
1562
1563         status = dcerpc_spoolss_SetPrinterData(p, mem_ctx, &r);
1564
1565         if (!NT_STATUS_IS_OK(status)) {
1566                 printf("SetPrinterData failed - %s\n", nt_errstr(status));
1567                 return False;
1568         }
1569
1570         if (!test_GetPrinterData(p, mem_ctx, handle, value_name)) {
1571                 return False;
1572         }
1573
1574         if (!test_DeletePrinterData(p, mem_ctx, handle, value_name)) {
1575                 return False;
1576         }
1577
1578         return True;
1579 }
1580
1581 static BOOL test_SecondaryClosePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1582                                        struct policy_handle *handle)
1583 {
1584         NTSTATUS status;
1585         struct dcerpc_binding *b;
1586         struct dcerpc_pipe *p2;
1587         BOOL ret = True;
1588
1589         /* only makes sense on SMB */
1590         if (p->conn->transport.transport != NCACN_NP) {
1591                 return True;
1592         }
1593
1594         printf("testing close on secondary pipe\n");
1595
1596         status = dcerpc_parse_binding(mem_ctx, p->conn->binding_string, &b);
1597         if (!NT_STATUS_IS_OK(status)) {
1598                 printf("Failed to parse dcerpc binding '%s'\n", p->conn->binding_string);
1599                 return False;
1600         }
1601
1602         status = dcerpc_secondary_connection(p, &p2, b);
1603         if (!NT_STATUS_IS_OK(status)) {
1604                 printf("Failed to create secondary connection\n");
1605                 return False;
1606         }
1607
1608         status = dcerpc_bind_auth_none(p2, DCERPC_SPOOLSS_UUID, 
1609                                        DCERPC_SPOOLSS_VERSION);
1610         if (!NT_STATUS_IS_OK(status)) {
1611                 printf("Failed to create bind on secondary connection\n");
1612                 talloc_free(p2);
1613
1614                 return False;
1615         }
1616
1617         if (test_ClosePrinter(p2, mem_ctx, handle)) {
1618                 printf("ERROR: Allowed close on secondary connection!\n");
1619                 ret = False;
1620         }
1621
1622         if (p2->last_fault_code != DCERPC_FAULT_CONTEXT_MISMATCH) {
1623                 printf("Unexpected fault code 0x%x - expected 0x%x\n",
1624                        p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH);
1625                 ret = False;
1626         }
1627
1628         talloc_free(p2);
1629
1630         return ret;
1631 }
1632
1633 static BOOL test_OpenPrinter_badname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, const char *name)
1634 {
1635         NTSTATUS status;
1636         struct spoolss_OpenPrinter op;
1637         struct spoolss_OpenPrinterEx opEx;
1638         struct policy_handle handle;
1639         BOOL ret = True;
1640
1641         op.in.printername       = name;
1642         op.in.datatype          = NULL;
1643         op.in.devmode_ctr.size  = 0;
1644         op.in.devmode_ctr.devmode= NULL;
1645         op.in.access_mask       = 0;
1646         op.out.handle           = &handle;
1647
1648         printf("\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
1649
1650         status = dcerpc_spoolss_OpenPrinter(p, mem_ctx, &op);
1651         if (!NT_STATUS_IS_OK(status)) {
1652                 printf("OpenPrinter failed - %s\n", nt_errstr(status));
1653                 ret = False;
1654         }
1655         if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
1656                 printf("OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
1657                         name, win_errstr(op.out.result));
1658         }
1659
1660         if (W_ERROR_IS_OK(op.out.result)) {
1661                 ret &=test_ClosePrinter(p, mem_ctx, &handle);
1662         }
1663
1664         opEx.in.printername             = name;
1665         opEx.in.datatype                = NULL;
1666         opEx.in.devmode_ctr.size        = 0;
1667         opEx.in.devmode_ctr.devmode     = NULL;
1668         opEx.in.access_mask             = 0;
1669         opEx.in.level                   = 1;
1670         opEx.in.userlevel.level1        = NULL;
1671         opEx.out.handle                 = &handle;
1672
1673         printf("\nTesting OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
1674
1675         status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &opEx);
1676         if (!NT_STATUS_IS_OK(status)) {
1677                 printf("OpenPrinter failed - %s\n", nt_errstr(status));
1678                 ret = False;
1679         }
1680         if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,opEx.out.result)) {
1681                 printf("OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
1682                         name, win_errstr(opEx.out.result));
1683         }
1684
1685         if (W_ERROR_IS_OK(opEx.out.result)) {
1686                 ret &=test_ClosePrinter(p, mem_ctx, &handle);
1687         }
1688
1689         return ret;
1690 }
1691
1692 static BOOL test_OpenPrinter_badnames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1693 {
1694         BOOL ret = True;
1695         char *name;
1696
1697         ret &= test_OpenPrinter_badname(p, mem_ctx, "__INVALID_PRINTER__");
1698         ret &= test_OpenPrinter_badname(p, mem_ctx, "\\\\__INVALID_HOST__");
1699         ret &= test_OpenPrinter_badname(p, mem_ctx, "");
1700         ret &= test_OpenPrinter_badname(p, mem_ctx, "\\\\\\");
1701         ret &= test_OpenPrinter_badname(p, mem_ctx, "\\\\\\__INVALID_PRINTER__");
1702
1703         name = talloc_asprintf(mem_ctx, "\\\\%s\\", dcerpc_server_name(p));
1704         ret &= test_OpenPrinter_badname(p, mem_ctx, name);
1705         talloc_free(name);
1706
1707         name = talloc_asprintf(mem_ctx, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p));
1708         ret &= test_OpenPrinter_badname(p, mem_ctx, name);
1709         talloc_free(name);
1710
1711         return ret;
1712 }
1713
1714 static BOOL test_OpenPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1715                              const char *name)
1716 {
1717         NTSTATUS status;
1718         struct spoolss_OpenPrinter r;
1719         struct policy_handle handle;
1720         BOOL ret = True;
1721
1722         r.in.printername        = talloc_asprintf(mem_ctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
1723         r.in.datatype           = NULL;
1724         r.in.devmode_ctr.size   = 0;
1725         r.in.devmode_ctr.devmode= NULL;
1726         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
1727         r.out.handle            = &handle;
1728
1729         printf("\nTesting OpenPrinter(%s)\n", r.in.printername);
1730
1731         status = dcerpc_spoolss_OpenPrinter(p, mem_ctx, &r);
1732
1733         if (!NT_STATUS_IS_OK(status)) {
1734                 printf("OpenPrinter failed - %s\n", nt_errstr(status));
1735                 return False;
1736         }
1737
1738         if (!W_ERROR_IS_OK(r.out.result)) {
1739                 printf("OpenPrinter failed - %s\n", win_errstr(r.out.result));
1740                 return False;
1741         }
1742
1743         if (!test_GetPrinter(p, mem_ctx, &handle)) {
1744                 ret = False;
1745         }
1746
1747         if (!test_SecondaryClosePrinter(p, mem_ctx, &handle)) {
1748                 ret = False;
1749         }
1750
1751         if (!test_ClosePrinter(p, mem_ctx, &handle)) {
1752                 ret = False;
1753         }
1754
1755         return ret;
1756 }
1757
1758 static BOOL call_OpenPrinterEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1759                                const char *name, struct policy_handle *handle)
1760 {
1761         struct spoolss_OpenPrinterEx r;
1762         struct spoolss_UserLevel1 userlevel1;
1763         NTSTATUS status;
1764
1765         if (name && name[0]) {
1766                 r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s", 
1767                                                    dcerpc_server_name(p), name);
1768         } else {
1769                 r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s", 
1770                                                    dcerpc_server_name(p));
1771         }
1772
1773         r.in.datatype           = NULL;
1774         r.in.devmode_ctr.size   = 0;
1775         r.in.devmode_ctr.devmode= NULL;
1776         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
1777         r.in.level              = 1;
1778         r.in.userlevel.level1   = &userlevel1;
1779         r.out.handle = handle;
1780
1781         userlevel1.size = 1234;
1782         userlevel1.client = "hello";
1783         userlevel1.user = "spottyfoot!";
1784         userlevel1.build = 1;
1785         userlevel1.major = 2;
1786         userlevel1.minor = 3;
1787         userlevel1.processor = 4;
1788
1789         printf("Testing OpenPrinterEx(%s)\n", r.in.printername);
1790
1791         status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &r);
1792
1793         if (!NT_STATUS_IS_OK(status)) {
1794                 printf("OpenPrinterEx failed - %s\n", nt_errstr(status));
1795                 return False;
1796         }
1797         
1798         if (!W_ERROR_IS_OK(r.out.result)) {
1799                 printf("OpenPrinterEx failed - %s\n", win_errstr(r.out.result));
1800                 return False;
1801         }
1802
1803         return True;
1804 }
1805
1806 static BOOL test_OpenPrinterEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1807                                const char *name)
1808 {
1809         struct policy_handle handle;
1810         BOOL ret = True;
1811
1812         if (!call_OpenPrinterEx(p, mem_ctx, name, &handle)) {
1813                 return False;
1814         }
1815
1816         if (!test_GetPrinter(p, mem_ctx, &handle)) {
1817                 ret = False;
1818         }
1819
1820         if (!test_EnumForms(p, mem_ctx, &handle, False)) {
1821                 ret = False;
1822         }
1823
1824         if (!test_AddForm(p, mem_ctx, &handle)) {
1825                 ret = False;
1826         }
1827
1828         if (!test_EnumPrinterData(p, mem_ctx, &handle)) {
1829                 ret = False;
1830         }
1831
1832         if (!test_EnumPrinterDataEx(p, mem_ctx, &handle)) {
1833                 ret = False;
1834         }
1835
1836         if (!test_PausePrinter(p, mem_ctx, &handle)) {
1837                 ret = False;
1838         }
1839
1840         if (!test_DoPrintTest(p, mem_ctx, &handle)) {
1841                 ret = False;
1842         }
1843
1844         if (!test_ResumePrinter(p, mem_ctx, &handle)) {
1845                 ret = False;
1846         }
1847
1848         if (!test_SetPrinterData(p, mem_ctx, &handle)) {
1849                 ret = False;
1850         }
1851
1852         if (!test_SecondaryClosePrinter(p, mem_ctx, &handle)) {
1853                 ret = False;
1854         }
1855
1856         if (!test_ClosePrinter(p, mem_ctx, &handle)) {
1857                 ret = False;
1858         }
1859         
1860         return ret;
1861 }
1862
1863 static BOOL test_EnumPrinters_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1864 {
1865         struct spoolss_EnumPrinters r;
1866         NTSTATUS status;
1867         uint16_t levels[] = {1, 2, 4, 5};
1868         int i;
1869         BOOL ret = True;
1870
1871         for (i=0;i<ARRAY_SIZE(levels);i++) {
1872                 union spoolss_PrinterInfo *info;
1873                 int j;
1874
1875                 r.in.flags      = PRINTER_ENUM_LOCAL;
1876                 r.in.server     = "";
1877                 r.in.level      = levels[i];
1878                 r.in.buffer     = NULL;
1879                 r.in.offered    = 0;
1880
1881                 printf("\nTesting EnumPrinters level %u\n", r.in.level);
1882
1883                 status = dcerpc_spoolss_EnumPrinters(p, mem_ctx, &r);
1884                 if (!NT_STATUS_IS_OK(status)) {
1885                         printf("EnumPrinters failed - %s\n", nt_errstr(status));
1886                         ret = False;
1887                         continue;
1888                 }
1889
1890                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1891                         DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
1892                         data_blob_clear(&blob);
1893                         r.in.buffer = &blob;
1894                         r.in.offered = r.out.needed;
1895                         status = dcerpc_spoolss_EnumPrinters(p, mem_ctx, &r);
1896                 }
1897
1898                 if (!NT_STATUS_IS_OK(status)) {
1899                         printf("EnumPrinters failed - %s\n", 
1900                                nt_errstr(status));
1901                         continue;
1902                 }
1903
1904                 if (!W_ERROR_IS_OK(r.out.result)) {
1905                         printf("EnumPrinters failed - %s\n", 
1906                                win_errstr(r.out.result));
1907                         continue;
1908                 }
1909
1910                 if (!r.out.info) {
1911                         printf("No printers returned\n");
1912                         continue;
1913                 }
1914
1915                 info = r.out.info;
1916
1917                 for (j=0;j<r.out.count;j++) {
1918                         if (r.in.level == 1) {
1919                                 /* the names appear to be comma-separated name lists? */
1920                                 char *name = talloc_strdup(mem_ctx, info[j].info1.name);
1921                                 char *comma = strchr(name, ',');
1922                                 if (comma) *comma = 0;
1923                                 if (!test_OpenPrinter(p, mem_ctx, name)) {
1924                                         ret = False;
1925                                 }
1926                                 if (!test_OpenPrinterEx(p, mem_ctx, name)) {
1927                                         ret = False;
1928                                 }
1929                         }
1930                 }
1931         }
1932
1933         return ret;
1934 }
1935
1936 #if 0
1937 static BOOL test_GetPrinterDriver2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1938                                    struct policy_handle *handle, 
1939                                    const char *driver_name)
1940 {
1941         NTSTATUS status;
1942         struct spoolss_GetPrinterDriver2 r;
1943
1944         r.in.handle = handle;
1945         r.in.architecture = "W32X86";
1946         r.in.level = 1;
1947         r.in.buffer = NULL;
1948         r.in.offered = 0;
1949         r.in.client_major_version = 0;
1950         r.in.client_minor_version = 0;
1951
1952         printf("Testing GetPrinterDriver2\n");
1953
1954         status = dcerpc_spoolss_GetPrinterDriver2(p, mem_ctx, &r);
1955         if (!NT_STATUS_IS_OK(status)) {
1956                 printf("GetPrinterDriver2 failed - %s\n", nt_errstr(status));
1957                 return False;
1958         }
1959
1960         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1961                 r.in.offered = r.out.needed;
1962                 status = dcerpc_spoolss_GetPrinterDriver2(p, mem_ctx, &r);
1963         }
1964                 
1965         if (!NT_STATUS_IS_OK(status)) {
1966                 printf("GetPrinterDriver2 failed - %s\n", 
1967                        nt_errstr(status));
1968                 return False;
1969         }
1970
1971         if (!W_ERROR_IS_OK(r.out.result)) {
1972                 printf("GetPrinterDriver2 failed - %s\n", 
1973                        win_errstr(r.out.result));
1974                 return False;
1975         }
1976
1977         return True;
1978 }
1979 #endif
1980
1981 static BOOL test_EnumPrinterDrivers_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1982 {
1983         struct spoolss_EnumPrinterDrivers r;
1984         NTSTATUS status;
1985         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
1986         int i;
1987         BOOL ret = True;
1988
1989         for (i=0;i<ARRAY_SIZE(levels);i++) {
1990
1991                 r.in.server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1992                 r.in.environment = "Windows NT x86";
1993                 r.in.level = levels[i];
1994                 r.in.buffer = NULL;
1995                 r.in.offered = 0;
1996
1997                 printf("\nTesting EnumPrinterDrivers level %u\n", r.in.level);
1998
1999                 status = dcerpc_spoolss_EnumPrinterDrivers(p, mem_ctx, &r);
2000
2001                 if (!NT_STATUS_IS_OK(status)) {
2002                         printf("EnumPrinterDrivers failed - %s\n", 
2003                                nt_errstr(status));
2004                         ret = False;
2005                         continue;
2006                 }
2007
2008                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2009                         DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
2010                         data_blob_clear(&blob);
2011                         r.in.buffer = &blob;
2012                         r.in.offered = r.out.needed;
2013                         status = dcerpc_spoolss_EnumPrinterDrivers(p, mem_ctx, &r);
2014                 }
2015
2016                 if (!NT_STATUS_IS_OK(status)) {
2017                         printf("EnumPrinterDrivers failed - %s\n", 
2018                                nt_errstr(status));
2019                         ret = False;
2020                         break;
2021                 }
2022
2023                 if (!W_ERROR_IS_OK(r.out.result)) {
2024                         printf("EnumPrinterDrivers failed - %s\n", 
2025                                win_errstr(r.out.result));
2026                         ret = False;
2027                         break;
2028                 }
2029
2030                 if (!r.out.info) {
2031                         printf("No printer drivers returned\n");
2032                         break;
2033                 }
2034         }
2035
2036         return ret;
2037 }
2038
2039 BOOL torture_rpc_spoolss(void)
2040 {
2041         NTSTATUS status;
2042         struct dcerpc_pipe *p;
2043         TALLOC_CTX *mem_ctx;
2044         BOOL ret = True;
2045         struct test_spoolss_context *ctx;
2046
2047         mem_ctx = talloc_init("torture_rpc_spoolss");
2048
2049         status = torture_rpc_connection(mem_ctx, 
2050                                         &p, 
2051                                         DCERPC_SPOOLSS_NAME,
2052                                         DCERPC_SPOOLSS_UUID,
2053                                         DCERPC_SPOOLSS_VERSION);
2054         if (!NT_STATUS_IS_OK(status)) {
2055                 talloc_free(mem_ctx);
2056                 return False;
2057         }
2058
2059         ctx = talloc_zero(mem_ctx, struct test_spoolss_context);
2060         ctx->p  = p;
2061
2062         ret &= test_OpenPrinter_server(ctx);
2063
2064         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "W3SvcInstalled");
2065         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "BeepEnabled");
2066         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "EventLog");
2067         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "NetPopup");
2068         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "NetPopupToComputer");
2069         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "MajorVersion");
2070         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "MinorVersion");
2071         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "DefaultSpoolDirectory");
2072         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "Architecture");
2073         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "DsPresent");
2074
2075         ret &= test_EnumForms(ctx->p, ctx, &ctx->server_handle, True);
2076
2077         ret &= test_EnumPorts(ctx);
2078
2079         ret &= test_GetPrinterDriverDirectory(ctx);
2080
2081         ret &= test_EnumPrinterDrivers(ctx);
2082
2083         ret &= test_EnumMonitors(ctx);
2084
2085         ret &= test_EnumPrintProcessors(ctx);
2086
2087         ret &= test_EnumPrinters(ctx);
2088
2089         ret &= test_OpenPrinter_badnames(p, mem_ctx);
2090
2091         ret &= test_AddPort(p, mem_ctx);
2092
2093         ret &= test_EnumPorts_old(p, mem_ctx);
2094
2095         ret &= test_EnumPrinters_old(p, mem_ctx);
2096
2097         ret &= test_EnumPrinterDrivers_old(p, mem_ctx);
2098
2099         talloc_free(mem_ctx);
2100
2101         return ret;
2102 }