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