r3396: Rename form_name -> formname. This time, check smbtorture builds before
[kai/samba-autobuild/.git] / source4 / torture / rpc / spoolss.c
1 /* 
2    Unix SMB/CIFS implementation.
3    test suite for spoolss rpc operations
4
5    Copyright (C) Tim Potter 2003
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 static BOOL test_GetPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
25                      struct policy_handle *handle)
26 {
27         NTSTATUS status;
28         struct spoolss_GetPrinter r;
29         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7};
30         int i;
31         BOOL ret = True;
32         
33         for (i=0;i<ARRAY_SIZE(levels);i++) {
34                 uint32_t buf_size = 0;
35                 r.in.handle = handle;
36                 r.in.level = levels[i];
37                 r.in.buffer = NULL;
38                 r.in.buf_size = &buf_size;
39                 r.out.buf_size = &buf_size;
40
41                 printf("Testing GetPrinter level %u\n", r.in.level);
42
43                 status = dcerpc_spoolss_GetPrinter(p, mem_ctx, &r);
44                 if (!NT_STATUS_IS_OK(status)) {
45                         printf("GetPrinter failed - %s\n", nt_errstr(status));
46                         ret = False;
47                         continue;
48                 }
49                 
50                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
51                         DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
52                         data_blob_clear(&blob);
53                         r.in.buffer = &blob;
54                         status = dcerpc_spoolss_GetPrinter(p, mem_ctx, &r);
55                 }
56                 
57                 if (!NT_STATUS_IS_OK(status) ||
58                     !W_ERROR_IS_OK(r.out.result)) {
59                         printf("GetPrinter failed - %s/%s\n", 
60                                nt_errstr(status), win_errstr(r.out.result));
61                         ret = False;
62                         continue;
63                 }
64         }
65
66         return ret;
67 }
68
69
70 static BOOL test_ClosePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
71                        struct policy_handle *handle)
72 {
73         NTSTATUS status;
74         struct spoolss_ClosePrinter r;
75
76         r.in.handle = handle;
77         r.out.handle = handle;
78
79         printf("Testing ClosePrinter\n");
80
81         status = dcerpc_spoolss_ClosePrinter(p, mem_ctx, &r);
82         if (!NT_STATUS_IS_OK(status)) {
83                 printf("ClosePrinter failed - %s\n", nt_errstr(status));
84                 return False;
85         }
86
87         return True;
88 }
89
90 static BOOL test_GetForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
91                          struct policy_handle *handle, 
92                          const char *formname)
93 {
94         NTSTATUS status;
95         struct spoolss_GetForm r;
96         uint32_t buf_size;
97
98         r.in.handle = handle;
99         r.in.formname = formname;
100         r.in.level = 1;
101         r.in.buffer = NULL;
102         buf_size = 0;
103         r.in.buf_size = r.out.buf_size = &buf_size;
104
105         printf("Testing GetForm\n");
106
107         status = dcerpc_spoolss_GetForm(p, mem_ctx, &r);
108
109         if (!NT_STATUS_IS_OK(status)) {
110                 printf("GetForm failed - %s\n", nt_errstr(status));
111                 return False;
112         }
113
114         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
115                 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
116
117                 data_blob_clear(&blob);
118                 r.in.buffer = &blob;
119
120                 status = dcerpc_spoolss_GetForm(p, mem_ctx, &r);
121
122                 if (!r.out.info) {
123                         printf("No form info returned");
124                         return False;
125                 }
126         }
127
128         return True;
129 }
130
131 static BOOL test_EnumForms(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
132                     struct policy_handle *handle)
133 {
134         NTSTATUS status;
135         struct spoolss_EnumForms r;
136         uint32_t buf_size;
137
138         r.in.handle = handle;
139         r.in.level = 1;
140         r.in.buffer = NULL;
141         buf_size = 0;
142         r.in.buf_size = &buf_size;
143         r.out.buf_size = &buf_size;
144
145         printf("Testing EnumForms\n");
146
147         status = dcerpc_spoolss_EnumForms(p, mem_ctx, &r);
148
149         if (!NT_STATUS_IS_OK(status)) {
150                 printf("EnumForms failed - %s\n", nt_errstr(status));
151                 return False;
152         }
153
154         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
155                 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
156                 union spoolss_FormInfo *info;
157                 int j;
158
159                 data_blob_clear(&blob);
160                 r.in.buffer = &blob;
161
162                 status = dcerpc_spoolss_EnumForms(p, mem_ctx, &r);
163
164                 if (!r.out.buffer) {
165                         printf("No forms returned");
166                         return False;
167                 }
168
169                 status = pull_spoolss_FormInfoArray(r.out.buffer, mem_ctx, r.in.level, r.out.count, &info);
170                 if (!NT_STATUS_IS_OK(status)) {
171                         printf("EnumFormsArray parse failed - %s\n", nt_errstr(status));
172                         return False;
173                 }
174
175                 for (j=0;j<r.out.count;j++) {
176                         printf("Form %d\n", j);
177                         NDR_PRINT_UNION_DEBUG(spoolss_FormInfo, r.in.level, &info[j]);
178                 }
179
180                 for (j = 0; j < r.out.count; j++)
181                         test_GetForm(p, mem_ctx, handle, info[j].info1.formname);
182         }
183
184         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
185                 printf("EnumForms failed - %s/%s\n", 
186                        nt_errstr(status), win_errstr(r.out.result));
187                 return False;
188         }
189
190         return True;
191 }
192
193 static BOOL test_DeleteForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
194                             struct policy_handle *handle, 
195                             const char *formname)
196 {
197         NTSTATUS status;
198         struct spoolss_DeleteForm r;
199
200         r.in.handle = handle;
201         r.in.formname = formname;
202
203         status = dcerpc_spoolss_DeleteForm(p, mem_ctx, &r);
204
205         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
206                 printf("DeleteForm failed - %s/%s\n", 
207                        nt_errstr(status), win_errstr(r.out.result));
208                 return False;
209         }
210
211         return True;
212 }
213
214 static BOOL test_AddForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
215                   struct policy_handle *handle)
216 {
217         struct spoolss_AddForm r;
218         struct spoolss_AddFormInfo1 form;
219         NTSTATUS status;
220         const char *formname = "testform3";
221         BOOL ret = True;
222
223         r.in.handle = handle;
224         r.in.level = 1;
225         form.flags = 2;         /* User form */
226         form.formname = formname;
227         form.width = 1;
228         form.length = 2;
229         form.left = 3;
230         form.top = 4;
231         form.right = 5;
232         form.bottom = 6;
233         r.in.info.info1 = &form;
234         
235         status = dcerpc_spoolss_AddForm(p, mem_ctx, &r);
236
237         if (!NT_STATUS_IS_OK(status)) {
238                 printf("AddForm failed - %s\n", nt_errstr(status));
239                 return False;
240         }
241
242         if (!W_ERROR_IS_OK(r.out.result)) {
243                 printf("AddForm failed - %s\n", nt_errstr(status));
244                 goto done;
245         }
246
247         {
248                 struct spoolss_SetForm sf;
249
250                 sf.in.handle = handle;
251                 sf.in.formname = formname;
252                 sf.in.level = 1;
253                 sf.in.info.info1 = &form;
254                 form.width = 1234;
255
256                 status = dcerpc_spoolss_SetForm(p, mem_ctx, &sf);
257
258                 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
259                         printf("SetForm failed - %s/%s\n", 
260                                nt_errstr(status), win_errstr(r.out.result));
261                         ret = False;
262                         /* Fall through to delete */
263                 }
264         }
265
266  done:
267         if (!test_DeleteForm(p, mem_ctx, handle, formname)) {
268                 printf("DeleteForm failed\n");
269                 ret = False;
270         }
271
272         return ret;
273 }
274
275 static BOOL test_EnumPorts(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
276 {
277         NTSTATUS status;
278         struct spoolss_EnumPorts r;
279         uint32_t buf_size;
280
281         r.in.servername = talloc_asprintf(mem_ctx, "\\\\%s", 
282                                           dcerpc_server_name(p));
283         r.in.level = 2;
284         r.in.buffer = NULL;
285         buf_size = 0;
286         r.in.buf_size = &buf_size;
287         r.out.buf_size = &buf_size;
288
289         printf("Testing EnumPorts\n");
290
291         status = dcerpc_spoolss_EnumPorts(p, mem_ctx, &r);
292
293         if (!NT_STATUS_IS_OK(status)) {
294                 printf("EnumPorts failed -- %s\n", nt_errstr(status));
295                 return False;
296         }
297
298         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
299                 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
300                 union spoolss_PortInfo *info;
301                 int j;
302
303                 data_blob_clear(&blob);
304                 r.in.buffer = &blob;
305
306                 status = dcerpc_spoolss_EnumPorts(p, mem_ctx, &r);
307
308                 if (!NT_STATUS_IS_OK(status)) {
309                         printf("EnumPorts failed -- %s\n", nt_errstr(status));
310                         return False;
311                 }
312
313                 if (!r.out.buffer) {
314                         printf("No ports returned");
315                         return False;
316                 }
317
318                 status = pull_spoolss_PortInfoArray(r.out.buffer, mem_ctx,
319                                                     r.in.level, r.out.count,
320                                                     &info);
321                 if (!NT_STATUS_IS_OK(status)) {
322                         printf("EnumPortArray parse failed - %s\n",
323                                nt_errstr(status));
324                         return False;
325                 }
326
327                 for (j=0;j<r.out.count;j++) {
328                         printf("Port %d\n", j);
329                         NDR_PRINT_UNION_DEBUG(spoolss_PortInfo, r.in.level,
330                                               &info[j]);
331                 }
332         }
333
334         return True;
335 }
336
337 static BOOL test_GetJob(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
338                   struct policy_handle *handle, uint32_t job_id)
339 {
340         NTSTATUS status;
341         struct spoolss_GetJob r;
342         uint32_t buf_size;
343
344         r.in.handle = handle;
345         r.in.job_id = job_id;
346         r.in.level = 1;
347         r.in.buffer = NULL;
348         buf_size = 0;
349         r.in.buf_size = r.out.buf_size = &buf_size;
350
351         printf("Testing GetJob\n");
352
353         status = dcerpc_spoolss_GetJob(p, mem_ctx, &r);
354
355         if (!NT_STATUS_IS_OK(status)) {
356                 printf("GetJob failed - %s\n", nt_errstr(status));
357                 return False;
358         }
359
360         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
361                 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
362
363                 data_blob_clear(&blob);
364                 r.in.buffer = &blob;
365
366                 status = dcerpc_spoolss_GetJob(p, mem_ctx, &r);
367
368                 if (!r.out.info) {
369                         printf("No job info returned");
370                         return False;
371                 }
372         }
373
374         return True;
375 }
376
377 static BOOL test_SetJob(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
378                  struct policy_handle *handle, uint32_t job_id, uint32_t command)
379 {
380         NTSTATUS status;
381         struct spoolss_SetJob r;
382
383         r.in.handle = handle;
384         r.in.job_id = job_id;
385         r.in.level = 0;
386         r.in.command = command;
387
388         printf("Testing SetJob\n");
389
390         status = dcerpc_spoolss_SetJob(p, mem_ctx, &r);
391
392         if (!NT_STATUS_IS_OK(status)) {
393                 printf("SetJob failed - %s\n", nt_errstr(status));
394                 return False;
395         }
396
397         return True;
398 }
399
400 static BOOL test_EnumJobs(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
401                    struct policy_handle *handle)
402 {
403         NTSTATUS status;
404         struct spoolss_EnumJobs r;
405         uint32_t buf_size;
406
407         r.in.handle = handle;
408         r.in.firstjob = 0;
409         r.in.numjobs = 0xffffffff;
410         r.in.level = 1;
411         r.in.buffer = NULL;
412         buf_size = 0;
413         r.in.buf_size = &buf_size;
414         r.out.buf_size = &buf_size;
415
416         printf("Testing EnumJobs\n");
417
418         status = dcerpc_spoolss_EnumJobs(p, mem_ctx, &r);
419
420         if (!NT_STATUS_IS_OK(status)) {
421                 printf("EnumJobs failed - %s\n", nt_errstr(status));
422                 return False;
423         }
424
425         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
426                 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
427                 union spoolss_JobInfo *info;
428                 int j;
429
430                 data_blob_clear(&blob);
431                 r.in.buffer = &blob;
432
433                 status = dcerpc_spoolss_EnumJobs(p, mem_ctx, &r);
434
435                 if (!r.out.buffer) {
436                         printf("No jobs returned");
437                         return True;
438                 }
439
440                 status = pull_spoolss_JobInfoArray(
441                         r.out.buffer, mem_ctx, r.in.level, r.out.count,
442                         &info);
443
444                 if (!NT_STATUS_IS_OK(status)) {
445                         printf("EnumJobsArray parse failed - %s\n",
446                                nt_errstr(status));
447                         return False;
448                 }
449
450                 for (j = 0; j < r.out.count; j++) {
451                         printf("Job %d\n", j);
452                         NDR_PRINT_UNION_DEBUG(
453                                 spoolss_JobInfo, r.in.level, &info[j]);
454                 }
455
456                 for (j = 0; j < r.out.count; j++) {
457                         test_GetJob(p, mem_ctx, handle, info[j].info1.job_id);
458                         test_SetJob(
459                                 p, mem_ctx, handle, info[j].info1.job_id, 1);
460                 }
461
462         } else if (!W_ERROR_IS_OK(r.out.result)) {
463                 printf("EnumJobs failed - %s\n", win_errstr(r.out.result));
464                 return False;
465         }
466
467         return True;
468 }
469
470 static BOOL test_GetPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
471                                 struct policy_handle *handle, 
472                                 const char *value_name)
473 {
474         NTSTATUS status;
475         struct spoolss_GetPrinterData r;
476         uint32_t buf_size;
477
478         r.in.handle = handle;
479         r.in.value_name = value_name;
480         buf_size = 0;
481         r.in.buf_size = r.out.buf_size = &buf_size;
482
483         printf("Testing GetPrinterData\n");
484
485         status = dcerpc_spoolss_GetPrinterData(p, mem_ctx, &r);
486
487         if (!NT_STATUS_IS_OK(status)) {
488                 printf("GetPrinterData failed - %s\n", nt_errstr(status));
489                 return False;
490         }
491
492         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
493
494                 status = dcerpc_spoolss_GetPrinterData(p, mem_ctx, &r);
495
496                 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
497                         printf("GetPrinterData failed - %s/%s\n", 
498                                nt_errstr(status), win_errstr(r.out.result));
499                         return False;
500                 }
501         }
502
503         return True;
504 }
505
506 static BOOL test_GetPrinterDataEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
507                                   struct policy_handle *handle, 
508                                   const char *key_name,
509                                   const char *value_name)
510 {
511         NTSTATUS status;
512         struct spoolss_GetPrinterDataEx r;
513         uint32_t buf_size;
514
515         r.in.handle = handle;
516         r.in.key_name = key_name;
517         r.in.value_name = value_name;
518         buf_size = 0;
519         r.in.buf_size = r.out.buf_size = &buf_size;
520
521         printf("Testing GetPrinterDataEx\n");
522
523         status = dcerpc_spoolss_GetPrinterDataEx(p, mem_ctx, &r);
524
525         if (!NT_STATUS_IS_OK(status)) {
526                 printf("GetPrinterDataEx failed - %s\n", nt_errstr(status));
527                 return False;
528         }
529
530         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
531
532                 status = dcerpc_spoolss_GetPrinterDataEx(p, mem_ctx, &r);
533
534                 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
535                         printf("GetPrinterDataEx failed - %s/%s\n", 
536                                nt_errstr(status), win_errstr(r.out.result));
537                         return False;
538                 }
539         }
540
541         return True;
542 }
543
544 static BOOL test_EnumPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
545                           struct policy_handle *handle)
546 {
547         NTSTATUS status;
548         struct spoolss_EnumPrinterData r;
549
550         r.in.handle = handle;
551         r.in.enum_index = 0;
552
553         do {
554                 uint32_t data_size;
555                 
556                 r.in.value_offered = 0;
557                 data_size = 0;
558                 r.in.data_size = &data_size;
559                 r.out.data_size = &data_size;
560
561                 printf("Testing EnumPrinterData\n");
562
563                 status = dcerpc_spoolss_EnumPrinterData(p, mem_ctx, &r);
564
565                 if (!NT_STATUS_IS_OK(status)) {
566                         printf("EnumPrinterData failed - %s\n", nt_errstr(status));
567                         return False;
568                 }
569
570                 r.in.value_offered = r.out.value_needed;
571
572                 status = dcerpc_spoolss_EnumPrinterData(p, mem_ctx, &r);
573
574                 if (!NT_STATUS_IS_OK(status)) {
575                         printf("EnumPrinterData failed - %s\n", nt_errstr(status));
576                         return False;
577                 }
578                 
579                 test_GetPrinterData(p, mem_ctx, handle, r.out.value_name);
580
581                 test_GetPrinterDataEx(
582                         p, mem_ctx, handle, "PrinterDriverData", 
583                         r.out.value_name);
584
585                 r.in.enum_index++;
586
587         } while (W_ERROR_IS_OK(r.out.result));
588
589         return True;
590 }
591
592 static BOOL test_DeletePrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
593                                    struct policy_handle *handle, 
594                                    const char *value_name)
595 {
596         NTSTATUS status;
597         struct spoolss_DeletePrinterData r;
598
599         r.in.handle = handle;
600         r.in.value_name = value_name;
601
602         printf("Testing DeletePrinterData\n");
603
604         status = dcerpc_spoolss_DeletePrinterData(p, mem_ctx, &r);
605
606         if (!NT_STATUS_IS_OK(status)) {
607                 printf("DeletePrinterData failed - %s\n", nt_errstr(status));
608                 return False;
609         }
610
611         return True;
612 }
613
614 static BOOL test_SetPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
615                          struct policy_handle *handle)
616 {
617         NTSTATUS status;
618         struct spoolss_SetPrinterData r;
619         const char *value_name = "spottyfoot";
620         
621         r.in.handle = handle;
622         r.in.value_name = value_name;
623         r.in.type = 0;
624         r.in.buffer = data_blob_talloc(mem_ctx, "dog", 4);
625         r.in.real_len = 4;
626
627         printf("Testing SetPrinterData\n");
628
629         status = dcerpc_spoolss_SetPrinterData(p, mem_ctx, &r);
630
631         if (!NT_STATUS_IS_OK(status)) {
632                 printf("SetPrinterData failed - %s\n", nt_errstr(status));
633                 return False;
634         }
635
636         if (!test_DeletePrinterData(p, mem_ctx, handle, value_name)) {
637                 return False;
638         }
639
640         return True;
641 }
642
643 static BOOL test_SecondaryClosePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
644                                        struct policy_handle *handle)
645 {
646         NTSTATUS status;
647         struct dcerpc_pipe *p2;
648         BOOL ret = True;
649
650         /* only makes sense on SMB */
651         if (p->transport.transport != NCACN_NP) {
652                 return True;
653         }
654
655         printf("testing close on secondary pipe\n");
656
657         status = dcerpc_secondary_connection(p, &p2, 
658                                              DCERPC_SPOOLSS_NAME, 
659                                              DCERPC_SPOOLSS_UUID, 
660                                              DCERPC_SPOOLSS_VERSION);
661         if (!NT_STATUS_IS_OK(status)) {
662                 printf("Failed to create secondary connection\n");
663                 return False;
664         }
665
666         if (test_ClosePrinter(p2, mem_ctx, handle)) {
667                 printf("ERROR: Allowed close on secondary connection!\n");
668                 ret = False;
669         }
670
671         if (p2->last_fault_code != DCERPC_FAULT_CONTEXT_MISMATCH) {
672                 printf("Unexpected fault code 0x%x - expected 0x%x\n",
673                        p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH);
674                 ret = False;
675         }
676
677         dcerpc_pipe_close(p2);
678
679         return ret;
680 }
681
682 static BOOL test_OpenPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
683                              const char *name)
684 {
685         NTSTATUS status;
686         struct spoolss_OpenPrinter r;
687         struct policy_handle handle;
688         DATA_BLOB blob;
689         BOOL ret = True;
690
691         blob = data_blob(NULL, 0);
692
693         r.in.server = talloc_asprintf(mem_ctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
694         r.in.printer = NULL;
695         r.in.buffer = &blob;
696         r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;  
697         r.out.handle = &handle;
698
699         printf("\nTesting OpenPrinter(\\\\%s)\n", r.in.server);
700
701         status = dcerpc_spoolss_OpenPrinter(p, mem_ctx, &r);
702         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
703                 printf("OpenPrinter failed - %s/%s\n", 
704                        nt_errstr(status), win_errstr(r.out.result));
705                 /* don't consider failing this an error until we understand it */
706                 return True;
707         }
708
709
710         if (!test_GetPrinter(p, mem_ctx, &handle)) {
711                 ret = False;
712         }
713
714         if (!test_SecondaryClosePrinter(p, mem_ctx, &handle)) {
715                 ret = False;
716         }
717
718         if (!test_ClosePrinter(p, mem_ctx, &handle)) {
719                 ret = False;
720         }
721         
722         return ret;
723 }
724
725 static BOOL call_OpenPrinterEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
726                                const char *name, struct policy_handle *handle)
727 {
728         struct spoolss_OpenPrinterEx r;
729         struct spoolss_UserLevel1 userlevel1;
730         NTSTATUS status;
731
732         if (name && name[0])
733                 r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s", 
734                                                    dcerpc_server_name(p), name);
735         else
736                 r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s", 
737                                                    dcerpc_server_name(p));
738
739         r.in.datatype = NULL;
740         r.in.devmode_ctr.size = 0;
741         r.in.devmode_ctr.devmode = NULL;
742         r.in.access_mask = 0x02000000;
743         r.in.level = 1;
744         r.out.handle = handle;
745
746         userlevel1.size = 1234;
747         userlevel1.client = "hello";
748         userlevel1.user = "spottyfoot!";
749         userlevel1.build = 1;
750         userlevel1.major = 2;
751         userlevel1.minor = 3;
752         userlevel1.processor = 4;
753         r.in.userlevel.level1 = &userlevel1;
754
755         printf("Testing OpenPrinterEx(%s)\n", r.in.printername);
756
757         status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &r);
758
759         if (!NT_STATUS_IS_OK(status)) {
760                 printf("OpenPrinterEx failed - %s\n", nt_errstr(status));
761                 return False;
762         }
763         
764         if (!W_ERROR_IS_OK(r.out.result)) {
765                 printf("OpenPrinterEx failed - %s\n", win_errstr(r.out.result));
766                 return False;
767         }
768
769         return True;
770 }
771
772 static BOOL test_OpenPrinterEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
773                                const char *name)
774 {
775         struct policy_handle handle;
776         BOOL ret = True;
777
778         if (!call_OpenPrinterEx(p, mem_ctx, name, &handle)) {
779                 return False;
780         }
781
782         if (!test_GetPrinter(p, mem_ctx, &handle)) {
783                 ret = False;
784         }
785
786         if (!test_EnumForms(p, mem_ctx, &handle)) {
787                 ret = False;
788         }
789
790         if (!test_AddForm(p, mem_ctx, &handle)) {
791                 ret = False;
792         }
793
794         if (!test_EnumPrinterData(p, mem_ctx, &handle)) {
795                 ret = False;
796         }
797
798         if (!test_EnumJobs(p, mem_ctx, &handle)) {
799                 ret = False;
800         }
801
802         if (!test_SetPrinterData(p, mem_ctx, &handle)) {
803                 ret = False;
804         }
805
806         if (!test_SecondaryClosePrinter(p, mem_ctx, &handle)) {
807                 ret = False;
808         }
809
810         if (!test_ClosePrinter(p, mem_ctx, &handle)) {
811                 ret = False;
812         }
813         
814         return ret;
815 }
816
817 static BOOL test_EnumPrinters(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
818 {
819         struct spoolss_EnumPrinters r;
820         NTSTATUS status;
821         uint16_t levels[] = {1, 2, 4, 5};
822         int i;
823         BOOL ret = True;
824
825         for (i=0;i<ARRAY_SIZE(levels);i++) {
826                 uint32_t buf_size = 0;
827                 union spoolss_PrinterInfo *info;
828                 int j;
829
830                 r.in.flags = 0x02;
831                 r.in.server = "";
832                 r.in.level = levels[i];
833                 r.in.buffer = NULL;
834                 r.in.buf_size = &buf_size;
835                 r.out.buf_size = &buf_size;
836
837                 printf("\nTesting EnumPrinters level %u\n", r.in.level);
838
839                 status = dcerpc_spoolss_EnumPrinters(p, mem_ctx, &r);
840                 if (!NT_STATUS_IS_OK(status)) {
841                         printf("EnumPrinters failed - %s\n", nt_errstr(status));
842                         ret = False;
843                         continue;
844                 }
845                 
846                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
847                         DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
848                         data_blob_clear(&blob);
849                         r.in.buffer = &blob;
850                         status = dcerpc_spoolss_EnumPrinters(p, mem_ctx, &r);
851                 }
852                 
853                 if (!NT_STATUS_IS_OK(status) ||
854                     !W_ERROR_IS_OK(r.out.result)) {
855                         printf("EnumPrinters failed - %s/%s\n", 
856                                nt_errstr(status), win_errstr(r.out.result));
857                         continue;
858                 }
859
860                 if (!r.out.buffer) {
861                         printf("No printers returned");
862                         continue;
863                 }
864
865                 status = pull_spoolss_PrinterInfoArray(r.out.buffer, mem_ctx, r.in.level, r.out.count, &info);
866                 if (!NT_STATUS_IS_OK(status)) {
867                         printf("EnumPrintersArray parse failed - %s\n", nt_errstr(status));
868                         continue;
869                 }
870
871                 for (j=0;j<r.out.count;j++) {
872                         printf("Printer %d\n", j);
873                         NDR_PRINT_UNION_DEBUG(spoolss_PrinterInfo, r.in.level, &info[j]);
874                 }
875
876                 for (j=0;j<r.out.count;j++) {
877                         if (r.in.level == 1) {
878                                 /* the names appear to be comma-separated name lists? */
879                                 char *name = talloc_strdup(mem_ctx, info[j].info1.name);
880                                 char *comma = strchr(name, ',');
881                                 if (comma) *comma = 0;
882                                 if (!test_OpenPrinter(p, mem_ctx, name)) {
883                                         ret = False;
884                                 }
885                                 if (!test_OpenPrinterEx(p, mem_ctx, name)) {
886                                         ret = False;
887                                 }
888                         }
889                 }
890         }
891         
892         return ret;
893 }
894
895 static BOOL test_GetPrinterDriver2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
896                                    struct policy_handle *handle, 
897                                    const char *driver_name)
898 {
899         NTSTATUS status;
900         struct spoolss_GetPrinterDriver2 r;
901         uint32_t buf_size;
902
903         r.in.handle = handle;
904         r.in.architecture = "W32X86";
905         r.in.level = 1;
906         buf_size = 0;
907         r.in.buffer = NULL;
908         r.in.buf_size = r.out.buf_size = &buf_size;
909         r.in.client_major_version = 0;
910         r.in.client_minor_version = 0;
911
912         printf("Testing GetPrinterDriver2\n");
913
914         status = dcerpc_spoolss_GetPrinterDriver2(p, mem_ctx, &r);
915
916         if (!NT_STATUS_IS_OK(status)) {
917                 printf("GetPrinterDriver2 failed - %s\n", nt_errstr(status));
918                 return False;
919         }
920
921         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
922                 status = dcerpc_spoolss_GetPrinterDriver2(p, mem_ctx, &r);
923         }
924                 
925         if (!NT_STATUS_IS_OK(status) ||
926             !W_ERROR_IS_OK(r.out.result)) {
927                 printf("GetPrinterDriver2 failed - %s/%s\n", 
928                        nt_errstr(status), win_errstr(r.out.result));
929                 return False;
930         }
931
932         return True;
933 }
934         
935 static BOOL test_EnumPrinterDrivers(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
936 {
937         struct spoolss_EnumPrinterDrivers r;
938         NTSTATUS status;
939         uint16_t levels[] = {1, 2, 3};
940         int i;
941         BOOL ret = True;
942
943         for (i=0;i<ARRAY_SIZE(levels);i++) {
944                 uint32_t buf_size;
945                 char *server;
946                 union spoolss_DriverInfo *info;
947                 uint32_t j;
948
949                 asprintf(&server, "\\\\%s", dcerpc_server_name(p));
950                 r.in.server = server;
951                 r.in.environment = "Windows NT x86";
952                 r.in.level = levels[i];
953                 r.in.buffer = NULL;
954                 buf_size = 0;
955                 r.in.buf_size = &buf_size;
956                 r.out.buf_size = &buf_size;
957
958                 printf("\nTesting EnumPrinterDrivers level %u\n", r.in.level);
959
960                 status = dcerpc_spoolss_EnumPrinterDrivers(p, mem_ctx, &r);
961
962                 if (!NT_STATUS_IS_OK(status)) {
963                         printf("EnumPrinterDrivers failed - %s\n", 
964                                nt_errstr(status));
965                         ret = False;
966                         continue;
967                 }
968                 
969                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
970                         DATA_BLOB blob = data_blob_talloc(
971                                 mem_ctx, NULL, buf_size);
972
973                         data_blob_clear(&blob);
974                         r.in.buffer = &blob;
975                         status = dcerpc_spoolss_EnumPrinterDrivers(
976                                 p, mem_ctx, &r);
977                 }
978                 
979                 if (!NT_STATUS_IS_OK(status) ||
980                     !W_ERROR_IS_OK(r.out.result)) {
981                         printf("EnumPrinterDrivers failed - %s/%s\n", 
982                                nt_errstr(status), win_errstr(r.out.result));
983                         goto done;
984                 }
985
986                 if (!r.out.buffer) {
987                         printf("No printer drivers returned");
988                         goto done;
989                 }
990
991                 status = pull_spoolss_DriverInfoArray(
992                         r.out.buffer, mem_ctx, r.in.level, r.out.count, &info);
993
994                 if (!NT_STATUS_IS_OK(status)) {
995                         printf("EnumPrinterDriverArray parse failed - %s\n", 
996                                nt_errstr(status));
997                         continue;
998                 }
999
1000                 for (j=0;j<r.out.count;j++) {
1001                         printf("Printer driver %d\n", j);
1002                         NDR_PRINT_UNION_DEBUG(
1003                                 spoolss_DriverInfo, r.in.level, 
1004                                 &info[j]);
1005
1006                         if (r.in.level == 1) {
1007                                 struct policy_handle handle;
1008
1009                                 if (!call_OpenPrinterEx(
1010                                             p, mem_ctx, "",
1011                                             &handle))
1012                                         continue;
1013
1014                                 test_GetPrinterDriver2(
1015                                         p, mem_ctx, &handle, 
1016                                         info[j].info1.driver_name);
1017                         }
1018                 }
1019
1020         done:
1021                 free(server);
1022         }
1023         
1024         return ret;
1025 }
1026
1027 BOOL torture_rpc_spoolss(void)
1028 {
1029         NTSTATUS status;
1030         struct dcerpc_pipe *p;
1031         TALLOC_CTX *mem_ctx;
1032         BOOL ret = True;
1033
1034         mem_ctx = talloc_init("torture_rpc_spoolss");
1035
1036         status = torture_rpc_connection(&p, 
1037                                         DCERPC_SPOOLSS_NAME,
1038                                         DCERPC_SPOOLSS_UUID,
1039                                         DCERPC_SPOOLSS_VERSION);
1040         if (!NT_STATUS_IS_OK(status)) {
1041                 return False;
1042         }
1043
1044         if (!test_EnumPorts(p, mem_ctx)) {
1045                 ret = False;
1046         }
1047
1048         if (!test_EnumPrinters(p, mem_ctx)) {
1049                 ret = False;
1050         }
1051
1052         if (!test_EnumPrinterDrivers(p, mem_ctx)) {
1053                 ret = False;
1054         }
1055
1056         talloc_destroy(mem_ctx);
1057
1058         torture_rpc_close(p);
1059
1060         return ret;
1061 }