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