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