Implemented AddForm RPC. The mystery of the useless_ptr has been
[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                         struct spoolss_AddForm af;
128                         struct spoolss_AddFormInfo1 form;
129
130                         af.in.handle = handle;
131                         af.in.level = 1;
132                         form.flags = 2;
133                         form.name = "testform3";
134                         form.width = r.out.info->info1.width;
135                         form.length = r.out.info->info1.length;
136                         form.left = r.out.info->info1.left;
137                         form.top = r.out.info->info1.top;
138                         form.right = r.out.info->info1.right;
139                         form.bottom = r.out.info->info1.bottom;
140                         af.in.info.info1 = &form;
141
142                         status = dcerpc_spoolss_AddForm(
143                                 p, mem_ctx, &af);
144                 }
145         }
146
147         return True;
148 }
149
150 BOOL test_EnumForms(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
151                     struct policy_handle *handle)
152 {
153         NTSTATUS status;
154         struct spoolss_EnumForms r;
155         uint32 buf_size;
156
157         r.in.handle = handle;
158         r.in.level = 1;
159         r.in.buffer = NULL;
160         buf_size = 0;
161         r.in.buf_size = &buf_size;
162         r.out.buf_size = &buf_size;
163
164         printf("Testing EnumForms\n");
165
166         status = dcerpc_spoolss_EnumForms(p, mem_ctx, &r);
167
168         if (!NT_STATUS_IS_OK(status)) {
169                 printf("EnumForms failed - %s\n", nt_errstr(status));
170                 return False;
171         }
172
173         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
174                 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
175                 union spoolss_FormInfo *info;
176                 int j;
177
178                 data_blob_clear(&blob);
179                 r.in.buffer = &blob;
180
181                 status = dcerpc_spoolss_EnumForms(p, mem_ctx, &r);
182
183                 if (!r.out.buffer) {
184                         printf("No forms returned");
185                         return False;
186                 }
187
188                 status = pull_spoolss_FormInfoArray(r.out.buffer, mem_ctx, r.in.level, r.out.count, &info);
189                 if (!NT_STATUS_IS_OK(status)) {
190                         printf("EnumFormsArray parse failed - %s\n", nt_errstr(status));
191                         return False;
192                 }
193
194                 for (j=0;j<r.out.count;j++) {
195                         printf("Form %d\n", j);
196                         NDR_PRINT_UNION_DEBUG(spoolss_FormInfo, r.in.level, &info[j]);
197                 }
198
199                 for (j = 0; j < r.out.count; j++)
200                         test_GetForm(p, mem_ctx, handle, info[j].info1.name);
201         }
202
203         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
204                 printf("EnumForms 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_EnumPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
213                           struct policy_handle *handle)
214 {
215         NTSTATUS status;
216         struct spoolss_EnumPrinterData r;
217
218         r.in.handle = handle;
219         r.in.enum_index = 0;
220
221         do {
222                 uint32 data_size;
223                 
224                 r.in.value_offered = 0;
225                 data_size = 0;
226                 r.in.data_size = &data_size;
227                 r.out.data_size = &data_size;
228
229                 printf("Testing EnumPrinterData\n");
230
231                 status = dcerpc_spoolss_EnumPrinterData(p, mem_ctx, &r);
232
233                 if (!NT_STATUS_IS_OK(status)) {
234                         printf("EnumPrinterData failed - %s\n", nt_errstr(status));
235                         return False;
236                 }
237
238                 r.in.value_offered = r.out.value_needed;
239
240                 status = dcerpc_spoolss_EnumPrinterData(p, mem_ctx, &r);
241
242                 if (!NT_STATUS_IS_OK(status)) {
243                         printf("EnumPrinterData failed - %s\n", nt_errstr(status));
244                         return False;
245                 }
246                 
247                 r.in.enum_index++;
248         } while (!W_ERROR_IS_OK(r.out.result));
249
250         return True;
251 }
252
253 static BOOL test_OpenPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
254                              const char *name)
255 {
256         NTSTATUS status;
257         struct spoolss_OpenPrinter r;
258         struct policy_handle handle;
259         DATA_BLOB blob;
260         BOOL ret = True;
261
262         blob = data_blob(NULL, 0);
263
264         r.in.server = talloc_asprintf(mem_ctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
265         r.in.printer = NULL;
266         r.in.buffer = &blob;
267         r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;  
268         r.out.handle = &handle;
269
270         printf("\nTesting OpenPrinter(\\\\%s)\n", r.in.server);
271
272         status = dcerpc_spoolss_OpenPrinter(p, mem_ctx, &r);
273         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
274                 printf("OpenPrinter failed - %s/%s\n", 
275                        nt_errstr(status), win_errstr(r.out.result));
276                 /* don't consider failing this an error until we understand it */
277                 return True;
278         }
279
280
281         if (!test_GetPrinter(p, mem_ctx, &handle)) {
282                 ret = False;
283         }
284
285         if (!test_ClosePrinter(p, mem_ctx, &handle)) {
286                 ret = False;
287         }
288         
289         return ret;
290 }
291
292 static BOOL test_OpenPrinterEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
293                                const char *name)
294 {
295         struct policy_handle handle;
296         struct spoolss_OpenPrinterEx r;
297         struct spoolss_UserLevel1 userlevel1;
298         NTSTATUS status;
299         BOOL ret = True;
300
301         r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s", 
302                                            dcerpc_server_name(p), name);
303         r.in.datatype = NULL;
304         r.in.devmode_ctr.size = 0;
305         r.in.devmode_ctr.devmode = NULL;
306         r.in.access_required = 0x02000000;
307         r.in.level = 1;
308         r.out.handle = &handle;
309
310         userlevel1.size = 1234;
311         userlevel1.client = "hello";
312         userlevel1.user = "spottyfoot!";
313         userlevel1.build = 1;
314         userlevel1.major = 2;
315         userlevel1.minor = 3;
316         userlevel1.processor = 4;
317         r.in.userlevel.level1 = &userlevel1;
318
319         printf("Testing OpenPrinterEx(%s)\n", r.in.printername);
320
321         status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &r);
322
323         if (!NT_STATUS_IS_OK(status)) {
324                 printf("OpenPrinterEx failed - %s\n", nt_errstr(status));
325                 return False;
326         }
327
328         if (!W_ERROR_IS_OK(r.out.result)) {
329                 printf("OpenPrinterEx failed - %s\n", win_errstr(r.out.result));
330                 return False;
331         }
332
333         if (!test_GetPrinter(p, mem_ctx, &handle)) {
334                 ret = False;
335         }
336
337         if (!test_EnumForms(p, mem_ctx, &handle)) {
338                 ret = False;
339         }
340
341         if (!test_EnumPrinterData(p, mem_ctx, &handle)) {
342                 ret = False;
343         }
344
345         if (!test_ClosePrinter(p, mem_ctx, &handle)) {
346                 ret = False;
347         }
348
349         return ret;
350 }
351
352
353 static BOOL test_EnumPrinters(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
354 {
355         struct spoolss_EnumPrinters r;
356         NTSTATUS status;
357         uint16 levels[] = {1, 2, 4, 5};
358         int i;
359         BOOL ret = True;
360
361         for (i=0;i<ARRAY_SIZE(levels);i++) {
362                 uint32 buf_size = 0;
363                 union spoolss_PrinterInfo *info;
364                 int j;
365
366                 r.in.flags = 0x02;
367                 r.in.server = "";
368                 r.in.level = levels[i];
369                 r.in.buffer = NULL;
370                 r.in.buf_size = &buf_size;
371                 r.out.buf_size = &buf_size;
372
373                 printf("\nTesting EnumPrinters level %u\n", r.in.level);
374
375                 status = dcerpc_spoolss_EnumPrinters(p, mem_ctx, &r);
376                 if (!NT_STATUS_IS_OK(status)) {
377                         printf("EnumPrinters failed - %s\n", nt_errstr(status));
378                         ret = False;
379                         continue;
380                 }
381                 
382                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
383                         DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
384                         data_blob_clear(&blob);
385                         r.in.buffer = &blob;
386                         status = dcerpc_spoolss_EnumPrinters(p, mem_ctx, &r);
387                 }
388                 
389                 if (!NT_STATUS_IS_OK(status) ||
390                     !W_ERROR_IS_OK(r.out.result)) {
391                         printf("EnumPrinters failed - %s/%s\n", 
392                                nt_errstr(status), win_errstr(r.out.result));
393                         continue;
394                 }
395
396                 if (!r.out.buffer) {
397                         printf("No printers returned");
398                         continue;
399                 }
400
401                 status = pull_spoolss_PrinterInfoArray(r.out.buffer, mem_ctx, r.in.level, r.out.count, &info);
402                 if (!NT_STATUS_IS_OK(status)) {
403                         printf("EnumPrintersArray parse failed - %s\n", nt_errstr(status));
404                         continue;
405                 }
406
407                 for (j=0;j<r.out.count;j++) {
408                         printf("Printer %d\n", j);
409                         NDR_PRINT_UNION_DEBUG(spoolss_PrinterInfo, r.in.level, &info[j]);
410                 }
411
412                 for (j=0;j<r.out.count;j++) {
413                         if (r.in.level == 1) {
414                                 /* the names appear to be comma-separated name lists? */
415                                 char *name = talloc_strdup(mem_ctx, info[j].info1.name);
416                                 char *comma = strchr(name, ',');
417                                 if (comma) *comma = 0;
418                                 if (!test_OpenPrinter(p, mem_ctx, name)) {
419                                         ret = False;
420                                 }
421                                 if (!test_OpenPrinterEx(p, mem_ctx, name)) {
422                                         ret = False;
423                                 }
424                         }
425                 }
426         }
427         
428         return ret;
429 }
430
431 BOOL torture_rpc_spoolss(int dummy)
432 {
433         NTSTATUS status;
434         struct dcerpc_pipe *p;
435         TALLOC_CTX *mem_ctx;
436         BOOL ret = True;
437
438         mem_ctx = talloc_init("torture_rpc_spoolss");
439
440         status = torture_rpc_connection(&p, 
441                                         DCERPC_SPOOLSS_NAME,
442                                         DCERPC_SPOOLSS_UUID,
443                                         DCERPC_SPOOLSS_VERSION);
444         if (!NT_STATUS_IS_OK(status)) {
445                 return False;
446         }
447
448         p->flags |= DCERPC_DEBUG_PRINT_BOTH;
449         
450         if (!test_EnumPrinters(p, mem_ctx)) {
451                 ret = False;
452         }
453
454         talloc_destroy(mem_ctx);
455
456         torture_rpc_close(p);
457
458         return ret;
459 }