Implemented SetForm RPC.
[kai/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
24 BOOL test_GetPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
25                      struct policy_handle *handle)
26 {
27         NTSTATUS status;
28         struct spoolss_GetPrinter r;
29         uint16 levels[] = {1, 2, 3, 4, 5, 6, 7};
30         int i;
31         BOOL ret = True;
32         
33         for (i=0;i<ARRAY_SIZE(levels);i++) {
34                 uint32 buf_size = 0;
35                 r.in.handle = handle;
36                 r.in.level = levels[i];
37                 r.in.buffer = NULL;
38                 r.in.buf_size = &buf_size;
39                 r.out.buf_size = &buf_size;
40
41                 printf("Testing GetPrinter level %u\n", r.in.level);
42
43                 status = dcerpc_spoolss_GetPrinter(p, mem_ctx, &r);
44                 if (!NT_STATUS_IS_OK(status)) {
45                         printf("GetPrinter failed - %s\n", nt_errstr(status));
46                         ret = False;
47                         continue;
48                 }
49                 
50                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
51                         DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
52                         data_blob_clear(&blob);
53                         r.in.buffer = &blob;
54                         status = dcerpc_spoolss_GetPrinter(p, mem_ctx, &r);
55                 }
56                 
57                 if (!NT_STATUS_IS_OK(status) ||
58                     !W_ERROR_IS_OK(r.out.result)) {
59                         printf("GetPrinter failed - %s/%s\n", 
60                                nt_errstr(status), win_errstr(r.out.result));
61                         ret = False;
62                         continue;
63                 }
64         }
65
66         return ret;
67 }
68
69
70 BOOL test_ClosePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
71                        struct policy_handle *handle)
72 {
73         NTSTATUS status;
74         struct spoolss_ClosePrinter r;
75
76         r.in.handle = handle;
77         r.out.handle = handle;
78
79         printf("Testing ClosePrinter\n");
80
81         status = dcerpc_spoolss_ClosePrinter(p, mem_ctx, &r);
82         if (!NT_STATUS_IS_OK(status)) {
83                 printf("ClosePrinter failed - %s\n", nt_errstr(status));
84                 return False;
85         }
86
87         return True;
88 }
89
90 BOOL test_GetForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
91                   struct policy_handle *handle, char *formname)
92 {
93         NTSTATUS status;
94         struct spoolss_GetForm r;
95         uint32 buf_size;
96
97         r.in.handle = handle;
98         r.in.formname = formname;
99         r.in.level = 1;
100         r.in.buffer = NULL;
101         buf_size = 0;
102         r.in.buf_size = r.out.buf_size = &buf_size;
103
104         printf("Testing GetForm\n");
105
106         status = dcerpc_spoolss_GetForm(p, mem_ctx, &r);
107
108         if (!NT_STATUS_IS_OK(status)) {
109                 printf("GetForm failed - %s\n", nt_errstr(status));
110                 return False;
111         }
112
113         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
114                 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
115
116                 data_blob_clear(&blob);
117                 r.in.buffer = &blob;
118
119                 status = dcerpc_spoolss_GetForm(p, mem_ctx, &r);
120
121                 if (!r.out.info) {
122                         printf("No form info returned");
123                         return False;
124                 }
125         }
126
127         return True;
128 }
129
130 BOOL test_EnumForms(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
131                     struct policy_handle *handle)
132 {
133         NTSTATUS status;
134         struct spoolss_EnumForms r;
135         uint32 buf_size;
136
137         r.in.handle = handle;
138         r.in.level = 1;
139         r.in.buffer = NULL;
140         buf_size = 0;
141         r.in.buf_size = &buf_size;
142         r.out.buf_size = &buf_size;
143
144         printf("Testing EnumForms\n");
145
146         status = dcerpc_spoolss_EnumForms(p, mem_ctx, &r);
147
148         if (!NT_STATUS_IS_OK(status)) {
149                 printf("EnumForms failed - %s\n", nt_errstr(status));
150                 return False;
151         }
152
153         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
154                 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
155                 union spoolss_FormInfo *info;
156                 int j;
157
158                 data_blob_clear(&blob);
159                 r.in.buffer = &blob;
160
161                 status = dcerpc_spoolss_EnumForms(p, mem_ctx, &r);
162
163                 if (!r.out.buffer) {
164                         printf("No forms returned");
165                         return False;
166                 }
167
168                 status = pull_spoolss_FormInfoArray(r.out.buffer, mem_ctx, r.in.level, r.out.count, &info);
169                 if (!NT_STATUS_IS_OK(status)) {
170                         printf("EnumFormsArray parse failed - %s\n", nt_errstr(status));
171                         return False;
172                 }
173
174                 for (j=0;j<r.out.count;j++) {
175                         printf("Form %d\n", j);
176                         NDR_PRINT_UNION_DEBUG(spoolss_FormInfo, r.in.level, &info[j]);
177                 }
178
179                 for (j = 0; j < r.out.count; j++)
180                         test_GetForm(p, mem_ctx, handle, info[j].info1.name);
181         }
182
183         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
184                 printf("EnumForms failed - %s/%s\n", 
185                        nt_errstr(status), win_errstr(r.out.result));
186                 return False;
187         }
188
189         return True;
190 }
191
192 BOOL test_DeleteForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
193                      struct policy_handle *handle, char *formname)
194 {
195         NTSTATUS status;
196         struct spoolss_DeleteForm r;
197
198         r.in.handle = handle;
199         r.in.formname = formname;
200
201         status = dcerpc_spoolss_DeleteForm(p, mem_ctx, &r);
202
203         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
204                 printf("DeleteForm failed - %s/%s\n", 
205                        nt_errstr(status), win_errstr(r.out.result));
206                 return False;
207         }
208
209         return True;
210 }
211
212 BOOL test_AddForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
213                   struct policy_handle *handle)
214 {
215         struct spoolss_AddForm r;
216         struct spoolss_AddFormInfo1 form;
217         NTSTATUS status;
218         char *formname = "testform3";
219         BOOL ret = True;
220
221         r.in.handle = handle;
222         r.in.level = 1;
223         form.flags = 2;         /* User form */
224         form.name = formname;
225         form.width = 1;
226         form.length = 2;
227         form.left = 3;
228         form.top = 4;
229         form.right = 5;
230         form.bottom = 6;
231         r.in.info.info1 = &form;
232         
233         status = dcerpc_spoolss_AddForm(p, mem_ctx, &r);
234
235         if (!NT_STATUS_IS_OK(status)) {
236                 printf("AddForm failed - %s\n", nt_errstr(status));
237                 return False;
238         }
239
240         if (!W_ERROR_IS_OK(r.out.result)) {
241                 printf("AddForm failed - %s\n", nt_errstr(status));
242                 goto done;
243         }
244
245         {
246                 struct spoolss_SetForm sf;
247
248                 sf.in.handle = handle;
249                 sf.in.form_name = formname;
250                 sf.in.level = 1;
251                 sf.in.info.info1 = &form;
252                 form.width = 1234;
253
254                 status = dcerpc_spoolss_SetForm(p, mem_ctx, &sf);
255
256                 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
257                         printf("SetForm failed - %s/%s\n", 
258                                nt_errstr(status), win_errstr(r.out.result));
259                         ret = False;
260                         /* Fall through to delete */
261                 }
262         }
263
264  done:
265         if (!test_DeleteForm(p, mem_ctx, handle, formname)) {
266                 printf("DeleteForm failed\n");
267                 ret = False;
268         }
269
270         return ret;
271 }
272
273 BOOL test_EnumPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
274                           struct policy_handle *handle)
275 {
276         NTSTATUS status;
277         struct spoolss_EnumPrinterData r;
278
279         r.in.handle = handle;
280         r.in.enum_index = 0;
281
282         do {
283                 uint32 data_size;
284                 
285                 r.in.value_offered = 0;
286                 data_size = 0;
287                 r.in.data_size = &data_size;
288                 r.out.data_size = &data_size;
289
290                 printf("Testing EnumPrinterData\n");
291
292                 status = dcerpc_spoolss_EnumPrinterData(p, mem_ctx, &r);
293
294                 if (!NT_STATUS_IS_OK(status)) {
295                         printf("EnumPrinterData failed - %s\n", nt_errstr(status));
296                         return False;
297                 }
298
299                 r.in.value_offered = r.out.value_needed;
300
301                 status = dcerpc_spoolss_EnumPrinterData(p, mem_ctx, &r);
302
303                 if (!NT_STATUS_IS_OK(status)) {
304                         printf("EnumPrinterData failed - %s\n", nt_errstr(status));
305                         return False;
306                 }
307                 
308                 r.in.enum_index++;
309         } while (!W_ERROR_IS_OK(r.out.result));
310
311         return True;
312 }
313
314 static BOOL test_OpenPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
315                              const char *name)
316 {
317         NTSTATUS status;
318         struct spoolss_OpenPrinter r;
319         struct policy_handle handle;
320         DATA_BLOB blob;
321         BOOL ret = True;
322
323         blob = data_blob(NULL, 0);
324
325         r.in.server = talloc_asprintf(mem_ctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
326         r.in.printer = NULL;
327         r.in.buffer = &blob;
328         r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;  
329         r.out.handle = &handle;
330
331         printf("\nTesting OpenPrinter(\\\\%s)\n", r.in.server);
332
333         status = dcerpc_spoolss_OpenPrinter(p, mem_ctx, &r);
334         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
335                 printf("OpenPrinter failed - %s/%s\n", 
336                        nt_errstr(status), win_errstr(r.out.result));
337                 /* don't consider failing this an error until we understand it */
338                 return True;
339         }
340
341
342         if (!test_GetPrinter(p, mem_ctx, &handle)) {
343                 ret = False;
344         }
345
346         if (!test_ClosePrinter(p, mem_ctx, &handle)) {
347                 ret = False;
348         }
349         
350         return ret;
351 }
352
353 static BOOL test_OpenPrinterEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
354                                const char *name)
355 {
356         struct policy_handle handle;
357         struct spoolss_OpenPrinterEx r;
358         struct spoolss_UserLevel1 userlevel1;
359         NTSTATUS status;
360         BOOL ret = True;
361
362         r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s", 
363                                            dcerpc_server_name(p), name);
364         r.in.datatype = NULL;
365         r.in.devmode_ctr.size = 0;
366         r.in.devmode_ctr.devmode = NULL;
367         r.in.access_required = 0x02000000;
368         r.in.level = 1;
369         r.out.handle = &handle;
370
371         userlevel1.size = 1234;
372         userlevel1.client = "hello";
373         userlevel1.user = "spottyfoot!";
374         userlevel1.build = 1;
375         userlevel1.major = 2;
376         userlevel1.minor = 3;
377         userlevel1.processor = 4;
378         r.in.userlevel.level1 = &userlevel1;
379
380         printf("Testing OpenPrinterEx(%s)\n", r.in.printername);
381
382         status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &r);
383
384         if (!NT_STATUS_IS_OK(status)) {
385                 printf("OpenPrinterEx failed - %s\n", nt_errstr(status));
386                 return False;
387         }
388
389         if (!W_ERROR_IS_OK(r.out.result)) {
390                 printf("OpenPrinterEx failed - %s\n", win_errstr(r.out.result));
391                 return False;
392         }
393
394         if (!test_GetPrinter(p, mem_ctx, &handle)) {
395                 ret = False;
396         }
397
398         if (!test_EnumForms(p, mem_ctx, &handle)) {
399                 ret = False;
400         }
401
402         if (!test_AddForm(p, mem_ctx, &handle)) {
403                 ret = False;
404         }
405
406         if (!test_EnumPrinterData(p, mem_ctx, &handle)) {
407                 ret = False;
408         }
409
410         if (!test_ClosePrinter(p, mem_ctx, &handle)) {
411                 ret = False;
412         }
413
414         return ret;
415 }
416
417
418 static BOOL test_EnumPrinters(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
419 {
420         struct spoolss_EnumPrinters r;
421         NTSTATUS status;
422         uint16 levels[] = {1, 2, 4, 5};
423         int i;
424         BOOL ret = True;
425
426         for (i=0;i<ARRAY_SIZE(levels);i++) {
427                 uint32 buf_size = 0;
428                 union spoolss_PrinterInfo *info;
429                 int j;
430
431                 r.in.flags = 0x02;
432                 r.in.server = "";
433                 r.in.level = levels[i];
434                 r.in.buffer = NULL;
435                 r.in.buf_size = &buf_size;
436                 r.out.buf_size = &buf_size;
437
438                 printf("\nTesting EnumPrinters level %u\n", r.in.level);
439
440                 status = dcerpc_spoolss_EnumPrinters(p, mem_ctx, &r);
441                 if (!NT_STATUS_IS_OK(status)) {
442                         printf("EnumPrinters failed - %s\n", nt_errstr(status));
443                         ret = False;
444                         continue;
445                 }
446                 
447                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
448                         DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
449                         data_blob_clear(&blob);
450                         r.in.buffer = &blob;
451                         status = dcerpc_spoolss_EnumPrinters(p, mem_ctx, &r);
452                 }
453                 
454                 if (!NT_STATUS_IS_OK(status) ||
455                     !W_ERROR_IS_OK(r.out.result)) {
456                         printf("EnumPrinters failed - %s/%s\n", 
457                                nt_errstr(status), win_errstr(r.out.result));
458                         continue;
459                 }
460
461                 if (!r.out.buffer) {
462                         printf("No printers returned");
463                         continue;
464                 }
465
466                 status = pull_spoolss_PrinterInfoArray(r.out.buffer, mem_ctx, r.in.level, r.out.count, &info);
467                 if (!NT_STATUS_IS_OK(status)) {
468                         printf("EnumPrintersArray parse failed - %s\n", nt_errstr(status));
469                         continue;
470                 }
471
472                 for (j=0;j<r.out.count;j++) {
473                         printf("Printer %d\n", j);
474                         NDR_PRINT_UNION_DEBUG(spoolss_PrinterInfo, r.in.level, &info[j]);
475                 }
476
477                 for (j=0;j<r.out.count;j++) {
478                         if (r.in.level == 1) {
479                                 /* the names appear to be comma-separated name lists? */
480                                 char *name = talloc_strdup(mem_ctx, info[j].info1.name);
481                                 char *comma = strchr(name, ',');
482                                 if (comma) *comma = 0;
483                                 if (!test_OpenPrinter(p, mem_ctx, name)) {
484                                         ret = False;
485                                 }
486                                 if (!test_OpenPrinterEx(p, mem_ctx, name)) {
487                                         ret = False;
488                                 }
489                         }
490                 }
491         }
492         
493         return ret;
494 }
495
496 BOOL torture_rpc_spoolss(int dummy)
497 {
498         NTSTATUS status;
499         struct dcerpc_pipe *p;
500         TALLOC_CTX *mem_ctx;
501         BOOL ret = True;
502
503         mem_ctx = talloc_init("torture_rpc_spoolss");
504
505         status = torture_rpc_connection(&p, 
506                                         DCERPC_SPOOLSS_NAME,
507                                         DCERPC_SPOOLSS_UUID,
508                                         DCERPC_SPOOLSS_VERSION);
509         if (!NT_STATUS_IS_OK(status)) {
510                 return False;
511         }
512
513         p->flags |= DCERPC_DEBUG_PRINT_BOTH;
514         
515         if (!test_EnumPrinters(p, mem_ctx)) {
516                 ret = False;
517         }
518
519         talloc_destroy(mem_ctx);
520
521         torture_rpc_close(p);
522
523         return ret;
524 }