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