r7120: make use of the new 'noopnum' property and get rid of handwritten
[samba.git] / source / 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, uint32_t 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.level = 0;
1057         r.in.command = command;
1058
1059         printf("Testing SetJob\n");
1060
1061         status = dcerpc_spoolss_SetJob(p, mem_ctx, &r);
1062
1063         if (!NT_STATUS_IS_OK(status)) {
1064                 printf("SetJob failed - %s\n", nt_errstr(status));
1065                 return False;
1066         }
1067
1068         return True;
1069 }
1070
1071 static BOOL test_EnumJobs(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1072                    struct policy_handle *handle)
1073 {
1074         NTSTATUS status;
1075         struct spoolss_EnumJobs r;
1076         uint32_t buf_size;
1077
1078         r.in.handle = handle;
1079         r.in.firstjob = 0;
1080         r.in.numjobs = 0xffffffff;
1081         r.in.level = 1;
1082         r.in.buffer = NULL;
1083         buf_size = 0;
1084         r.in.buf_size = &buf_size;
1085         r.out.buf_size = &buf_size;
1086
1087         printf("Testing EnumJobs\n");
1088
1089         status = dcerpc_spoolss_EnumJobs(p, mem_ctx, &r);
1090
1091         if (!NT_STATUS_IS_OK(status)) {
1092                 printf("EnumJobs failed - %s\n", nt_errstr(status));
1093                 return False;
1094         }
1095
1096         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1097                 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
1098                 union spoolss_JobInfo *info;
1099                 int j;
1100
1101                 data_blob_clear(&blob);
1102                 r.in.buffer = &blob;
1103
1104                 status = dcerpc_spoolss_EnumJobs(p, mem_ctx, &r);
1105
1106                 if (!r.out.info) {
1107                         printf("No jobs returned");
1108                         return True;
1109                 }
1110
1111                 info = r.out.info;
1112
1113                 for (j = 0; j < r.out.count; j++) {
1114                         test_GetJob(p, mem_ctx, handle, info[j].info1.job_id);
1115                         test_SetJob(p, mem_ctx, handle, info[j].info1.job_id, 1);
1116                 }
1117
1118         } else if (!W_ERROR_IS_OK(r.out.result)) {
1119                 printf("EnumJobs failed - %s\n", win_errstr(r.out.result));
1120                 return False;
1121         }
1122
1123         return True;
1124 }
1125
1126 static BOOL test_GetPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1127                                 struct policy_handle *handle, 
1128                                 const char *value_name)
1129 {
1130         NTSTATUS status;
1131         struct spoolss_GetPrinterData r;
1132         uint32_t buf_size;
1133
1134         r.in.handle = handle;
1135         r.in.value_name = value_name;
1136         buf_size = 0;
1137         r.in.buf_size = r.out.buf_size = &buf_size;
1138
1139         printf("Testing GetPrinterData\n");
1140
1141         status = dcerpc_spoolss_GetPrinterData(p, mem_ctx, &r);
1142
1143         if (!NT_STATUS_IS_OK(status)) {
1144                 printf("GetPrinterData failed - %s\n", nt_errstr(status));
1145                 return False;
1146         }
1147
1148         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1149
1150                 status = dcerpc_spoolss_GetPrinterData(p, mem_ctx, &r);
1151
1152                 if (!NT_STATUS_IS_OK(status)) {
1153                         printf("GetPrinterData failed - %s\n", 
1154                                nt_errstr(status));
1155                         return False;
1156                 }
1157
1158                 if (!W_ERROR_IS_OK(r.out.result)) {
1159                         printf("GetPrinterData failed - %s\n", 
1160                                win_errstr(r.out.result));
1161                         return False;
1162                 }
1163         }
1164
1165         return True;
1166 }
1167
1168 static BOOL test_GetPrinterDataEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1169                                   struct policy_handle *handle, 
1170                                   const char *key_name,
1171                                   const char *value_name)
1172 {
1173         NTSTATUS status;
1174         struct spoolss_GetPrinterDataEx r;
1175         uint32_t buf_size;
1176
1177         r.in.handle = handle;
1178         r.in.key_name = key_name;
1179         r.in.value_name = value_name;
1180         buf_size = 0;
1181         r.in.buf_size = r.out.buf_size = &buf_size;
1182
1183         printf("Testing GetPrinterDataEx\n");
1184
1185         status = dcerpc_spoolss_GetPrinterDataEx(p, mem_ctx, &r);
1186         if (!NT_STATUS_IS_OK(status)) {
1187                 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
1188                     p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1189                         printf("GetPrinterDataEx not supported by server\n");
1190                         return True;
1191                 }
1192                 printf("GetPrinterDataEx failed - %s\n", nt_errstr(status));
1193                 return False;
1194         }
1195
1196         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1197
1198                 status = dcerpc_spoolss_GetPrinterDataEx(p, mem_ctx, &r);
1199
1200                 if (!NT_STATUS_IS_OK(status)) {
1201                         printf("GetPrinterDataEx failed - %s\n", 
1202                                nt_errstr(status));
1203                         return False;
1204                 }
1205
1206                 if (!W_ERROR_IS_OK(r.out.result)) {
1207                         printf("GetPrinterDataEx failed - %s\n", 
1208                                win_errstr(r.out.result));
1209                         return False;
1210                 }
1211         }
1212
1213         return True;
1214 }
1215
1216 static BOOL test_EnumPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1217                                  struct policy_handle *handle)
1218 {
1219         NTSTATUS status;
1220         struct spoolss_EnumPrinterData r;
1221
1222         r.in.handle = handle;
1223         r.in.enum_index = 0;
1224
1225         do {
1226                 uint32_t data_size;
1227                 
1228                 r.in.value_offered = 0;
1229                 data_size = 0;
1230                 r.in.data_size = &data_size;
1231                 r.out.data_size = &data_size;
1232
1233                 printf("Testing EnumPrinterData\n");
1234
1235                 status = dcerpc_spoolss_EnumPrinterData(p, mem_ctx, &r);
1236
1237                 if (!NT_STATUS_IS_OK(status)) {
1238                         printf("EnumPrinterData failed - %s\n", nt_errstr(status));
1239                         return False;
1240                 }
1241
1242                 r.in.value_offered = r.out.value_needed;
1243
1244                 status = dcerpc_spoolss_EnumPrinterData(p, mem_ctx, &r);
1245
1246                 if (!NT_STATUS_IS_OK(status)) {
1247                         printf("EnumPrinterData failed - %s\n", nt_errstr(status));
1248                         return False;
1249                 }
1250                 
1251                 test_GetPrinterData(p, mem_ctx, handle, r.out.value_name);
1252
1253                 test_GetPrinterDataEx(
1254                         p, mem_ctx, handle, "PrinterDriverData", 
1255                         r.out.value_name);
1256
1257                 r.in.enum_index++;
1258
1259         } while (W_ERROR_IS_OK(r.out.result));
1260
1261         return True;
1262 }
1263
1264 static BOOL test_EnumPrinterDataEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1265                                    struct policy_handle *handle)
1266 {
1267         NTSTATUS status;
1268         struct spoolss_EnumPrinterDataEx r;
1269
1270         r.in.handle = handle;
1271         r.in.key_name = "PrinterDriverData";
1272         r.in.buf_size = 0;
1273
1274         printf("Testing EnumPrinterDataEx\n");
1275
1276         status = dcerpc_spoolss_EnumPrinterDataEx(p, mem_ctx, &r);
1277
1278         if (!NT_STATUS_IS_OK(status)) {
1279                 printf("EnumPrinterDataEx failed - %s\n", nt_errstr(status));
1280                 return False;
1281         }
1282
1283         r.in.buf_size = r.out.buf_size;
1284
1285         status = dcerpc_spoolss_EnumPrinterDataEx(p, mem_ctx, &r);
1286
1287         if (!NT_STATUS_IS_OK(status)) {
1288                 printf("EnumPrinterDataEx failed - %s\n", nt_errstr(status));
1289                 return False;
1290         }
1291
1292         return True;
1293 }
1294
1295
1296 static BOOL test_DeletePrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1297                                    struct policy_handle *handle, 
1298                                    const char *value_name)
1299 {
1300         NTSTATUS status;
1301         struct spoolss_DeletePrinterData r;
1302
1303         r.in.handle = handle;
1304         r.in.value_name = value_name;
1305
1306         printf("Testing DeletePrinterData\n");
1307
1308         status = dcerpc_spoolss_DeletePrinterData(p, mem_ctx, &r);
1309
1310         if (!NT_STATUS_IS_OK(status)) {
1311                 printf("DeletePrinterData failed - %s\n", nt_errstr(status));
1312                 return False;
1313         }
1314
1315         return True;
1316 }
1317
1318 static BOOL test_SetPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1319                          struct policy_handle *handle)
1320 {
1321         NTSTATUS status;
1322         struct spoolss_SetPrinterData r;
1323         const char *value_name = "spottyfoot";
1324         
1325         r.in.handle = handle;
1326         r.in.value_name = value_name;
1327         r.in.type = 0;
1328         r.in.buffer = data_blob_talloc(mem_ctx, "dog", 4);
1329         r.in.real_len = 4;
1330
1331         printf("Testing SetPrinterData\n");
1332
1333         status = dcerpc_spoolss_SetPrinterData(p, mem_ctx, &r);
1334
1335         if (!NT_STATUS_IS_OK(status)) {
1336                 printf("SetPrinterData failed - %s\n", nt_errstr(status));
1337                 return False;
1338         }
1339
1340         if (!test_DeletePrinterData(p, mem_ctx, handle, value_name)) {
1341                 return False;
1342         }
1343
1344         return True;
1345 }
1346
1347 static BOOL test_SecondaryClosePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1348                                        struct policy_handle *handle)
1349 {
1350         NTSTATUS status;
1351         struct dcerpc_binding *b;
1352         struct dcerpc_pipe *p2;
1353         BOOL ret = True;
1354
1355         /* only makes sense on SMB */
1356         if (p->conn->transport.transport != NCACN_NP) {
1357                 return True;
1358         }
1359
1360         printf("testing close on secondary pipe\n");
1361
1362         status = dcerpc_parse_binding(mem_ctx, p->conn->binding_string, &b);
1363         if (!NT_STATUS_IS_OK(status)) {
1364                 printf("Failed to parse dcerpc binding '%s'\n", p->conn->binding_string);
1365                 return False;
1366         }
1367
1368         status = dcerpc_secondary_connection(p, &p2, b);
1369         if (!NT_STATUS_IS_OK(status)) {
1370                 printf("Failed to create secondary connection\n");
1371                 return False;
1372         }
1373
1374         status = dcerpc_bind_auth_none(p2, DCERPC_SPOOLSS_UUID, 
1375                                        DCERPC_SPOOLSS_VERSION);
1376         if (!NT_STATUS_IS_OK(status)) {
1377                 printf("Failed to create bind on secondary connection\n");
1378                 talloc_free(p2);
1379
1380                 return False;
1381         }
1382
1383         if (test_ClosePrinter(p2, mem_ctx, handle)) {
1384                 printf("ERROR: Allowed close on secondary connection!\n");
1385                 ret = False;
1386         }
1387
1388         if (p2->last_fault_code != DCERPC_FAULT_CONTEXT_MISMATCH) {
1389                 printf("Unexpected fault code 0x%x - expected 0x%x\n",
1390                        p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH);
1391                 ret = False;
1392         }
1393
1394         talloc_free(p2);
1395
1396         return ret;
1397 }
1398
1399 static BOOL test_OpenPrinter_badname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, const char *name)
1400 {
1401         NTSTATUS status;
1402         struct spoolss_OpenPrinter op;
1403         struct spoolss_OpenPrinterEx opEx;
1404         struct policy_handle handle;
1405         BOOL ret = True;
1406
1407         op.in.printername       = name;
1408         op.in.datatype          = NULL;
1409         op.in.devmode_ctr.size  = 0;
1410         op.in.devmode_ctr.devmode= NULL;
1411         op.in.access_mask       = 0;
1412         op.out.handle           = &handle;
1413
1414         printf("\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
1415
1416         status = dcerpc_spoolss_OpenPrinter(p, mem_ctx, &op);
1417         if (!NT_STATUS_IS_OK(status)) {
1418                 printf("OpenPrinter failed - %s\n", nt_errstr(status));
1419                 ret = False;
1420         }
1421         if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
1422                 printf("OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
1423                         name, win_errstr(op.out.result));
1424         }
1425
1426         if (W_ERROR_IS_OK(op.out.result)) {
1427                 ret &=test_ClosePrinter(p, mem_ctx, &handle);
1428         }
1429
1430         opEx.in.printername             = name;
1431         opEx.in.datatype                = NULL;
1432         opEx.in.devmode_ctr.size        = 0;
1433         opEx.in.devmode_ctr.devmode     = NULL;
1434         opEx.in.access_mask             = 0;
1435         opEx.in.level                   = 1;
1436         opEx.in.userlevel.level1        = NULL;
1437         opEx.out.handle                 = &handle;
1438
1439         printf("\nTesting OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
1440
1441         status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &opEx);
1442         if (!NT_STATUS_IS_OK(status)) {
1443                 printf("OpenPrinter failed - %s\n", nt_errstr(status));
1444                 ret = False;
1445         }
1446         if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,opEx.out.result)) {
1447                 printf("OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
1448                         name, win_errstr(opEx.out.result));
1449         }
1450
1451         if (W_ERROR_IS_OK(opEx.out.result)) {
1452                 ret &=test_ClosePrinter(p, mem_ctx, &handle);
1453         }
1454
1455         return ret;
1456 }
1457
1458 static BOOL test_OpenPrinter_badnames(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1459 {
1460         BOOL ret = True;
1461         char *name;
1462
1463         ret &= test_OpenPrinter_badname(p, mem_ctx, "__INVALID_PRINTER__");
1464         ret &= test_OpenPrinter_badname(p, mem_ctx, "\\\\__INVALID_HOST__");
1465         ret &= test_OpenPrinter_badname(p, mem_ctx, "");
1466         ret &= test_OpenPrinter_badname(p, mem_ctx, "\\\\\\");
1467         ret &= test_OpenPrinter_badname(p, mem_ctx, "\\\\\\__INVALID_PRINTER__");
1468
1469         name = talloc_asprintf(mem_ctx, "\\\\%s\\", dcerpc_server_name(p));
1470         ret &= test_OpenPrinter_badname(p, mem_ctx, name);
1471         talloc_free(name);
1472
1473         name = talloc_asprintf(mem_ctx, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p));
1474         ret &= test_OpenPrinter_badname(p, mem_ctx, name);
1475         talloc_free(name);
1476
1477         return ret;
1478 }
1479
1480 static BOOL test_OpenPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1481                              const char *name)
1482 {
1483         NTSTATUS status;
1484         struct spoolss_OpenPrinter r;
1485         struct policy_handle handle;
1486         BOOL ret = True;
1487
1488         r.in.printername        = talloc_asprintf(mem_ctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
1489         r.in.datatype           = NULL;
1490         r.in.devmode_ctr.size   = 0;
1491         r.in.devmode_ctr.devmode= NULL;
1492         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
1493         r.out.handle            = &handle;
1494
1495         printf("\nTesting OpenPrinter(%s)\n", r.in.printername);
1496
1497         status = dcerpc_spoolss_OpenPrinter(p, mem_ctx, &r);
1498
1499         if (!NT_STATUS_IS_OK(status)) {
1500                 printf("OpenPrinter failed - %s\n", nt_errstr(status));
1501                 return False;
1502         }
1503
1504         if (!W_ERROR_IS_OK(r.out.result)) {
1505                 printf("OpenPrinter failed - %s\n", win_errstr(r.out.result));
1506                 return False;
1507         }
1508
1509         if (!test_GetPrinter(p, mem_ctx, &handle)) {
1510                 ret = False;
1511         }
1512
1513         if (!test_SecondaryClosePrinter(p, mem_ctx, &handle)) {
1514                 ret = False;
1515         }
1516
1517         if (!test_ClosePrinter(p, mem_ctx, &handle)) {
1518                 ret = False;
1519         }
1520
1521         return ret;
1522 }
1523
1524 static BOOL call_OpenPrinterEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1525                                const char *name, struct policy_handle *handle)
1526 {
1527         struct spoolss_OpenPrinterEx r;
1528         struct spoolss_UserLevel1 userlevel1;
1529         NTSTATUS status;
1530
1531         if (name && name[0]) {
1532                 r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s", 
1533                                                    dcerpc_server_name(p), name);
1534         } else {
1535                 r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s", 
1536                                                    dcerpc_server_name(p));
1537         }
1538
1539         r.in.datatype           = NULL;
1540         r.in.devmode_ctr.size   = 0;
1541         r.in.devmode_ctr.devmode= NULL;
1542         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
1543         r.in.level              = 1;
1544         r.in.userlevel.level1   = &userlevel1;
1545         r.out.handle = handle;
1546
1547         userlevel1.size = 1234;
1548         userlevel1.client = "hello";
1549         userlevel1.user = "spottyfoot!";
1550         userlevel1.build = 1;
1551         userlevel1.major = 2;
1552         userlevel1.minor = 3;
1553         userlevel1.processor = 4;
1554
1555         printf("Testing OpenPrinterEx(%s)\n", r.in.printername);
1556
1557         status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &r);
1558
1559         if (!NT_STATUS_IS_OK(status)) {
1560                 printf("OpenPrinterEx failed - %s\n", nt_errstr(status));
1561                 return False;
1562         }
1563         
1564         if (!W_ERROR_IS_OK(r.out.result)) {
1565                 printf("OpenPrinterEx failed - %s\n", win_errstr(r.out.result));
1566                 return False;
1567         }
1568
1569         return True;
1570 }
1571
1572 static BOOL test_OpenPrinterEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1573                                const char *name)
1574 {
1575         struct policy_handle handle;
1576         BOOL ret = True;
1577
1578         if (!call_OpenPrinterEx(p, mem_ctx, name, &handle)) {
1579                 return False;
1580         }
1581
1582         if (!test_GetPrinter(p, mem_ctx, &handle)) {
1583                 ret = False;
1584         }
1585
1586         if (!test_EnumForms(p, mem_ctx, &handle)) {
1587                 ret = False;
1588         }
1589
1590         if (!test_AddForm(p, mem_ctx, &handle)) {
1591                 ret = False;
1592         }
1593
1594         if (!test_EnumPrinterData(p, mem_ctx, &handle)) {
1595                 ret = False;
1596         }
1597
1598         if (!test_EnumPrinterDataEx(p, mem_ctx, &handle)) {
1599                 ret = False;
1600         }
1601
1602         if (!test_EnumJobs(p, mem_ctx, &handle)) {
1603                 ret = False;
1604         }
1605
1606         if (!test_SetPrinterData(p, mem_ctx, &handle)) {
1607                 ret = False;
1608         }
1609
1610         if (!test_SecondaryClosePrinter(p, mem_ctx, &handle)) {
1611                 ret = False;
1612         }
1613
1614         if (!test_ClosePrinter(p, mem_ctx, &handle)) {
1615                 ret = False;
1616         }
1617         
1618         return ret;
1619 }
1620
1621 static BOOL test_EnumPrinters_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1622 {
1623         struct spoolss_EnumPrinters r;
1624         NTSTATUS status;
1625         uint16_t levels[] = {1, 2, 4, 5};
1626         int i;
1627         BOOL ret = True;
1628
1629         for (i=0;i<ARRAY_SIZE(levels);i++) {
1630                 uint32_t buf_size = 0;
1631                 union spoolss_PrinterInfo *info;
1632                 int j;
1633
1634                 r.in.flags      = PRINTER_ENUM_LOCAL;
1635                 r.in.server     = "";
1636                 r.in.level      = levels[i];
1637                 r.in.buffer     = NULL;
1638                 r.in.buf_size   = &buf_size;
1639                 r.out.buf_size  = &buf_size;
1640
1641                 printf("\nTesting EnumPrinters level %u\n", r.in.level);
1642
1643                 status = dcerpc_spoolss_EnumPrinters(p, mem_ctx, &r);
1644                 if (!NT_STATUS_IS_OK(status)) {
1645                         printf("EnumPrinters failed - %s\n", nt_errstr(status));
1646                         ret = False;
1647                         continue;
1648                 }
1649
1650                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1651                         DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
1652                         data_blob_clear(&blob);
1653                         r.in.buffer = &blob;
1654                         status = dcerpc_spoolss_EnumPrinters(p, mem_ctx, &r);
1655                 }
1656
1657                 if (!NT_STATUS_IS_OK(status)) {
1658                         printf("EnumPrinters failed - %s\n", 
1659                                nt_errstr(status));
1660                         continue;
1661                 }
1662
1663                 if (!W_ERROR_IS_OK(r.out.result)) {
1664                         printf("EnumPrinters failed - %s\n", 
1665                                win_errstr(r.out.result));
1666                         continue;
1667                 }
1668
1669                 if (!r.out.info) {
1670                         printf("No printers returned");
1671                         continue;
1672                 }
1673
1674                 info = r.out.info;
1675
1676                 for (j=0;j<r.out.count;j++) {
1677                         if (r.in.level == 1) {
1678                                 /* the names appear to be comma-separated name lists? */
1679                                 char *name = talloc_strdup(mem_ctx, info[j].info1.name);
1680                                 char *comma = strchr(name, ',');
1681                                 if (comma) *comma = 0;
1682                                 if (!test_OpenPrinter(p, mem_ctx, name)) {
1683                                         ret = False;
1684                                 }
1685                                 if (!test_OpenPrinterEx(p, mem_ctx, name)) {
1686                                         ret = False;
1687                                 }
1688                         }
1689                 }
1690         }
1691
1692         return ret;
1693 }
1694
1695 #if 0
1696 static BOOL test_GetPrinterDriver2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1697                                    struct policy_handle *handle, 
1698                                    const char *driver_name)
1699 {
1700         NTSTATUS status;
1701         struct spoolss_GetPrinterDriver2 r;
1702         uint32_t buf_size;
1703
1704         r.in.handle = handle;
1705         r.in.architecture = "W32X86";
1706         r.in.level = 1;
1707         buf_size = 0;
1708         r.in.buffer = NULL;
1709         r.in.buf_size = r.out.buf_size = &buf_size;
1710         r.in.client_major_version = 0;
1711         r.in.client_minor_version = 0;
1712
1713         printf("Testing GetPrinterDriver2\n");
1714
1715         status = dcerpc_spoolss_GetPrinterDriver2(p, mem_ctx, &r);
1716
1717         if (!NT_STATUS_IS_OK(status)) {
1718                 printf("GetPrinterDriver2 failed - %s\n", nt_errstr(status));
1719                 return False;
1720         }
1721
1722         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1723                 status = dcerpc_spoolss_GetPrinterDriver2(p, mem_ctx, &r);
1724         }
1725                 
1726         if (!NT_STATUS_IS_OK(status)) {
1727                 printf("GetPrinterDriver2 failed - %s\n", 
1728                        nt_errstr(status));
1729                 return False;
1730         }
1731
1732         if (!W_ERROR_IS_OK(r.out.result)) {
1733                 printf("GetPrinterDriver2 failed - %s\n", 
1734                        win_errstr(r.out.result));
1735                 return False;
1736         }
1737
1738         return True;
1739 }
1740 #endif
1741
1742 static BOOL test_EnumPrinterDrivers_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
1743 {
1744         struct spoolss_EnumPrinterDrivers r;
1745         NTSTATUS status;
1746         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
1747         int i;
1748         BOOL ret = True;
1749
1750         for (i=0;i<ARRAY_SIZE(levels);i++) {
1751                 uint32_t buf_size;
1752
1753                 r.in.server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1754                 r.in.environment = "Windows NT x86";
1755                 r.in.level = levels[i];
1756                 r.in.buffer = NULL;
1757                 buf_size = 0;
1758                 r.in.buf_size = &buf_size;
1759                 r.out.buf_size = &buf_size;
1760
1761                 printf("\nTesting EnumPrinterDrivers level %u\n", r.in.level);
1762
1763                 status = dcerpc_spoolss_EnumPrinterDrivers(p, mem_ctx, &r);
1764
1765                 if (!NT_STATUS_IS_OK(status)) {
1766                         printf("EnumPrinterDrivers failed - %s\n", 
1767                                nt_errstr(status));
1768                         ret = False;
1769                         continue;
1770                 }
1771
1772                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1773                         DATA_BLOB blob = data_blob_talloc(
1774                                 mem_ctx, NULL, buf_size);
1775
1776                         data_blob_clear(&blob);
1777                         r.in.buffer = &blob;
1778                         status = dcerpc_spoolss_EnumPrinterDrivers(p, mem_ctx, &r);
1779                 }
1780                 
1781                 if (!NT_STATUS_IS_OK(status)) {
1782                         printf("EnumPrinterDrivers failed - %s\n", 
1783                                nt_errstr(status));
1784                         ret = False;
1785                         break;
1786                 }
1787
1788                 if (!W_ERROR_IS_OK(r.out.result)) {
1789                         printf("EnumPrinterDrivers failed - %s\n", 
1790                                win_errstr(r.out.result));
1791                         ret = False;
1792                         break;
1793                 }
1794
1795                 if (!r.out.info) {
1796                         printf("No printer drivers returned");
1797                         break;
1798                 }
1799         }
1800
1801         return ret;
1802 }
1803
1804 BOOL torture_rpc_spoolss(void)
1805 {
1806         NTSTATUS status;
1807         struct dcerpc_pipe *p;
1808         TALLOC_CTX *mem_ctx;
1809         BOOL ret = True;
1810         struct test_spoolss_context *ctx;
1811
1812         mem_ctx = talloc_init("torture_rpc_spoolss");
1813
1814         status = torture_rpc_connection(mem_ctx, 
1815                                         &p, 
1816                                         DCERPC_SPOOLSS_NAME,
1817                                         DCERPC_SPOOLSS_UUID,
1818                                         DCERPC_SPOOLSS_VERSION);
1819         if (!NT_STATUS_IS_OK(status)) {
1820                 talloc_free(mem_ctx);
1821                 return False;
1822         }
1823
1824         ctx = talloc_zero(mem_ctx, struct test_spoolss_context);
1825         ctx->p  = p;
1826
1827         ret &= test_OpenPrinter_server(ctx);
1828
1829         ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "Architecture");
1830
1831         /*ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "DefaultSpoolDirectory");*/
1832
1833         ret &= test_EnumPorts(ctx);
1834
1835         ret &= test_EnumPrinterDrivers(ctx);
1836
1837         ret &= test_EnumMonitors(ctx);
1838
1839         ret &= test_EnumPrintProcessors(ctx);
1840
1841         ret &= test_EnumPrinters(ctx);
1842
1843         ret &= test_OpenPrinter_badnames(p, mem_ctx);
1844
1845         ret &= test_AddPort(p, mem_ctx);
1846
1847         ret &= test_EnumPorts_old(p, mem_ctx);
1848
1849         ret &= test_EnumPrinters_old(p, mem_ctx);
1850
1851         ret &= test_EnumPrinterDrivers_old(p, mem_ctx);
1852
1853         talloc_free(mem_ctx);
1854
1855         return ret;
1856 }