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