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