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