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