b8ed50157561c1042ff78a49b187ec9a70dd36a4
[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    Copyright (C) Stefan Metzmacher 2005
7    Copyright (C) Jelmer Vernooij 2007
8    Copyright (C) Guenther Deschner 2009-2010
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "torture/torture.h"
26 #include "torture/rpc/rpc.h"
27 #include "librpc/gen_ndr/ndr_misc.h"
28 #include "librpc/gen_ndr/ndr_spoolss.h"
29 #include "librpc/gen_ndr/ndr_spoolss_c.h"
30 #include "param/param.h"
31
32 #define TORTURE_WELLKNOWN_PRINTER       "torture_wkn_printer"
33 #define TORTURE_PRINTER                 "torture_printer"
34 #define TORTURE_WELLKNOWN_PRINTER_EX    "torture_wkn_printer_ex"
35 #define TORTURE_PRINTER_EX              "torture_printer_ex"
36
37 struct test_spoolss_context {
38         /* print server handle */
39         struct policy_handle server_handle;
40
41         /* for EnumPorts */
42         uint32_t port_count[3];
43         union spoolss_PortInfo *ports[3];
44
45         /* for EnumPrinterDrivers */
46         uint32_t driver_count[8];
47         union spoolss_DriverInfo *drivers[8];
48
49         /* for EnumMonitors */
50         uint32_t monitor_count[3];
51         union spoolss_MonitorInfo *monitors[3];
52
53         /* for EnumPrintProcessors */
54         uint32_t print_processor_count[2];
55         union spoolss_PrintProcessorInfo *print_processors[2];
56
57         /* for EnumPrinters */
58         uint32_t printer_count[6];
59         union spoolss_PrinterInfo *printers[6];
60 };
61
62 #define COMPARE_STRING(tctx, c,r,e) \
63         torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
64
65 /* not every compiler supports __typeof__() */
66 #if (__GNUC__ >= 3)
67 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
68         if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
69                 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
70         }\
71         if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
72                 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
73         }\
74 } while(0)
75 #else
76 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
77 #endif
78
79 #define COMPARE_UINT32(tctx, c, r, e) do {\
80         _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
81         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
82 } while(0)
83
84 #define COMPARE_UINT64(tctx, c, r, e) do {\
85         _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
86         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
87 } while(0)
88
89
90 #define COMPARE_NTTIME(tctx, c, r, e) do {\
91         _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
92         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
93 } while(0)
94
95 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
96         int __i; \
97         if (!c.e && !r.e) { \
98                 break; \
99         } \
100         if (c.e && !r.e) { \
101                 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
102         } \
103         if (!c.e && r.e) { \
104                 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
105         } \
106         for (__i=0;c.e[__i] != NULL; __i++) { \
107                 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
108         } \
109 } while(0)
110
111 #define CHECK_ALIGN(size, n) do {\
112         if (size % n) {\
113                 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
114                         size, n, size + n - (size % n));\
115         }\
116 } while(0)
117
118 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
119
120 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, ic, needed, align) do { \
121         uint32_t size = ndr_size_##fn##_info(tctx, ic, level, count, info);\
122         uint32_t round_size = DO_ROUND(size, align);\
123         if (round_size != needed) {\
124                 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
125                 CHECK_ALIGN(size, align);\
126         }\
127 } while(0)
128
129 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, ic, needed, align) do { \
130         uint32_t size = ndr_size_##fn##_info(tctx, ic, count, info);\
131         uint32_t round_size = DO_ROUND(size, align);\
132         if (round_size != needed) {\
133                 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
134                 CHECK_ALIGN(size, align);\
135         }\
136 } while(0)
137
138 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, ic, needed, align) do { \
139         uint32_t size = ndr_size_##fn(info, level, ic, 0);\
140         uint32_t round_size = DO_ROUND(size, align);\
141         if (round_size != needed) {\
142                 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
143                 CHECK_ALIGN(size, align);\
144         }\
145 } while(0)
146
147 static bool test_OpenPrinter_server(struct torture_context *tctx,
148                                     struct dcerpc_pipe *p,
149                                     struct policy_handle *server_handle)
150 {
151         NTSTATUS status;
152         struct spoolss_OpenPrinter op;
153
154         op.in.printername       = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
155         op.in.datatype          = NULL;
156         op.in.devmode_ctr.devmode= NULL;
157         op.in.access_mask       = 0;
158         op.out.handle           = server_handle;
159
160         torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
161
162         status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
163         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
164         torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
165
166         return true;
167 }
168
169 static bool test_EnumPorts(struct torture_context *tctx,
170                            struct dcerpc_pipe *p,
171                            struct test_spoolss_context *ctx)
172 {
173         NTSTATUS status;
174         struct spoolss_EnumPorts r;
175         uint16_t levels[] = { 1, 2 };
176         int i, j;
177
178         for (i=0;i<ARRAY_SIZE(levels);i++) {
179                 int level = levels[i];
180                 DATA_BLOB blob;
181                 uint32_t needed;
182                 uint32_t count;
183                 union spoolss_PortInfo *info;
184
185                 r.in.servername = "";
186                 r.in.level = level;
187                 r.in.buffer = NULL;
188                 r.in.offered = 0;
189                 r.out.needed = &needed;
190                 r.out.count = &count;
191                 r.out.info = &info;
192
193                 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
194
195                 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
196                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
197                 if (W_ERROR_IS_OK(r.out.result)) {
198                         /* TODO: do some more checks here */
199                         continue;
200                 }
201                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
202                         "EnumPorts unexpected return code");
203
204                 blob = data_blob_talloc(ctx, NULL, needed);
205                 data_blob_clear(&blob);
206                 r.in.buffer = &blob;
207                 r.in.offered = needed;
208
209                 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
210                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
211
212                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
213
214                 torture_assert(tctx, info, "EnumPorts returned no info");
215
216                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
217
218                 ctx->port_count[level]  = count;
219                 ctx->ports[level]       = info;
220         }
221
222         for (i=1;i<ARRAY_SIZE(levels);i++) {
223                 int level = levels[i];
224                 int old_level = levels[i-1];
225                 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
226                         "EnumPorts invalid value");
227         }
228         /* if the array sizes are not the same we would maybe segfault in the following code */
229
230         for (i=0;i<ARRAY_SIZE(levels);i++) {
231                 int level = levels[i];
232                 for (j=0;j<ctx->port_count[level];j++) {
233                         union spoolss_PortInfo *cur = &ctx->ports[level][j];
234                         union spoolss_PortInfo *ref = &ctx->ports[2][j];
235                         switch (level) {
236                         case 1:
237                                 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
238                                 break;
239                         case 2:
240                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
241                                 break;
242                         }
243                 }
244         }
245
246         return true;
247 }
248
249 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
250                                             struct dcerpc_pipe *p,
251                                             struct test_spoolss_context *ctx)
252 {
253         NTSTATUS status;
254         struct spoolss_GetPrintProcessorDirectory r;
255         struct {
256                 uint16_t level;
257                 const char *server;
258         } levels[] = {{
259                         .level  = 1,
260                         .server = NULL
261                 },{
262                         .level  = 1,
263                         .server = ""
264                 },{
265                         .level  = 78,
266                         .server = ""
267                 },{
268                         .level  = 1,
269                         .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
270                 },{
271                         .level  = 1024,
272                         .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
273                 }
274         };
275         int i;
276         uint32_t needed;
277
278         for (i=0;i<ARRAY_SIZE(levels);i++) {
279                 int level = levels[i].level;
280                 DATA_BLOB blob;
281
282                 r.in.server             = levels[i].server;
283                 r.in.environment        = SPOOLSS_ARCHITECTURE_NT_X86;
284                 r.in.level              = level;
285                 r.in.buffer             = NULL;
286                 r.in.offered            = 0;
287                 r.out.needed            = &needed;
288
289                 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
290
291                 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
292                 torture_assert_ntstatus_ok(tctx, status,
293                         "dcerpc_spoolss_GetPrintProcessorDirectory failed");
294                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
295                         "GetPrintProcessorDirectory unexpected return code");
296
297                 blob = data_blob_talloc(ctx, NULL, needed);
298                 data_blob_clear(&blob);
299                 r.in.buffer = &blob;
300                 r.in.offered = needed;
301
302                 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
303                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
304
305                 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
306
307                 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
308         }
309
310         return true;
311 }
312
313
314 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
315                                            struct dcerpc_pipe *p,
316                                            struct test_spoolss_context *ctx)
317 {
318         NTSTATUS status;
319         struct spoolss_GetPrinterDriverDirectory r;
320         struct {
321                 uint16_t level;
322                 const char *server;
323         } levels[] = {{
324                         .level  = 1,
325                         .server = NULL
326                 },{
327                         .level  = 1,
328                         .server = ""
329                 },{
330                         .level  = 78,
331                         .server = ""
332                 },{
333                         .level  = 1,
334                         .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
335                 },{
336                         .level  = 1024,
337                         .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
338                 }
339         };
340         int i;
341         uint32_t needed;
342
343         for (i=0;i<ARRAY_SIZE(levels);i++) {
344                 int level = levels[i].level;
345                 DATA_BLOB blob;
346
347                 r.in.server             = levels[i].server;
348                 r.in.environment        = SPOOLSS_ARCHITECTURE_NT_X86;
349                 r.in.level              = level;
350                 r.in.buffer             = NULL;
351                 r.in.offered            = 0;
352                 r.out.needed            = &needed;
353
354                 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
355
356                 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
357                 torture_assert_ntstatus_ok(tctx, status,
358                         "dcerpc_spoolss_GetPrinterDriverDirectory failed");
359                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
360                         "GetPrinterDriverDirectory unexpected return code");
361
362                 blob = data_blob_talloc(ctx, NULL, needed);
363                 data_blob_clear(&blob);
364                 r.in.buffer = &blob;
365                 r.in.offered = needed;
366
367                 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
368                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
369
370                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
371
372                 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
373         }
374
375         return true;
376 }
377
378 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
379                                     struct dcerpc_pipe *p,
380                                     struct test_spoolss_context *ctx,
381                                     const char *architecture)
382 {
383         NTSTATUS status;
384         struct spoolss_EnumPrinterDrivers r;
385         uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
386         int i, j;
387
388         for (i=0;i<ARRAY_SIZE(levels);i++) {
389                 int level = levels[i];
390                 DATA_BLOB blob;
391                 uint32_t needed;
392                 uint32_t count;
393                 union spoolss_DriverInfo *info;
394
395                 /* FIXME: gd, come back and fix "" as server, and handle
396                  * priority of returned error codes in torture test and samba 3
397                  * server */
398
399                 r.in.server             = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
400                 r.in.environment        = architecture;
401                 r.in.level              = level;
402                 r.in.buffer             = NULL;
403                 r.in.offered            = 0;
404                 r.out.needed            = &needed;
405                 r.out.count             = &count;
406                 r.out.info              = &info;
407
408                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u (%s)\n", r.in.level, r.in.environment);
409
410                 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
411                 torture_assert_ntstatus_ok(tctx, status,
412                                            "dcerpc_spoolss_EnumPrinterDrivers failed");
413                 if (W_ERROR_IS_OK(r.out.result)) {
414                         /* TODO: do some more checks here */
415                         continue;
416                 }
417                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
418                         blob = data_blob_talloc(ctx, NULL, needed);
419                         data_blob_clear(&blob);
420                         r.in.buffer = &blob;
421                         r.in.offered = needed;
422
423                         status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
424                         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
425                 }
426
427                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
428
429                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
430
431                 ctx->driver_count[level]        = count;
432                 ctx->drivers[level]             = info;
433         }
434
435         for (i=1;i<ARRAY_SIZE(levels);i++) {
436                 int level = levels[i];
437                 int old_level = levels[i-1];
438
439                 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
440                         "EnumPrinterDrivers invalid value");
441         }
442
443         for (i=0;i<ARRAY_SIZE(levels);i++) {
444                 int level = levels[i];
445
446                 for (j=0;j<ctx->driver_count[level];j++) {
447                         union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
448                         union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
449
450                         switch (level) {
451                         case 1:
452                                 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
453                                 break;
454                         case 2:
455                                 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
456                                 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
457                                 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
458                                 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
459                                 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
460                                 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
461                                 break;
462                         case 3:
463                                 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
464                                 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
465                                 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
466                                 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
467                                 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
468                                 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
469                                 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
470                                 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
471                                 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
472                                 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
473                                 break;
474                         case 4:
475                                 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
476                                 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
477                                 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
478                                 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
479                                 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
480                                 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
481                                 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
482                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
483                                 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
484                                 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
485                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
486                                 break;
487                         case 5:
488                                 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
489                                 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
490                                 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
491                                 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
492                                 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
493                                 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
494                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
495                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
496                                 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
497                                 break;
498                         case 6:
499                                 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
500                                 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
501                                 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
502                                 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
503                                 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
504                                 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
505                                 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
506                                 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
507                                 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
508                                 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
509                                 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
510                                 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
511                                 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
512                                 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
513                                 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
514                                 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
515                                 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
516                                 break;
517                         case 8:
518                                 /* level 8 is our reference, and it makes no sense to compare it to itself */
519                                 break;
520                         }
521                 }
522         }
523
524         return true;
525 }
526
527 static bool test_EnumMonitors(struct torture_context *tctx,
528                               struct dcerpc_pipe *p,
529                               struct test_spoolss_context *ctx)
530 {
531         NTSTATUS status;
532         struct spoolss_EnumMonitors r;
533         uint16_t levels[] = { 1, 2 };
534         int i, j;
535
536         for (i=0;i<ARRAY_SIZE(levels);i++) {
537                 int level = levels[i];
538                 DATA_BLOB blob;
539                 uint32_t needed;
540                 uint32_t count;
541                 union spoolss_MonitorInfo *info;
542
543                 r.in.servername = "";
544                 r.in.level = level;
545                 r.in.buffer = NULL;
546                 r.in.offered = 0;
547                 r.out.needed = &needed;
548                 r.out.count = &count;
549                 r.out.info = &info;
550
551                 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
552
553                 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
554                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
555                 if (W_ERROR_IS_OK(r.out.result)) {
556                         /* TODO: do some more checks here */
557                         continue;
558                 }
559                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
560                         "EnumMonitors failed");
561
562                 blob = data_blob_talloc(ctx, NULL, needed);
563                 data_blob_clear(&blob);
564                 r.in.buffer = &blob;
565                 r.in.offered = needed;
566
567                 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
568                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
569
570                 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
571
572                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
573
574                 ctx->monitor_count[level]       = count;
575                 ctx->monitors[level]            = info;
576         }
577
578         for (i=1;i<ARRAY_SIZE(levels);i++) {
579                 int level = levels[i];
580                 int old_level = levels[i-1];
581                 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
582                                          "EnumMonitors invalid value");
583         }
584
585         for (i=0;i<ARRAY_SIZE(levels);i++) {
586                 int level = levels[i];
587                 for (j=0;j<ctx->monitor_count[level];j++) {
588                         union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
589                         union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
590                         switch (level) {
591                         case 1:
592                                 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
593                                 break;
594                         case 2:
595                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
596                                 break;
597                         }
598                 }
599         }
600
601         return true;
602 }
603
604 static bool test_EnumPrintProcessors(struct torture_context *tctx,
605                                      struct dcerpc_pipe *p,
606                                      struct test_spoolss_context *ctx)
607 {
608         NTSTATUS status;
609         struct spoolss_EnumPrintProcessors r;
610         uint16_t levels[] = { 1 };
611         int i, j;
612
613         for (i=0;i<ARRAY_SIZE(levels);i++) {
614                 int level = levels[i];
615                 DATA_BLOB blob;
616                 uint32_t needed;
617                 uint32_t count;
618                 union spoolss_PrintProcessorInfo *info;
619
620                 r.in.servername = "";
621                 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
622                 r.in.level = level;
623                 r.in.buffer = NULL;
624                 r.in.offered = 0;
625                 r.out.needed = &needed;
626                 r.out.count = &count;
627                 r.out.info = &info;
628
629                 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
630
631                 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
632                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
633                 if (W_ERROR_IS_OK(r.out.result)) {
634                         /* TODO: do some more checks here */
635                         continue;
636                 }
637                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
638                         "EnumPrintProcessors unexpected return code");
639
640                 blob = data_blob_talloc(ctx, NULL, needed);
641                 data_blob_clear(&blob);
642                 r.in.buffer = &blob;
643                 r.in.offered = needed;
644
645                 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
646                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
647
648                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
649
650                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
651
652                 ctx->print_processor_count[level]       = count;
653                 ctx->print_processors[level]            = info;
654         }
655
656         for (i=1;i<ARRAY_SIZE(levels);i++) {
657                 int level = levels[i];
658                 int old_level = levels[i-1];
659                 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
660                         "EnumPrintProcessors failed");
661         }
662
663         for (i=0;i<ARRAY_SIZE(levels);i++) {
664                 int level = levels[i];
665                 for (j=0;j<ctx->print_processor_count[level];j++) {
666 #if 0
667                         union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
668                         union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
669 #endif
670                         switch (level) {
671                         case 1:
672                                 /* level 1 is our reference, and it makes no sense to compare it to itself */
673                                 break;
674                         }
675                 }
676         }
677
678         return true;
679 }
680
681 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
682                                         struct dcerpc_pipe *p,
683                                         struct test_spoolss_context *ctx)
684 {
685         NTSTATUS status;
686         struct spoolss_EnumPrintProcDataTypes r;
687         uint16_t levels[] = { 1 };
688         int i;
689
690         for (i=0;i<ARRAY_SIZE(levels);i++) {
691                 int level = levels[i];
692                 DATA_BLOB blob;
693                 uint32_t needed;
694                 uint32_t count;
695                 union spoolss_PrintProcDataTypesInfo *info;
696
697                 r.in.servername = "";
698                 r.in.print_processor_name = "winprint";
699                 r.in.level = level;
700                 r.in.buffer = NULL;
701                 r.in.offered = 0;
702                 r.out.needed = &needed;
703                 r.out.count = &count;
704                 r.out.info = &info;
705
706                 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
707
708                 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
709                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
710                 if (W_ERROR_IS_OK(r.out.result)) {
711                         /* TODO: do some more checks here */
712                         continue;
713                 }
714                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
715                         "EnumPrintProcDataTypes unexpected return code");
716
717                 blob = data_blob_talloc(ctx, NULL, needed);
718                 data_blob_clear(&blob);
719                 r.in.buffer = &blob;
720                 r.in.offered = needed;
721
722                 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
723                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
724
725                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
726
727                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
728
729         }
730
731         return true;
732 }
733
734
735 static bool test_EnumPrinters(struct torture_context *tctx,
736                               struct dcerpc_pipe *p,
737                               struct test_spoolss_context *ctx)
738 {
739         struct spoolss_EnumPrinters r;
740         NTSTATUS status;
741         uint16_t levels[] = { 0, 1, 2, 4, 5 };
742         int i, j;
743
744         for (i=0;i<ARRAY_SIZE(levels);i++) {
745                 int level = levels[i];
746                 DATA_BLOB blob;
747                 uint32_t needed;
748                 uint32_t count;
749                 union spoolss_PrinterInfo *info;
750
751                 r.in.flags      = PRINTER_ENUM_LOCAL;
752                 r.in.server     = "";
753                 r.in.level      = level;
754                 r.in.buffer     = NULL;
755                 r.in.offered    = 0;
756                 r.out.needed    = &needed;
757                 r.out.count     = &count;
758                 r.out.info      = &info;
759
760                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
761
762                 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
763                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
764                 if (W_ERROR_IS_OK(r.out.result)) {
765                         /* TODO: do some more checks here */
766                         continue;
767                 }
768                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
769                         "EnumPrinters unexpected return code");
770
771                 blob = data_blob_talloc(ctx, NULL, needed);
772                 data_blob_clear(&blob);
773                 r.in.buffer = &blob;
774                 r.in.offered = needed;
775
776                 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
777                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
778
779                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
780
781                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
782
783                 ctx->printer_count[level]       = count;
784                 ctx->printers[level]            = info;
785         }
786
787         for (i=1;i<ARRAY_SIZE(levels);i++) {
788                 int level = levels[i];
789                 int old_level = levels[i-1];
790                 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
791                                          "EnumPrinters invalid value");
792         }
793
794         for (i=0;i<ARRAY_SIZE(levels);i++) {
795                 int level = levels[i];
796                 for (j=0;j<ctx->printer_count[level];j++) {
797                         union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
798                         union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
799                         switch (level) {
800                         case 0:
801                                 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
802                                 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
803                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
804                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
805                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
806                                 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
807                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
808                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
809                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
810                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
811                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
812                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
813                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
814                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
815                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
816                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
817                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
818                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
819                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
820                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
821                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
822                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
823                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
824                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
825                                 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
826                                 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
827                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
828                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
829                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
830                                 break;
831                         case 1:
832                                 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
833                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
834                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
835                                 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
836                                 break;
837                         case 2:
838                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
839                                 break;
840                         case 4:
841                                 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
842                                 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
843                                 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
844                                 break;
845                         case 5:
846                                 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
847                                 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
848                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
849                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
850                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
851                                 break;
852                         }
853                 }
854         }
855
856         /* TODO:
857          *      - verify that the port of a printer was in the list returned by EnumPorts
858          */
859
860         return true;
861 }
862
863 static bool test_GetPrinterDriver2(struct torture_context *tctx,
864                                    struct dcerpc_pipe *p,
865                                    struct policy_handle *handle,
866                                    const char *driver_name);
867
868 static bool test_GetPrinter_level(struct torture_context *tctx,
869                                   struct dcerpc_pipe *p,
870                                   struct policy_handle *handle,
871                                   uint32_t level,
872                                   union spoolss_PrinterInfo *info)
873 {
874         struct spoolss_GetPrinter r;
875         uint32_t needed;
876
877         r.in.handle = handle;
878         r.in.level = level;
879         r.in.buffer = NULL;
880         r.in.offered = 0;
881         r.out.needed = &needed;
882
883         torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
884
885         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter(p, tctx, &r),
886                 "GetPrinter failed");
887
888         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
889                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
890                 data_blob_clear(&blob);
891                 r.in.buffer = &blob;
892                 r.in.offered = needed;
893
894                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter(p, tctx, &r),
895                         "GetPrinter failed");
896         }
897
898         torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
899
900         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
901
902         if (info && r.out.info) {
903                 *info = *r.out.info;
904         }
905
906         return true;
907 }
908
909
910 static bool test_GetPrinter(struct torture_context *tctx,
911                             struct dcerpc_pipe *p,
912                             struct policy_handle *handle)
913 {
914         uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
915         int i;
916
917         for (i=0;i<ARRAY_SIZE(levels);i++) {
918
919                 union spoolss_PrinterInfo info;
920
921                 ZERO_STRUCT(info);
922
923                 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, levels[i], &info),
924                         "failed to call GetPrinter");
925
926                 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
927                         torture_assert(tctx,
928                                 test_GetPrinterDriver2(tctx, p, handle, info.info2.drivername),
929                                 "failed to call test_GetPrinterDriver2");
930                 }
931         }
932
933         return true;
934 }
935
936 static bool test_SetPrinter(struct torture_context *tctx,
937                             struct dcerpc_pipe *p,
938                             struct policy_handle *handle,
939                             struct spoolss_SetPrinterInfoCtr *info_ctr,
940                             struct spoolss_DevmodeContainer *devmode_ctr,
941                             struct sec_desc_buf *secdesc_ctr,
942                             enum spoolss_PrinterControl command)
943 {
944         struct spoolss_SetPrinter r;
945
946         r.in.handle = handle;
947         r.in.info_ctr = info_ctr;
948         r.in.devmode_ctr = devmode_ctr;
949         r.in.secdesc_ctr = secdesc_ctr;
950         r.in.command = command;
951
952         torture_comment(tctx, "Testing SetPrinter Level %d\n", r.in.info_ctr->level);
953
954         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
955                 "failed to call SetPrinter");
956         torture_assert_werr_ok(tctx, r.out.result,
957                 "failed to call SetPrinter");
958
959         return true;
960 }
961
962 static bool test_SetPrinter_errors(struct torture_context *tctx,
963                                    struct dcerpc_pipe *p,
964                                    struct policy_handle *handle)
965 {
966         struct spoolss_SetPrinter r;
967         uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
968         int i;
969
970         struct spoolss_SetPrinterInfoCtr info_ctr;
971         struct spoolss_DevmodeContainer devmode_ctr;
972         struct sec_desc_buf secdesc_ctr;
973
974         info_ctr.level = 0;
975         info_ctr.info.info0 = NULL;
976
977         ZERO_STRUCT(devmode_ctr);
978         ZERO_STRUCT(secdesc_ctr);
979
980         r.in.handle = handle;
981         r.in.info_ctr = &info_ctr;
982         r.in.devmode_ctr = &devmode_ctr;
983         r.in.secdesc_ctr = &secdesc_ctr;
984         r.in.command = 0;
985
986         torture_comment(tctx, "Testing SetPrinter all zero\n");
987
988         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
989                 "failed to call SetPrinter");
990         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
991                 "failed to call SetPrinter");
992
993  again:
994         for (i=0; i < ARRAY_SIZE(levels); i++) {
995
996                 struct spoolss_SetPrinterInfo0 info0;
997                 struct spoolss_SetPrinterInfo1 info1;
998                 struct spoolss_SetPrinterInfo2 info2;
999                 struct spoolss_SetPrinterInfo3 info3;
1000                 struct spoolss_SetPrinterInfo4 info4;
1001                 struct spoolss_SetPrinterInfo5 info5;
1002                 struct spoolss_SetPrinterInfo6 info6;
1003                 struct spoolss_SetPrinterInfo7 info7;
1004                 struct spoolss_SetPrinterInfo8 info8;
1005                 struct spoolss_SetPrinterInfo9 info9;
1006
1007
1008                 info_ctr.level = levels[i];
1009                 switch (levels[i]) {
1010                 case 0:
1011                         ZERO_STRUCT(info0);
1012                         info_ctr.info.info0 = &info0;
1013                         break;
1014                 case 1:
1015                         ZERO_STRUCT(info1);
1016                         info_ctr.info.info1 = &info1;
1017                         break;
1018                 case 2:
1019                         ZERO_STRUCT(info2);
1020                         info_ctr.info.info2 = &info2;
1021                         break;
1022                 case 3:
1023                         ZERO_STRUCT(info3);
1024                         info_ctr.info.info3 = &info3;
1025                         break;
1026                 case 4:
1027                         ZERO_STRUCT(info4);
1028                         info_ctr.info.info4 = &info4;
1029                         break;
1030                 case 5:
1031                         ZERO_STRUCT(info5);
1032                         info_ctr.info.info5 = &info5;
1033                         break;
1034                 case 6:
1035                         ZERO_STRUCT(info6);
1036                         info_ctr.info.info6 = &info6;
1037                         break;
1038                 case 7:
1039                         ZERO_STRUCT(info7);
1040                         info_ctr.info.info7 = &info7;
1041                         break;
1042                 case 8:
1043                         ZERO_STRUCT(info8);
1044                         info_ctr.info.info8 = &info8;
1045                         break;
1046                 case 9:
1047                         ZERO_STRUCT(info9);
1048                         info_ctr.info.info9 = &info9;
1049                         break;
1050                 }
1051
1052                 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1053                         info_ctr.level, r.in.command);
1054
1055                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
1056                         "failed to call SetPrinter");
1057
1058                 switch (r.in.command) {
1059                 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1060                         /* is ignored for all levels other then 0 */
1061                         if (info_ctr.level > 0) {
1062                                 /* ignored then */
1063                                 break;
1064                         }
1065                 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1066                 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1067                 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1068                         if (info_ctr.level > 0) {
1069                                 /* is invalid for all levels other then 0 */
1070                                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1071                                         "unexpected error code returned");
1072                                 continue;
1073                         } else {
1074                                 torture_assert_werr_ok(tctx, r.out.result,
1075                                         "failed to call SetPrinter with non 0 command");
1076                                 continue;
1077                         }
1078                         break;
1079
1080                 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1081                         /* FIXME: gd needs further investigation */
1082                 default:
1083                         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1084                                 "unexpected error code returned");
1085                         continue;
1086                 }
1087
1088                 switch (info_ctr.level) {
1089                 case 1:
1090                         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1091                                 "unexpected error code returned");
1092                         break;
1093                 case 2:
1094                         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1095                                 "unexpected error code returned");
1096                         break;
1097                 case 3:
1098                 case 4:
1099                 case 5:
1100                 case 7:
1101                         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1102                                 "unexpected error code returned");
1103                         break;
1104                 case 9:
1105                         torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1106                                 "unexpected error code returned");
1107                         break;
1108                 default:
1109                         torture_assert_werr_ok(tctx, r.out.result,
1110                                 "failed to call SetPrinter");
1111                         break;
1112                 }
1113         }
1114
1115         if (r.in.command < 5) {
1116                 r.in.command++;
1117                 goto again;
1118         }
1119
1120         return true;
1121 }
1122
1123 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1124 {
1125         if ((r->level == 2) && (r->info.info2)) {
1126                 r->info.info2->secdesc_ptr = 0;
1127                 r->info.info2->devmode_ptr = 0;
1128         }
1129 }
1130
1131 static bool test_PrinterInfo(struct torture_context *tctx,
1132                              struct dcerpc_pipe *p,
1133                              struct policy_handle *handle)
1134 {
1135         NTSTATUS status;
1136         struct spoolss_SetPrinter s;
1137         struct spoolss_GetPrinter q;
1138         struct spoolss_GetPrinter q0;
1139         struct spoolss_SetPrinterInfoCtr info_ctr;
1140         union spoolss_PrinterInfo info;
1141         struct spoolss_DevmodeContainer devmode_ctr;
1142         struct sec_desc_buf secdesc_ctr;
1143         uint32_t needed;
1144         bool ret = true;
1145         int i;
1146
1147         uint32_t status_list[] = {
1148                 /* these do not stick
1149                 PRINTER_STATUS_PAUSED,
1150                 PRINTER_STATUS_ERROR,
1151                 PRINTER_STATUS_PENDING_DELETION, */
1152                 PRINTER_STATUS_PAPER_JAM,
1153                 PRINTER_STATUS_PAPER_OUT,
1154                 PRINTER_STATUS_MANUAL_FEED,
1155                 PRINTER_STATUS_PAPER_PROBLEM,
1156                 PRINTER_STATUS_OFFLINE,
1157                 PRINTER_STATUS_IO_ACTIVE,
1158                 PRINTER_STATUS_BUSY,
1159                 PRINTER_STATUS_PRINTING,
1160                 PRINTER_STATUS_OUTPUT_BIN_FULL,
1161                 PRINTER_STATUS_NOT_AVAILABLE,
1162                 PRINTER_STATUS_WAITING,
1163                 PRINTER_STATUS_PROCESSING,
1164                 PRINTER_STATUS_INITIALIZING,
1165                 PRINTER_STATUS_WARMING_UP,
1166                 PRINTER_STATUS_TONER_LOW,
1167                 PRINTER_STATUS_NO_TONER,
1168                 PRINTER_STATUS_PAGE_PUNT,
1169                 PRINTER_STATUS_USER_INTERVENTION,
1170                 PRINTER_STATUS_OUT_OF_MEMORY,
1171                 PRINTER_STATUS_DOOR_OPEN,
1172                 PRINTER_STATUS_SERVER_UNKNOWN,
1173                 PRINTER_STATUS_POWER_SAVE,
1174                 /* these do not stick
1175                 0x02000000,
1176                 0x04000000,
1177                 0x08000000,
1178                 0x10000000,
1179                 0x20000000,
1180                 0x40000000,
1181                 0x80000000 */
1182         };
1183         uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1184         uint32_t attribute_list[] = {
1185                 PRINTER_ATTRIBUTE_QUEUED,
1186                 /* fails with WERR_INVALID_DATATYPE:
1187                 PRINTER_ATTRIBUTE_DIRECT, */
1188                 /* does not stick
1189                 PRINTER_ATTRIBUTE_DEFAULT, */
1190                 PRINTER_ATTRIBUTE_SHARED,
1191                 /* does not stick
1192                 PRINTER_ATTRIBUTE_NETWORK, */
1193                 PRINTER_ATTRIBUTE_HIDDEN,
1194                 PRINTER_ATTRIBUTE_LOCAL,
1195                 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1196                 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1197                 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1198                 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1199                 /* does not stick
1200                 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1201                 /* fails with WERR_INVALID_DATATYPE:
1202                 PRINTER_ATTRIBUTE_RAW_ONLY, */
1203                 /* these do not stick
1204                 PRINTER_ATTRIBUTE_PUBLISHED,
1205                 PRINTER_ATTRIBUTE_FAX,
1206                 PRINTER_ATTRIBUTE_TS,
1207                 0x00010000,
1208                 0x00020000,
1209                 0x00040000,
1210                 0x00080000,
1211                 0x00100000,
1212                 0x00200000,
1213                 0x00400000,
1214                 0x00800000,
1215                 0x01000000,
1216                 0x02000000,
1217                 0x04000000,
1218                 0x08000000,
1219                 0x10000000,
1220                 0x20000000,
1221                 0x40000000,
1222                 0x80000000 */
1223         };
1224
1225         ZERO_STRUCT(devmode_ctr);
1226         ZERO_STRUCT(secdesc_ctr);
1227
1228         s.in.handle = handle;
1229         s.in.command = 0;
1230         s.in.info_ctr = &info_ctr;
1231         s.in.devmode_ctr = &devmode_ctr;
1232         s.in.secdesc_ctr = &secdesc_ctr;
1233
1234         q.in.handle = handle;
1235         q.out.info = &info;
1236         q0 = q;
1237
1238 #define TESTGETCALL(call, r) \
1239                 r.in.buffer = NULL; \
1240                 r.in.offered = 0;\
1241                 r.out.needed = &needed; \
1242                 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1243                 if (!NT_STATUS_IS_OK(status)) { \
1244                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1245                                r.in.level, nt_errstr(status), __location__); \
1246                         ret = false; \
1247                         break; \
1248                 }\
1249                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1250                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1251                         data_blob_clear(&blob); \
1252                         r.in.buffer = &blob; \
1253                         r.in.offered = needed; \
1254                 }\
1255                 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1256                 if (!NT_STATUS_IS_OK(status)) { \
1257                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1258                                r.in.level, nt_errstr(status), __location__); \
1259                         ret = false; \
1260                         break; \
1261                 } \
1262                 if (!W_ERROR_IS_OK(r.out.result)) { \
1263                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1264                                r.in.level, win_errstr(r.out.result), __location__); \
1265                         ret = false; \
1266                         break; \
1267                 }
1268
1269
1270 #define TESTSETCALL_EXP(call, r, err) \
1271                 clear_info2(&info_ctr);\
1272                 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1273                 if (!NT_STATUS_IS_OK(status)) { \
1274                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1275                                r.in.info_ctr->level, nt_errstr(status), __location__); \
1276                         ret = false; \
1277                         break; \
1278                 } \
1279                 if (!W_ERROR_IS_OK(err)) { \
1280                         if (!W_ERROR_EQUAL(err, r.out.result)) { \
1281                                 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1282                                        r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1283                                 ret = false; \
1284                         } \
1285                         break; \
1286                 } \
1287                 if (!W_ERROR_IS_OK(r.out.result)) { \
1288                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1289                                r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1290                         ret = false; \
1291                         break; \
1292                 }
1293
1294 #define TESTSETCALL(call, r) \
1295         TESTSETCALL_EXP(call, r, WERR_OK)
1296
1297 #define STRING_EQUAL(s1, s2, field) \
1298                 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1299                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1300                                #field, s2, __location__); \
1301                         ret = false; \
1302                         break; \
1303                 }
1304
1305 #define MEM_EQUAL(s1, s2, length, field) \
1306                 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1307                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1308                                #field, (const char *)s2, __location__); \
1309                         ret = false; \
1310                         break; \
1311                 }
1312
1313 #define INT_EQUAL(i1, i2, field) \
1314                 if (i1 != i2) { \
1315                         torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1316                                #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1317                         ret = false; \
1318                         break; \
1319                 }
1320
1321 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1322                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1323                 q.in.level = lvl1; \
1324                 TESTGETCALL(GetPrinter, q) \
1325                 info_ctr.level = lvl1; \
1326                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1327                 info_ctr.info.info ## lvl1->field1 = value;\
1328                 TESTSETCALL_EXP(SetPrinter, s, err) \
1329                 info_ctr.info.info ## lvl1->field1 = ""; \
1330                 TESTGETCALL(GetPrinter, q) \
1331                 info_ctr.info.info ## lvl1->field1 = value; \
1332                 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1333                 q.in.level = lvl2; \
1334                 TESTGETCALL(GetPrinter, q) \
1335                 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1336                 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1337         } while (0)
1338
1339 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1340         TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1341         } while (0);
1342
1343 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1344                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1345                 q.in.level = lvl1; \
1346                 TESTGETCALL(GetPrinter, q) \
1347                 info_ctr.level = lvl1; \
1348                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1349                 info_ctr.info.info ## lvl1->field1 = value; \
1350                 TESTSETCALL(SetPrinter, s) \
1351                 info_ctr.info.info ## lvl1->field1 = 0; \
1352                 TESTGETCALL(GetPrinter, q) \
1353                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1354                 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1355                 q.in.level = lvl2; \
1356                 TESTGETCALL(GetPrinter, q) \
1357                 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1358                 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1359         } while (0)
1360
1361 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1362         TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1363         } while (0)
1364
1365         q0.in.level = 0;
1366         do { TESTGETCALL(GetPrinter, q0) } while (0);
1367
1368         TEST_PRINTERINFO_STRING(2, comment,  1, comment, "xx2-1 comment");
1369         TEST_PRINTERINFO_STRING(2, comment,  2, comment, "xx2-2 comment");
1370
1371         /* level 0 printername does not stick */
1372 /*      TEST_PRINTERINFO_STRING(2, printername,  0, printername, "xx2-0 printer"); */
1373         TEST_PRINTERINFO_STRING(2, printername,  1, name,        "xx2-1 printer");
1374         TEST_PRINTERINFO_STRING(2, printername,  2, printername, "xx2-2 printer");
1375         TEST_PRINTERINFO_STRING(2, printername,  4, printername, "xx2-4 printer");
1376         TEST_PRINTERINFO_STRING(2, printername,  5, printername, "xx2-5 printer");
1377 /*      TEST_PRINTERINFO_STRING(4, printername,  0, printername, "xx4-0 printer"); */
1378         TEST_PRINTERINFO_STRING(4, printername,  1, name,        "xx4-1 printer");
1379         TEST_PRINTERINFO_STRING(4, printername,  2, printername, "xx4-2 printer");
1380         TEST_PRINTERINFO_STRING(4, printername,  4, printername, "xx4-4 printer");
1381         TEST_PRINTERINFO_STRING(4, printername,  5, printername, "xx4-5 printer");
1382 /*      TEST_PRINTERINFO_STRING(5, printername,  0, printername, "xx5-0 printer"); */
1383         TEST_PRINTERINFO_STRING(5, printername,  1, name,        "xx5-1 printer");
1384         TEST_PRINTERINFO_STRING(5, printername,  2, printername, "xx5-2 printer");
1385         TEST_PRINTERINFO_STRING(5, printername,  4, printername, "xx5-4 printer");
1386         TEST_PRINTERINFO_STRING(5, printername,  5, printername, "xx5-5 printer");
1387
1388         /* servername can be set but does not stick
1389         TEST_PRINTERINFO_STRING(2, servername,  0, servername, "xx2-0 servername");
1390         TEST_PRINTERINFO_STRING(2, servername,  2, servername, "xx2-2 servername");
1391         TEST_PRINTERINFO_STRING(2, servername,  4, servername, "xx2-4 servername");
1392         */
1393
1394         /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1395         TEST_PRINTERINFO_STRING_EXP_ERR(2, portname,  2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1396         TEST_PRINTERINFO_STRING_EXP_ERR(2, portname,  5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1397         TEST_PRINTERINFO_STRING_EXP_ERR(5, portname,  2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1398         TEST_PRINTERINFO_STRING_EXP_ERR(5, portname,  5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1399
1400         TEST_PRINTERINFO_STRING(2, sharename,   2, sharename,   "xx2-2 sharename");
1401         /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1402         TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername,  2, drivername,  "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1403         TEST_PRINTERINFO_STRING(2, location,    2, location,    "xx2-2 location");
1404         /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1405         TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile,     2, sepfile,     "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1406         /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1407         TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1408         TEST_PRINTERINFO_STRING(2, datatype,    2, datatype,    "xx2-2 datatype");
1409         TEST_PRINTERINFO_STRING(2, parameters,  2, parameters,  "xx2-2 parameters");
1410
1411         for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1412 /*              TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1413                         attribute_list[i],
1414                         (attribute_list[i] | default_attribute)
1415                         ); */
1416                 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1417                         attribute_list[i],
1418                         (attribute_list[i] | default_attribute)
1419                         );
1420                 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1421                         attribute_list[i],
1422                         (attribute_list[i] | default_attribute)
1423                         );
1424                 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1425                         attribute_list[i],
1426                         (attribute_list[i] | default_attribute)
1427                         );
1428 /*              TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1429                         attribute_list[i],
1430                         (attribute_list[i] | default_attribute)
1431                         ); */
1432                 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1433                         attribute_list[i],
1434                         (attribute_list[i] | default_attribute)
1435                         );
1436                 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1437                         attribute_list[i],
1438                         (attribute_list[i] | default_attribute)
1439                         );
1440                 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1441                         attribute_list[i],
1442                         (attribute_list[i] | default_attribute)
1443                         );
1444 /*              TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1445                         attribute_list[i],
1446                         (attribute_list[i] | default_attribute)
1447                         ); */
1448                 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1449                         attribute_list[i],
1450                         (attribute_list[i] | default_attribute)
1451                         );
1452                 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1453                         attribute_list[i],
1454                         (attribute_list[i] | default_attribute)
1455                         );
1456                 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1457                         attribute_list[i],
1458                         (attribute_list[i] | default_attribute)
1459                         );
1460         }
1461
1462         for (i=0; i < ARRAY_SIZE(status_list); i++) {
1463                 /* level 2 sets do not stick
1464                 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1465                 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1466                 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1467                 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1468                 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1469                 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1470         }
1471
1472         /* priorities need to be between 0 and 99
1473            passing an invalid priority will result in WERR_INVALID_PRIORITY */
1474         TEST_PRINTERINFO_INT(2, priority,       2, priority, 0);
1475         TEST_PRINTERINFO_INT(2, priority,       2, priority, 1);
1476         TEST_PRINTERINFO_INT(2, priority,       2, priority, 99);
1477         /* TEST_PRINTERINFO_INT(2, priority,    2, priority, 100); */
1478         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1479         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1480         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1481         /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1482
1483         TEST_PRINTERINFO_INT(2, starttime,      2, starttime, __LINE__);
1484         TEST_PRINTERINFO_INT(2, untiltime,      2, untiltime, __LINE__);
1485
1486         /* does not stick
1487         TEST_PRINTERINFO_INT(2, cjobs,          2, cjobs, __LINE__);
1488         TEST_PRINTERINFO_INT(2, averageppm,     2, averageppm, __LINE__); */
1489
1490         /* does not stick
1491         TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1492         TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1493
1494         /* FIXME: gd also test devmode and secdesc behavior */
1495
1496         {
1497                 /* verify composition of level 1 description field */
1498                 const char *description;
1499                 const char *tmp;
1500
1501                 q0.in.level = 1;
1502                 do { TESTGETCALL(GetPrinter, q0) } while (0);
1503
1504                 description = talloc_strdup(tctx, q0.out.info->info1.description);
1505
1506                 q0.in.level = 2;
1507                 do { TESTGETCALL(GetPrinter, q0) } while (0);
1508
1509                 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1510                         q0.out.info->info2.printername,
1511                         q0.out.info->info2.drivername,
1512                         q0.out.info->info2.location);
1513
1514                 do { STRING_EQUAL(description, tmp, "description")} while (0);
1515         }
1516
1517         return ret;
1518 }
1519
1520
1521 static bool test_ClosePrinter(struct torture_context *tctx,
1522                               struct dcerpc_pipe *p,
1523                               struct policy_handle *handle)
1524 {
1525         NTSTATUS status;
1526         struct spoolss_ClosePrinter r;
1527
1528         r.in.handle = handle;
1529         r.out.handle = handle;
1530
1531         torture_comment(tctx, "Testing ClosePrinter\n");
1532
1533         status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
1534         torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
1535         torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
1536
1537         return true;
1538 }
1539
1540 static bool test_GetForm(struct torture_context *tctx,
1541                          struct dcerpc_pipe *p,
1542                          struct policy_handle *handle,
1543                          const char *form_name,
1544                          uint32_t level)
1545 {
1546         NTSTATUS status;
1547         struct spoolss_GetForm r;
1548         uint32_t needed;
1549
1550         r.in.handle = handle;
1551         r.in.form_name = form_name;
1552         r.in.level = level;
1553         r.in.buffer = NULL;
1554         r.in.offered = 0;
1555         r.out.needed = &needed;
1556
1557         torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
1558
1559         status = dcerpc_spoolss_GetForm(p, tctx, &r);
1560         torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1561
1562         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1563                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1564                 data_blob_clear(&blob);
1565                 r.in.buffer = &blob;
1566                 r.in.offered = needed;
1567                 status = dcerpc_spoolss_GetForm(p, tctx, &r);
1568                 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1569
1570                 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1571
1572                 torture_assert(tctx, r.out.info, "No form info returned");
1573         }
1574
1575         torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1576
1577         CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
1578
1579         return true;
1580 }
1581
1582 static bool test_EnumForms(struct torture_context *tctx,
1583                            struct dcerpc_pipe *p,
1584                            struct policy_handle *handle, bool print_server)
1585 {
1586         NTSTATUS status;
1587         struct spoolss_EnumForms r;
1588         bool ret = true;
1589         uint32_t needed;
1590         uint32_t count;
1591         uint32_t levels[] = { 1, 2 };
1592         int i;
1593
1594         for (i=0; i<ARRAY_SIZE(levels); i++) {
1595
1596                 union spoolss_FormInfo *info;
1597
1598                 r.in.handle = handle;
1599                 r.in.level = levels[i];
1600                 r.in.buffer = NULL;
1601                 r.in.offered = 0;
1602                 r.out.needed = &needed;
1603                 r.out.count = &count;
1604                 r.out.info = &info;
1605
1606                 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
1607
1608                 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1609                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1610
1611                 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
1612                         break;
1613                 }
1614
1615                 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
1616                         torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1617
1618                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1619                         int j;
1620                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1621                         data_blob_clear(&blob);
1622                         r.in.buffer = &blob;
1623                         r.in.offered = needed;
1624
1625                         status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1626
1627                         torture_assert(tctx, info, "No forms returned");
1628
1629                         for (j = 0; j < count; j++) {
1630                                 if (!print_server)
1631                                         ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
1632                         }
1633                 }
1634
1635                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1636
1637                 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
1638
1639                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
1640         }
1641
1642         return true;
1643 }
1644
1645 static bool test_DeleteForm(struct torture_context *tctx,
1646                             struct dcerpc_pipe *p,
1647                             struct policy_handle *handle,
1648                             const char *form_name)
1649 {
1650         NTSTATUS status;
1651         struct spoolss_DeleteForm r;
1652
1653         r.in.handle = handle;
1654         r.in.form_name = form_name;
1655
1656         status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
1657
1658         torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
1659
1660         torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
1661
1662         return true;
1663 }
1664
1665 static bool test_AddForm(struct torture_context *tctx,
1666                          struct dcerpc_pipe *p,
1667                          struct policy_handle *handle, bool print_server)
1668 {
1669         struct spoolss_AddForm r;
1670         struct spoolss_AddFormInfo1 addform;
1671         const char *form_name = "testform3";
1672         NTSTATUS status;
1673         bool ret = true;
1674
1675         r.in.handle     = handle;
1676         r.in.level      = 1;
1677         r.in.info.info1 = &addform;
1678         addform.flags           = SPOOLSS_FORM_USER;
1679         addform.form_name       = form_name;
1680         addform.size.width      = 50;
1681         addform.size.height     = 25;
1682         addform.area.left       = 5;
1683         addform.area.top        = 10;
1684         addform.area.right      = 45;
1685         addform.area.bottom     = 15;
1686
1687         status = dcerpc_spoolss_AddForm(p, tctx, &r);
1688
1689         torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
1690
1691         torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
1692
1693         if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1694
1695         {
1696                 struct spoolss_SetForm sf;
1697                 struct spoolss_AddFormInfo1 setform;
1698
1699                 sf.in.handle    = handle;
1700                 sf.in.form_name = form_name;
1701                 sf.in.level     = 1;
1702                 sf.in.info.info1= &setform;
1703                 setform.flags           = addform.flags;
1704                 setform.form_name       = addform.form_name;
1705                 setform.size            = addform.size;
1706                 setform.area            = addform.area;
1707
1708                 setform.size.width      = 1234;
1709
1710                 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
1711
1712                 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
1713
1714                 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
1715         }
1716
1717         if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1718
1719         {
1720                 struct spoolss_EnumForms e;
1721                 union spoolss_FormInfo *info;
1722                 uint32_t needed;
1723                 uint32_t count;
1724                 bool found = false;
1725
1726                 e.in.handle = handle;
1727                 e.in.level = 1;
1728                 e.in.buffer = NULL;
1729                 e.in.offered = 0;
1730                 e.out.needed = &needed;
1731                 e.out.count = &count;
1732                 e.out.info = &info;
1733
1734                 torture_comment(tctx, "Testing EnumForms level 1\n");
1735
1736                 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1737                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1738
1739                 if (print_server && W_ERROR_EQUAL(e.out.result, WERR_BADFID))
1740                         torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1741
1742                 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
1743                         int j;
1744                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1745                         data_blob_clear(&blob);
1746                         e.in.buffer = &blob;
1747                         e.in.offered = needed;
1748
1749                         status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1750
1751                         torture_assert(tctx, info, "No forms returned");
1752
1753                         for (j = 0; j < count; j++) {
1754                                 if (strequal(form_name, info[j].info1.form_name)) {
1755                                         found = true;
1756                                         break;
1757                                 }
1758                         }
1759                 }
1760                 torture_assert(tctx, found, "Newly added form not found in enum call");
1761         }
1762
1763         if (!test_DeleteForm(tctx, p, handle, form_name)) {
1764                 ret = false;
1765         }
1766
1767         return ret;
1768 }
1769
1770 static bool test_EnumPorts_old(struct torture_context *tctx,
1771                                struct dcerpc_pipe *p)
1772 {
1773         NTSTATUS status;
1774         struct spoolss_EnumPorts r;
1775         uint32_t needed;
1776         uint32_t count;
1777         union spoolss_PortInfo *info;
1778
1779         r.in.servername = talloc_asprintf(tctx, "\\\\%s",
1780                                           dcerpc_server_name(p));
1781         r.in.level = 2;
1782         r.in.buffer = NULL;
1783         r.in.offered = 0;
1784         r.out.needed = &needed;
1785         r.out.count = &count;
1786         r.out.info = &info;
1787
1788         torture_comment(tctx, "Testing EnumPorts\n");
1789
1790         status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1791
1792         torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1793
1794         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1795                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1796                 data_blob_clear(&blob);
1797                 r.in.buffer = &blob;
1798                 r.in.offered = needed;
1799
1800                 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1801                 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1802                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
1803
1804                 torture_assert(tctx, info, "No ports returned");
1805         }
1806
1807         torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
1808
1809         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
1810
1811         return true;
1812 }
1813
1814 static bool test_AddPort(struct torture_context *tctx,
1815                          struct dcerpc_pipe *p)
1816 {
1817         NTSTATUS status;
1818         struct spoolss_AddPort r;
1819
1820         r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
1821                                            dcerpc_server_name(p));
1822         r.in.unknown = 0;
1823         r.in.monitor_name = "foo";
1824
1825         torture_comment(tctx, "Testing AddPort\n");
1826
1827         status = dcerpc_spoolss_AddPort(p, tctx, &r);
1828
1829         torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
1830
1831         /* win2k3 returns WERR_NOT_SUPPORTED */
1832
1833 #if 0
1834
1835         if (!W_ERROR_IS_OK(r.out.result)) {
1836                 printf("AddPort failed - %s\n", win_errstr(r.out.result));
1837                 return false;
1838         }
1839
1840 #endif
1841
1842         return true;
1843 }
1844
1845 static bool test_GetJob(struct torture_context *tctx,
1846                         struct dcerpc_pipe *p,
1847                         struct policy_handle *handle, uint32_t job_id)
1848 {
1849         NTSTATUS status;
1850         struct spoolss_GetJob r;
1851         union spoolss_JobInfo info;
1852         uint32_t needed;
1853         uint32_t levels[] = {1, 2 /* 3, 4 */};
1854         uint32_t i;
1855
1856         r.in.handle = handle;
1857         r.in.job_id = job_id;
1858         r.in.level = 0;
1859         r.in.buffer = NULL;
1860         r.in.offered = 0;
1861         r.out.needed = &needed;
1862         r.out.info = &info;
1863
1864         torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1865
1866         status = dcerpc_spoolss_GetJob(p, tctx, &r);
1867         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
1868
1869         for (i = 0; i < ARRAY_SIZE(levels); i++) {
1870
1871                 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1872
1873                 needed = 0;
1874
1875                 r.in.level = levels[i];
1876                 r.in.offered = 0;
1877                 r.in.buffer = NULL;
1878
1879                 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1880                 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1881
1882                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1883                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1884                         data_blob_clear(&blob);
1885                         r.in.buffer = &blob;
1886                         r.in.offered = needed;
1887
1888                         status = dcerpc_spoolss_GetJob(p, tctx, &r);
1889                         torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1890
1891                 }
1892                 torture_assert(tctx, r.out.info, "No job info returned");
1893                 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
1894
1895                 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
1896         }
1897
1898         return true;
1899 }
1900
1901 static bool test_SetJob(struct torture_context *tctx,
1902                         struct dcerpc_pipe *p,
1903                         struct policy_handle *handle, uint32_t job_id,
1904                         enum spoolss_JobControl command)
1905 {
1906         NTSTATUS status;
1907         struct spoolss_SetJob r;
1908
1909         r.in.handle     = handle;
1910         r.in.job_id     = job_id;
1911         r.in.ctr        = NULL;
1912         r.in.command    = command;
1913
1914         switch (command) {
1915         case SPOOLSS_JOB_CONTROL_PAUSE:
1916                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1917                 break;
1918         case SPOOLSS_JOB_CONTROL_RESUME:
1919                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1920                 break;
1921         case SPOOLSS_JOB_CONTROL_CANCEL:
1922                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1923                 break;
1924         case SPOOLSS_JOB_CONTROL_RESTART:
1925                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1926                 break;
1927         case SPOOLSS_JOB_CONTROL_DELETE:
1928                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1929                 break;
1930         case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
1931                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1932                 break;
1933         case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
1934                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1935                 break;
1936         case SPOOLSS_JOB_CONTROL_RETAIN:
1937                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1938                 break;
1939         case SPOOLSS_JOB_CONTROL_RELEASE:
1940                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1941                 break;
1942         default:
1943                 torture_comment(tctx, "Testing SetJob\n");
1944                 break;
1945         }
1946
1947         status = dcerpc_spoolss_SetJob(p, tctx, &r);
1948         torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
1949         torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
1950
1951         return true;
1952 }
1953
1954 static bool test_AddJob(struct torture_context *tctx,
1955                         struct dcerpc_pipe *p,
1956                         struct policy_handle *handle)
1957 {
1958         NTSTATUS status;
1959         struct spoolss_AddJob r;
1960         uint32_t needed;
1961
1962         r.in.level = 0;
1963         r.in.handle = handle;
1964         r.in.offered = 0;
1965         r.out.needed = &needed;
1966         r.in.buffer = r.out.buffer = NULL;
1967
1968         torture_comment(tctx, "Testing AddJob\n");
1969
1970         status = dcerpc_spoolss_AddJob(p, tctx, &r);
1971         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
1972
1973         r.in.level = 1;
1974
1975         status = dcerpc_spoolss_AddJob(p, tctx, &r);
1976         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
1977
1978         return true;
1979 }
1980
1981
1982 static bool test_EnumJobs(struct torture_context *tctx,
1983                           struct dcerpc_pipe *p,
1984                           struct policy_handle *handle)
1985 {
1986         NTSTATUS status;
1987         struct spoolss_EnumJobs r;
1988         uint32_t needed;
1989         uint32_t count;
1990         union spoolss_JobInfo *info;
1991
1992         r.in.handle = handle;
1993         r.in.firstjob = 0;
1994         r.in.numjobs = 0xffffffff;
1995         r.in.level = 1;
1996         r.in.buffer = NULL;
1997         r.in.offered = 0;
1998         r.out.needed = &needed;
1999         r.out.count = &count;
2000         r.out.info = &info;
2001
2002         torture_comment(tctx, "Testing EnumJobs\n");
2003
2004         status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
2005
2006         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
2007
2008         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2009                 int j;
2010                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2011                 data_blob_clear(&blob);
2012                 r.in.buffer = &blob;
2013                 r.in.offered = needed;
2014
2015                 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
2016
2017                 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
2018                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
2019                 torture_assert(tctx, info, "No jobs returned");
2020
2021                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2022
2023                 for (j = 0; j < count; j++) {
2024
2025                         torture_assert(tctx, test_GetJob(tctx, p, handle, info[j].info1.job_id),
2026                                 "failed to call test_GetJob");
2027
2028                         /* FIXME - gd */
2029                         if (!torture_setting_bool(tctx, "samba3", false)) {
2030                                 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
2031                                 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
2032                         }
2033                 }
2034
2035         } else {
2036                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
2037         }
2038
2039         return true;
2040 }
2041
2042 static bool test_DoPrintTest(struct torture_context *tctx,
2043                              struct dcerpc_pipe *p,
2044                              struct policy_handle *handle)
2045 {
2046         bool ret = true;
2047         NTSTATUS status;
2048         struct spoolss_StartDocPrinter s;
2049         struct spoolss_DocumentInfo1 info1;
2050         struct spoolss_StartPagePrinter sp;
2051         struct spoolss_WritePrinter w;
2052         struct spoolss_EndPagePrinter ep;
2053         struct spoolss_EndDocPrinter e;
2054         int i;
2055         uint32_t job_id;
2056         uint32_t num_written;
2057
2058         torture_comment(tctx, "Testing StartDocPrinter\n");
2059
2060         s.in.handle             = handle;
2061         s.in.level              = 1;
2062         s.in.info.info1         = &info1;
2063         s.out.job_id            = &job_id;
2064         info1.document_name     = "TorturePrintJob";
2065         info1.output_file       = NULL;
2066         info1.datatype          = "RAW";
2067
2068         status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
2069         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
2070         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
2071
2072         for (i=1; i < 4; i++) {
2073                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
2074
2075                 sp.in.handle            = handle;
2076
2077                 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
2078                 torture_assert_ntstatus_ok(tctx, status,
2079                                            "dcerpc_spoolss_StartPagePrinter failed");
2080                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
2081
2082                 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
2083
2084                 w.in.handle             = handle;
2085                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
2086                 w.out.num_written       = &num_written;
2087
2088                 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
2089                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
2090                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
2091
2092                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
2093
2094                 ep.in.handle            = handle;
2095
2096                 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
2097                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
2098                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
2099         }
2100
2101         torture_comment(tctx, "Testing EndDocPrinter\n");
2102
2103         e.in.handle = handle;
2104
2105         status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
2106         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
2107         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
2108
2109         ret &= test_AddJob(tctx, p, handle);
2110         ret &= test_EnumJobs(tctx, p, handle);
2111
2112         ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
2113
2114         return ret;
2115 }
2116
2117 static bool test_PausePrinter(struct torture_context *tctx,
2118                               struct dcerpc_pipe *p,
2119                               struct policy_handle *handle)
2120 {
2121         NTSTATUS status;
2122         struct spoolss_SetPrinter r;
2123         struct spoolss_SetPrinterInfoCtr info_ctr;
2124         struct spoolss_DevmodeContainer devmode_ctr;
2125         struct sec_desc_buf secdesc_ctr;
2126
2127         info_ctr.level = 0;
2128         info_ctr.info.info0 = NULL;
2129
2130         ZERO_STRUCT(devmode_ctr);
2131         ZERO_STRUCT(secdesc_ctr);
2132
2133         r.in.handle             = handle;
2134         r.in.info_ctr           = &info_ctr;
2135         r.in.devmode_ctr        = &devmode_ctr;
2136         r.in.secdesc_ctr        = &secdesc_ctr;
2137         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
2138
2139         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
2140
2141         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2142
2143         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2144
2145         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2146
2147         return true;
2148 }
2149
2150 static bool test_ResumePrinter(struct torture_context *tctx,
2151                                struct dcerpc_pipe *p,
2152                                struct policy_handle *handle)
2153 {
2154         NTSTATUS status;
2155         struct spoolss_SetPrinter r;
2156         struct spoolss_SetPrinterInfoCtr info_ctr;
2157         struct spoolss_DevmodeContainer devmode_ctr;
2158         struct sec_desc_buf secdesc_ctr;
2159
2160         info_ctr.level = 0;
2161         info_ctr.info.info0 = NULL;
2162
2163         ZERO_STRUCT(devmode_ctr);
2164         ZERO_STRUCT(secdesc_ctr);
2165
2166         r.in.handle             = handle;
2167         r.in.info_ctr           = &info_ctr;
2168         r.in.devmode_ctr        = &devmode_ctr;
2169         r.in.secdesc_ctr        = &secdesc_ctr;
2170         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
2171
2172         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2173
2174         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2175
2176         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2177
2178         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2179
2180         return true;
2181 }
2182
2183 static bool test_GetPrinterData(struct torture_context *tctx,
2184                                 struct dcerpc_pipe *p,
2185                                 struct policy_handle *handle,
2186                                 const char *value_name,
2187                                 enum winreg_Type *type_p,
2188                                 union spoolss_PrinterData *data_p)
2189 {
2190         NTSTATUS status;
2191         struct spoolss_GetPrinterData r;
2192         uint32_t needed;
2193         enum winreg_Type type;
2194         union spoolss_PrinterData data;
2195
2196         r.in.handle = handle;
2197         r.in.value_name = value_name;
2198         r.in.offered = 0;
2199         r.out.needed = &needed;
2200         r.out.type = &type;
2201         r.out.data = &data;
2202
2203         torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
2204
2205         status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2206         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2207
2208         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2209                 r.in.offered = needed;
2210
2211                 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2212                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2213         }
2214
2215         torture_assert_werr_ok(tctx, r.out.result,
2216                 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
2217
2218         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2219
2220         if (type_p) {
2221                 *type_p = type;
2222         }
2223
2224         if (data_p) {
2225                 *data_p = data;
2226         }
2227
2228         return true;
2229 }
2230
2231 static bool test_GetPrinterDataEx(struct torture_context *tctx,
2232                                   struct dcerpc_pipe *p,
2233                                   struct policy_handle *handle,
2234                                   const char *key_name,
2235                                   const char *value_name,
2236                                   enum winreg_Type *type_p,
2237                                   union spoolss_PrinterData *data_p)
2238 {
2239         NTSTATUS status;
2240         struct spoolss_GetPrinterDataEx r;
2241         enum winreg_Type type;
2242         uint32_t needed;
2243         union spoolss_PrinterData data;
2244
2245         r.in.handle = handle;
2246         r.in.key_name = key_name;
2247         r.in.value_name = value_name;
2248         r.in.offered = 0;
2249         r.out.type = &type;
2250         r.out.needed = &needed;
2251         r.out.data = &data;
2252
2253         torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
2254                 r.in.key_name, r.in.value_name);
2255
2256         status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2257         if (!NT_STATUS_IS_OK(status)) {
2258                 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
2259                     p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
2260                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
2261                 }
2262                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2263         }
2264
2265         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2266                 r.in.offered = needed;
2267                 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2268                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2269         }
2270
2271         torture_assert_werr_ok(tctx, r.out.result,
2272                 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
2273
2274         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2275
2276         if (type_p) {
2277                 *type_p = type;
2278         }
2279
2280         if (data_p) {
2281                 *data_p = data;
2282         }
2283
2284         return true;
2285 }
2286
2287 static bool test_GetPrinterData_list(struct torture_context *tctx,
2288                                      struct dcerpc_pipe *p,
2289                                      struct policy_handle *handle)
2290 {
2291         const char *list[] = {
2292                 "W3SvcInstalled",
2293                 "BeepEnabled",
2294                 "EventLog",
2295                 /* "NetPopup", not on w2k8 */
2296                 /* "NetPopupToComputer", not on w2k8 */
2297                 "MajorVersion",
2298                 "MinorVersion",
2299                 "DefaultSpoolDirectory",
2300                 "Architecture",
2301                 "DsPresent",
2302                 "OSVersion",
2303                 /* "OSVersionEx", not on s3 */
2304                 "DNSMachineName"
2305         };
2306         int i;
2307
2308         for (i=0; i < ARRAY_SIZE(list); i++) {
2309                 enum winreg_Type type, type_ex;
2310                 union spoolss_PrinterData data, data_ex;
2311
2312                 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, list[i], &type, &data),
2313                         talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
2314                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "random_string", list[i], &type_ex, &data_ex),
2315                         talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
2316                 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
2317                 switch (type) {
2318                 case REG_SZ:
2319                         torture_assert_str_equal(tctx, data.string, data_ex.string, "REG_SZ mismatch");
2320                         break;
2321                 case REG_DWORD:
2322                         torture_assert_int_equal(tctx, data.value, data_ex.value, "REG_DWORD mismatch");
2323                         break;
2324                 case REG_BINARY:
2325                         torture_assert_data_blob_equal(tctx, data.binary, data_ex.binary, "REG_BINARY mismatch");
2326                         break;
2327                 default:
2328                         break;
2329                 }
2330         }
2331
2332         return true;
2333 }
2334
2335 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
2336                                  struct policy_handle *handle)
2337 {
2338         NTSTATUS status;
2339         struct spoolss_EnumPrinterData r;
2340
2341         ZERO_STRUCT(r);
2342         r.in.handle = handle;
2343         r.in.enum_index = 0;
2344
2345         do {
2346                 uint32_t value_size = 0;
2347                 uint32_t data_size = 0;
2348                 enum winreg_Type type = 0;
2349
2350                 r.in.value_offered = value_size;
2351                 r.out.value_needed = &value_size;
2352                 r.in.data_offered = data_size;
2353                 r.out.data_needed = &data_size;
2354
2355                 r.out.type = &type;
2356                 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
2357
2358                 torture_comment(tctx, "Testing EnumPrinterData\n");
2359
2360                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2361
2362                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2363                 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
2364                         break;
2365                 }
2366                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData");
2367
2368                 r.in.value_offered = value_size;
2369                 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
2370                 r.in.data_offered = data_size;
2371                 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
2372
2373                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2374
2375                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2376                 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
2377                         break;
2378                 }
2379
2380                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData failed");
2381
2382                 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, r.out.value_name, NULL, NULL),
2383                         talloc_asprintf(tctx, "failed to call GetPrinterData for %s\n", r.out.value_name));
2384
2385                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", r.out.value_name, NULL, NULL),
2386                         talloc_asprintf(tctx, "failed to call GetPrinterDataEx on PrinterDriverData for %s\n", r.out.value_name));
2387
2388                 r.in.enum_index++;
2389
2390         } while (W_ERROR_IS_OK(r.out.result));
2391
2392         return true;
2393 }
2394
2395 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
2396                                    struct dcerpc_pipe *p,
2397                                    struct policy_handle *handle,
2398                                    const char *key_name)
2399 {
2400         struct spoolss_EnumPrinterDataEx r;
2401         struct spoolss_PrinterEnumValues *info;
2402         uint32_t needed;
2403         uint32_t count;
2404
2405         r.in.handle = handle;
2406         r.in.key_name = key_name;
2407         r.in.offered = 0;
2408         r.out.needed = &needed;
2409         r.out.count = &count;
2410         r.out.info = &info;
2411
2412         torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
2413
2414         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
2415                 "EnumPrinterDataEx failed");
2416         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2417                 r.in.offered = needed;
2418                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
2419                         "EnumPrinterDataEx failed");
2420         }
2421
2422         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
2423
2424         CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2425
2426         return true;
2427 }
2428
2429
2430 static bool test_DeletePrinterData(struct torture_context *tctx,
2431                                    struct dcerpc_pipe *p,
2432                                    struct policy_handle *handle,
2433                                    const char *value_name)
2434 {
2435         NTSTATUS status;
2436         struct spoolss_DeletePrinterData r;
2437
2438         r.in.handle = handle;
2439         r.in.value_name = value_name;
2440
2441         torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
2442                 r.in.value_name);
2443
2444         status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
2445
2446         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
2447         torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
2448
2449         return true;
2450 }
2451
2452 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
2453                                      struct dcerpc_pipe *p,
2454                                      struct policy_handle *handle,
2455                                      const char *key_name,
2456                                      const char *value_name)
2457 {
2458         struct spoolss_DeletePrinterDataEx r;
2459
2460         r.in.handle = handle;
2461         r.in.key_name = key_name;
2462         r.in.value_name = value_name;
2463
2464         torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
2465                 r.in.key_name, r.in.value_name);
2466
2467         torture_assert_ntstatus_ok(tctx,
2468                 dcerpc_spoolss_DeletePrinterDataEx(p, tctx, &r),
2469                 "DeletePrinterDataEx failed");
2470         torture_assert_werr_ok(tctx, r.out.result,
2471                 "DeletePrinterDataEx failed");
2472
2473         return true;
2474 }
2475
2476 static bool test_DeletePrinterKey(struct torture_context *tctx,
2477                                   struct dcerpc_pipe *p,
2478                                   struct policy_handle *handle,
2479                                   const char *key_name)
2480 {
2481         struct spoolss_DeletePrinterKey r;
2482
2483         r.in.handle = handle;
2484         r.in.key_name = key_name;
2485
2486         torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
2487
2488         if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
2489                 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
2490                 return true;
2491         }
2492
2493         torture_assert_ntstatus_ok(tctx,
2494                 dcerpc_spoolss_DeletePrinterKey(p, tctx, &r),
2495                 "DeletePrinterKey failed");
2496         torture_assert_werr_ok(tctx, r.out.result,
2497                 "DeletePrinterKey failed");
2498
2499         return true;
2500 }
2501
2502 static bool test_SetPrinterData(struct torture_context *tctx,
2503                                 struct dcerpc_pipe *p,
2504                                 struct policy_handle *handle)
2505 {
2506         NTSTATUS status;
2507         struct spoolss_SetPrinterData r;
2508         const char *values[] = {
2509                 "spootyfoot",
2510                 "spooty\\foot",
2511 #if 0
2512         /* FIXME: not working with s3 atm. */
2513                 "spooty,foot",
2514                 "spooty,fo,ot",
2515 #endif
2516                 "spooty foot",
2517 #if 0
2518         /* FIXME: not working with s3 atm. */
2519                 "spooty\\fo,ot",
2520                 "spooty,fo\\ot"
2521 #endif
2522         };
2523         int i;
2524
2525         for (i=0; i < ARRAY_SIZE(values); i++) {
2526
2527                 enum winreg_Type type;
2528                 union spoolss_PrinterData data;
2529
2530                 r.in.handle = handle;
2531                 r.in.value_name = values[i];
2532                 r.in.type = REG_SZ;
2533                 r.in.data.string = "dog";
2534
2535                 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
2536                         r.in.value_name);
2537
2538                 status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
2539
2540                 torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
2541                 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterData failed");
2542
2543                 if (!test_GetPrinterData(tctx, p, handle, r.in.value_name, &type, &data)) {
2544                         return false;
2545                 }
2546
2547                 torture_assert_int_equal(tctx, r.in.type, type, "type mismatch");
2548                 torture_assert_str_equal(tctx, r.in.data.string, data.string, "data mismatch");
2549
2550                 if (!test_DeletePrinterData(tctx, p, handle, r.in.value_name)) {
2551                         return false;
2552                 }
2553         }
2554
2555         return true;
2556 }
2557
2558 static bool test_EnumPrinterKey(struct torture_context *tctx,
2559                                 struct dcerpc_pipe *p,
2560                                 struct policy_handle *handle,
2561                                 const char *key_name,
2562                                 const char ***array);
2563
2564 static bool test_SetPrinterDataEx(struct torture_context *tctx,
2565                                   struct dcerpc_pipe *p,
2566                                   struct policy_handle *handle)
2567 {
2568         NTSTATUS status;
2569         struct spoolss_SetPrinterDataEx r;
2570         const char *value_name = "dog";
2571         const char *keys[] = {
2572                 "torturedataex",
2573                 "torture data ex",
2574 #if 0
2575         /* FIXME: not working with s3 atm. */
2576                 "torturedataex_with_subkey\\subkey",
2577                 "torturedataex_with_subkey\\subkey:0",
2578                 "torturedataex_with_subkey\\subkey:1",
2579                 "torturedataex_with_subkey\\subkey\\subsubkey",
2580                 "torturedataex_with_subkey\\subkey\\subsubkey:0",
2581                 "torturedataex_with_subkey\\subkey\\subsubkey:1",
2582 #endif
2583                 "torture,data",
2584 #if 0
2585         /* FIXME: not working with s3 atm. */
2586
2587                 "torture,data,ex",
2588                 "torture,data\\ex",
2589                 "torture\\data,ex"
2590 #endif
2591         };
2592         int i;
2593         DATA_BLOB blob = data_blob_string_const("catfoobar");
2594
2595
2596         for (i=0; i < ARRAY_SIZE(keys); i++) {
2597
2598                 char *c;
2599                 const char *key;
2600                 enum winreg_Type type;
2601                 const char **subkeys;
2602                 union spoolss_PrinterData data;
2603
2604                 r.in.handle = handle;
2605                 r.in.key_name = keys[i];
2606                 r.in.value_name = value_name;
2607                 r.in.type = REG_BINARY;
2608                 r.in.data.binary = blob;
2609
2610                 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s)\n", r.in.key_name, value_name);
2611
2612                 status = dcerpc_spoolss_SetPrinterDataEx(p, tctx, &r);
2613
2614                 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
2615                 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
2616
2617                 key = talloc_strdup(tctx, r.in.key_name);
2618
2619                 if (!test_GetPrinterDataEx(tctx, p, handle, r.in.key_name, value_name, &type, &data)) {
2620                         return false;
2621                 }
2622
2623                 torture_assert_int_equal(tctx, r.in.type, type, "type mismatch");
2624                 torture_assert_data_blob_equal(tctx, blob, data.binary, "data mismatch");
2625
2626                 if (!test_EnumPrinterDataEx(tctx, p, handle, r.in.key_name)) {
2627                         return false;
2628                 }
2629
2630                 if (!test_DeletePrinterDataEx(tctx, p, handle, r.in.key_name, value_name)) {
2631                         return false;
2632                 }
2633
2634                 c = strchr(key, '\\');
2635                 if (c) {
2636                         int i;
2637
2638                         /* we have subkeys */
2639
2640                         *c = 0;
2641
2642                         if (!test_EnumPrinterKey(tctx, p, handle, key, &subkeys)) {
2643                                 return false;
2644                         }
2645
2646                         for (i=0; subkeys && subkeys[i]; i++) {
2647
2648                                 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[i]);
2649
2650                                 if (!test_DeletePrinterKey(tctx, p, handle, current_key)) {
2651                                         return false;
2652                                 }
2653                         }
2654
2655                         if (!test_DeletePrinterKey(tctx, p, handle, key)) {
2656                                 return false;
2657                         }
2658
2659                 } else {
2660                         if (!test_DeletePrinterKey(tctx, p, handle, key)) {
2661                                 return false;
2662                         }
2663                 }
2664         }
2665
2666         return true;
2667 }
2668
2669
2670 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
2671                                        struct dcerpc_pipe *p,
2672                                        struct policy_handle *handle)
2673 {
2674         NTSTATUS status;
2675         struct dcerpc_binding *b;
2676         struct dcerpc_pipe *p2;
2677         struct spoolss_ClosePrinter cp;
2678
2679         /* only makes sense on SMB */
2680         if (p->conn->transport.transport != NCACN_NP) {
2681                 return true;
2682         }
2683
2684         torture_comment(tctx, "testing close on secondary pipe\n");
2685
2686         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
2687         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
2688
2689         status = dcerpc_secondary_connection(p, &p2, b);
2690         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
2691
2692         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
2693         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
2694
2695         cp.in.handle = handle;
2696         cp.out.handle = handle;
2697
2698         status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
2699         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
2700                         "ERROR: Allowed close on secondary connection");
2701
2702         torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
2703                                  "Unexpected fault code");
2704
2705         talloc_free(p2);
2706
2707         return true;
2708 }
2709
2710 static bool test_OpenPrinter_badname(struct torture_context *tctx,
2711                                      struct dcerpc_pipe *p, const char *name)
2712 {
2713         NTSTATUS status;
2714         struct spoolss_OpenPrinter op;
2715         struct spoolss_OpenPrinterEx opEx;
2716         struct policy_handle handle;
2717         bool ret = true;
2718
2719         op.in.printername       = name;
2720         op.in.datatype          = NULL;
2721         op.in.devmode_ctr.devmode= NULL;
2722         op.in.access_mask       = 0;
2723         op.out.handle           = &handle;
2724
2725         torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
2726
2727         status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
2728         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2729         if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
2730                 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
2731                         name, win_errstr(op.out.result));
2732         }
2733
2734         if (W_ERROR_IS_OK(op.out.result)) {
2735                 ret &=test_ClosePrinter(tctx, p, &handle);
2736         }
2737
2738         opEx.in.printername             = name;
2739         opEx.in.datatype                = NULL;
2740         opEx.in.devmode_ctr.devmode     = NULL;
2741         opEx.in.access_mask             = 0;
2742         opEx.in.level                   = 1;
2743         opEx.in.userlevel.level1        = NULL;
2744         opEx.out.handle                 = &handle;
2745
2746         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
2747
2748         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
2749         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2750         if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
2751                 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
2752                         name, win_errstr(opEx.out.result));
2753         }
2754
2755         if (W_ERROR_IS_OK(opEx.out.result)) {
2756                 ret &=test_ClosePrinter(tctx, p, &handle);
2757         }
2758
2759         return ret;
2760 }
2761
2762 static bool test_OpenPrinter(struct torture_context *tctx,
2763                              struct dcerpc_pipe *p,
2764                              const char *name)
2765 {
2766         NTSTATUS status;
2767         struct spoolss_OpenPrinter r;
2768         struct policy_handle handle;
2769         bool ret = true;
2770
2771         r.in.printername        = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
2772         r.in.datatype           = NULL;
2773         r.in.devmode_ctr.devmode= NULL;
2774         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
2775         r.out.handle            = &handle;
2776
2777         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
2778
2779         status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
2780
2781         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2782
2783         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
2784
2785         if (!test_GetPrinter(tctx, p, &handle)) {
2786                 ret = false;
2787         }
2788
2789         if (!torture_setting_bool(tctx, "samba3", false)) {
2790                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2791                         ret = false;
2792                 }
2793         }
2794
2795         if (!test_ClosePrinter(tctx, p, &handle)) {
2796                 ret = false;
2797         }
2798
2799         return ret;
2800 }
2801
2802 static bool call_OpenPrinterEx(struct torture_context *tctx,
2803                                struct dcerpc_pipe *p,
2804                                const char *name, struct policy_handle *handle)
2805 {
2806         struct spoolss_OpenPrinterEx r;
2807         struct spoolss_UserLevel1 userlevel1;
2808         NTSTATUS status;
2809
2810         if (name && name[0]) {
2811                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
2812                                                    dcerpc_server_name(p), name);
2813         } else {
2814                 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
2815                                                    dcerpc_server_name(p));
2816         }
2817
2818         r.in.datatype           = NULL;
2819         r.in.devmode_ctr.devmode= NULL;
2820         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
2821         r.in.level              = 1;
2822         r.in.userlevel.level1   = &userlevel1;
2823         r.out.handle = handle;
2824
2825         userlevel1.size = 1234;
2826         userlevel1.client = "hello";
2827         userlevel1.user = "spottyfoot!";
2828         userlevel1.build = 1;
2829         userlevel1.major = 2;
2830         userlevel1.minor = 3;
2831         userlevel1.processor = 4;
2832
2833         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
2834
2835         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
2836
2837         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2838
2839         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
2840
2841         return true;
2842 }
2843
2844 static bool test_OpenPrinterEx(struct torture_context *tctx,
2845                                struct dcerpc_pipe *p,
2846                                const char *name)
2847 {
2848         struct policy_handle handle;
2849         bool ret = true;
2850
2851         if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
2852                 return false;
2853         }
2854
2855         if (!test_GetPrinter(tctx, p, &handle)) {
2856                 ret = false;
2857         }
2858
2859         if (!test_EnumForms(tctx, p, &handle, false)) {
2860                 ret = false;
2861         }
2862
2863         if (!test_AddForm(tctx, p, &handle, false)) {
2864                 ret = false;
2865         }
2866
2867         if (!test_EnumPrinterData(tctx, p, &handle)) {
2868                 ret = false;
2869         }
2870
2871         if (!test_EnumPrinterDataEx(tctx, p, &handle, "PrinterDriverData")) {
2872                 ret = false;
2873         }
2874
2875         if (!test_printer_keys(tctx, p, &handle)) {
2876                 ret = false;
2877         }
2878
2879         if (!test_PausePrinter(tctx, p, &handle)) {
2880                 ret = false;
2881         }
2882
2883         if (!test_DoPrintTest(tctx, p, &handle)) {
2884                 ret = false;
2885         }
2886
2887         if (!test_ResumePrinter(tctx, p, &handle)) {
2888                 ret = false;
2889         }
2890
2891         if (!test_SetPrinterData(tctx, p, &handle)) {
2892                 ret = false;
2893         }
2894
2895         if (!test_SetPrinterDataEx(tctx, p, &handle)) {
2896                 ret = false;
2897         }
2898
2899         if (!torture_setting_bool(tctx, "samba3", false)) {
2900                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2901                         ret = false;
2902                 }
2903         }
2904
2905         if (!test_ClosePrinter(tctx, p, &handle)) {
2906                 ret = false;
2907         }
2908
2909         return ret;
2910 }
2911
2912 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
2913 {
2914         struct spoolss_EnumPrinters r;
2915         NTSTATUS status;
2916         uint16_t levels[] = {1, 2, 4, 5};
2917         int i;
2918         bool ret = true;
2919
2920         for (i=0;i<ARRAY_SIZE(levels);i++) {
2921                 union spoolss_PrinterInfo *info;
2922                 int j;
2923                 uint32_t needed;
2924                 uint32_t count;
2925
2926                 r.in.flags      = PRINTER_ENUM_LOCAL;
2927                 r.in.server     = "";
2928                 r.in.level      = levels[i];
2929                 r.in.buffer     = NULL;
2930                 r.in.offered    = 0;
2931                 r.out.needed    = &needed;
2932                 r.out.count     = &count;
2933                 r.out.info      = &info;
2934
2935                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
2936
2937                 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2938                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2939
2940                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2941                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2942                         data_blob_clear(&blob);
2943                         r.in.buffer = &blob;
2944                         r.in.offered = needed;
2945                         status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2946                 }
2947
2948                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2949
2950                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
2951
2952                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2953
2954                 if (!info) {
2955                         torture_comment(tctx, "No printers returned\n");
2956                         return true;
2957                 }
2958
2959                 for (j=0;j<count;j++) {
2960                         if (r.in.level == 1) {
2961                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
2962                                 char *slash, *name;
2963                                 name = unc;
2964                                 if (unc[0] == '\\' && unc[1] == '\\') {
2965                                         unc +=2;
2966                                 }
2967                                 slash = strchr(unc, '\\');
2968                                 if (slash) {
2969                                         slash++;
2970                                         name = slash;
2971                                 }
2972                                 if (!test_OpenPrinter(tctx, p, name)) {
2973                                         ret = false;
2974                                 }
2975                                 if (!test_OpenPrinterEx(tctx, p, name)) {
2976                                         ret = false;
2977                                 }
2978                         }
2979                 }
2980         }
2981
2982         return ret;
2983 }
2984
2985 static bool test_GetPrinterDriver(struct torture_context *tctx,
2986                                   struct dcerpc_pipe *p,
2987                                   struct policy_handle *handle,
2988                                   const char *driver_name)
2989 {
2990         struct spoolss_GetPrinterDriver r;
2991         uint32_t needed;
2992
2993         r.in.handle = handle;
2994         r.in.architecture = "W32X86";
2995         r.in.level = 1;
2996         r.in.buffer = NULL;
2997         r.in.offered = 0;
2998         r.out.needed = &needed;
2999
3000         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
3001
3002         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
3003                 "failed to call GetPrinterDriver");
3004         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3005                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3006                 data_blob_clear(&blob);
3007                 r.in.buffer = &blob;
3008                 r.in.offered = needed;
3009                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
3010                         "failed to call GetPrinterDriver");
3011         }
3012
3013         torture_assert_werr_ok(tctx, r.out.result,
3014                 "failed to call GetPrinterDriver");
3015
3016         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3017
3018         return true;
3019 }
3020
3021 static bool test_GetPrinterDriver2(struct torture_context *tctx,
3022                                    struct dcerpc_pipe *p,
3023                                    struct policy_handle *handle,
3024                                    const char *driver_name)
3025 {
3026         struct spoolss_GetPrinterDriver2 r;
3027         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
3028         uint32_t needed;
3029         uint32_t server_major_version;
3030         uint32_t server_minor_version;
3031         int i;
3032
3033         r.in.handle = handle;
3034         r.in.architecture = SPOOLSS_ARCHITECTURE_NT_X86;
3035         r.in.client_major_version = 3;
3036         r.in.client_minor_version = 0;
3037         r.out.needed = &needed;
3038         r.out.server_major_version = &server_major_version;
3039         r.out.server_minor_version = &server_minor_version;
3040
3041         for (i=0;i<ARRAY_SIZE(levels);i++) {
3042
3043                 r.in.buffer = NULL;
3044                 r.in.offered = 0;
3045                 r.in.level = levels[i];
3046
3047                 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
3048                         driver_name, r.in.level);
3049
3050                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
3051                         "failed to call GetPrinterDriver2");
3052                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3053                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3054                         data_blob_clear(&blob);
3055                         r.in.buffer = &blob;
3056                         r.in.offered = needed;
3057                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
3058                                 "failed to call GetPrinterDriver2");
3059                 }
3060
3061                 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
3062                         switch (r.in.level) {
3063                         case 101:
3064                         case 8:
3065                                 continue;
3066                         default:
3067                                 break;
3068                         }
3069                 }
3070
3071                 torture_assert_werr_ok(tctx, r.out.result,
3072                         "failed to call GetPrinterDriver2");
3073
3074                 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3075         }
3076
3077         return true;
3078 }
3079
3080 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
3081                                         struct dcerpc_pipe *p)
3082 {
3083         struct spoolss_EnumPrinterDrivers r;
3084         NTSTATUS status;
3085         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
3086         int i;
3087
3088         for (i=0;i<ARRAY_SIZE(levels);i++) {
3089
3090                 uint32_t needed;
3091                 uint32_t count;
3092                 union spoolss_DriverInfo *info;
3093
3094                 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
3095                 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
3096                 r.in.level = levels[i];
3097                 r.in.buffer = NULL;
3098                 r.in.offered = 0;
3099                 r.out.needed = &needed;
3100                 r.out.count = &count;
3101                 r.out.info = &info;
3102
3103                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
3104
3105                 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
3106
3107                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
3108
3109                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3110                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3111                         data_blob_clear(&blob);
3112                         r.in.buffer = &blob;
3113                         r.in.offered = needed;
3114                         status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
3115                 }
3116
3117                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
3118
3119                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
3120
3121                 if (!info) {
3122                         torture_comment(tctx, "No printer drivers returned\n");
3123                         break;
3124                 }
3125
3126                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3127         }
3128
3129         return true;
3130 }
3131
3132 static bool test_DeletePrinter(struct torture_context *tctx,
3133                                struct dcerpc_pipe *p,
3134                                struct policy_handle *handle)
3135 {
3136         struct spoolss_DeletePrinter r;
3137
3138         torture_comment(tctx, "Testing DeletePrinter\n");
3139
3140         r.in.handle = handle;
3141
3142         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter(p, tctx, &r),
3143                 "failed to delete printer");
3144         torture_assert_werr_ok(tctx, r.out.result,
3145                 "failed to delete printer");
3146
3147         return true;
3148 }
3149
3150 static bool test_EnumPrinters_findname(struct torture_context *tctx,
3151                                        struct dcerpc_pipe *p,
3152                                        uint32_t flags,
3153                                        uint32_t level,
3154                                        const char *name,
3155                                        bool *found)
3156 {
3157         struct spoolss_EnumPrinters e;
3158         uint32_t count;
3159         union spoolss_PrinterInfo *info;
3160         uint32_t needed;
3161         int i;
3162
3163         *found = false;
3164
3165         e.in.flags = flags;
3166         e.in.server = NULL;
3167         e.in.level = level;
3168         e.in.buffer = NULL;
3169         e.in.offered = 0;
3170         e.out.count = &count;
3171         e.out.info = &info;
3172         e.out.needed = &needed;
3173
3174         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
3175                 "failed to enum printers");
3176
3177         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
3178                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3179                 data_blob_clear(&blob);
3180                 e.in.buffer = &blob;
3181                 e.in.offered = needed;
3182
3183                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
3184                         "failed to enum printers");
3185         }
3186
3187         torture_assert_werr_ok(tctx, e.out.result,
3188                 "failed to enum printers");
3189
3190         for (i=0; i < count; i++) {
3191
3192                 const char *current = NULL;
3193
3194                 switch (level) {
3195                 case 1:
3196                         current = info[i].info1.name;
3197                         break;
3198                 }
3199
3200                 if (strequal(current, name)) {
3201                         *found = true;
3202                         break;
3203                 }
3204         }
3205
3206         return true;
3207 }
3208
3209 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
3210                                       struct dcerpc_pipe *p,
3211                                       const char *printername,
3212                                       bool ex)
3213 {
3214         WERROR result;
3215         struct spoolss_AddPrinter r;
3216         struct spoolss_AddPrinterEx rex;
3217         struct spoolss_SetPrinterInfoCtr info_ctr;
3218         struct spoolss_SetPrinterInfo1 info1;
3219         struct spoolss_DevmodeContainer devmode_ctr;
3220         struct sec_desc_buf secdesc_ctr;
3221         struct spoolss_UserLevelCtr userlevel_ctr;
3222         struct policy_handle handle;
3223         bool found = false;
3224
3225         ZERO_STRUCT(devmode_ctr);
3226         ZERO_STRUCT(secdesc_ctr);
3227         ZERO_STRUCT(userlevel_ctr);
3228         ZERO_STRUCT(info1);
3229
3230         torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
3231
3232         /* try to add printer to wellknown printer list (level 1) */
3233
3234         userlevel_ctr.level = 1;
3235
3236         info_ctr.info.info1 = &info1;
3237         info_ctr.level = 1;
3238
3239         rex.in.server = NULL;
3240         rex.in.info_ctr = &info_ctr;
3241         rex.in.devmode_ctr = &devmode_ctr;
3242         rex.in.secdesc_ctr = &secdesc_ctr;
3243         rex.in.userlevel_ctr = &userlevel_ctr;
3244         rex.out.handle = &handle;
3245
3246         r.in.server = NULL;
3247         r.in.info_ctr = &info_ctr;
3248         r.in.devmode_ctr = &devmode_ctr;
3249         r.in.secdesc_ctr = &secdesc_ctr;
3250         r.out.handle = &handle;
3251
3252         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3253                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3254                 "failed to add printer");
3255         result = ex ? rex.out.result : r.out.result;
3256         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
3257                 "unexpected result code");
3258
3259         info1.name = printername;
3260         info1.flags = PRINTER_ATTRIBUTE_SHARED;
3261
3262         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3263                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3264                 "failed to add printer");
3265         result = ex ? rex.out.result : r.out.result;
3266         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3267                 "unexpected result code");
3268
3269         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
3270            better do a real check to see the printer is really there */
3271
3272         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3273                                                         PRINTER_ENUM_NETWORK, 1,
3274                                                         printername,
3275                                                         &found),
3276                         "failed to enum printers");
3277
3278         torture_assert(tctx, found, "failed to find newly added printer");
3279
3280         info1.flags = 0;
3281
3282         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3283                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3284                 "failed to add printer");
3285         result = ex ? rex.out.result : r.out.result;
3286         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3287                 "unexpected result code");
3288
3289         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
3290            better do a real check to see the printer has really been removed
3291            from the well known printer list */
3292
3293         found = false;
3294
3295         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3296                                                         PRINTER_ENUM_NETWORK, 1,
3297                                                         printername,
3298                                                         &found),
3299                         "failed to enum printers");
3300 #if 0
3301         torture_assert(tctx, !found, "printer still in well known printer list");
3302 #endif
3303         return true;
3304 }
3305
3306 static bool test_AddPrinter_normal(struct torture_context *tctx,
3307                                    struct dcerpc_pipe *p,
3308                                    struct policy_handle *handle_p,
3309                                    const char *printername,
3310                                    const char *drivername,
3311                                    const char *portname,
3312                                    bool ex)
3313 {
3314         WERROR result;
3315         struct spoolss_AddPrinter r;
3316         struct spoolss_AddPrinterEx rex;
3317         struct spoolss_SetPrinterInfoCtr info_ctr;
3318         struct spoolss_SetPrinterInfo2 info2;
3319         struct spoolss_DevmodeContainer devmode_ctr;
3320         struct sec_desc_buf secdesc_ctr;
3321         struct spoolss_UserLevelCtr userlevel_ctr;
3322         struct policy_handle handle;
3323         bool found = false;
3324
3325         ZERO_STRUCT(devmode_ctr);
3326         ZERO_STRUCT(secdesc_ctr);
3327         ZERO_STRUCT(userlevel_ctr);
3328
3329         torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
3330
3331         userlevel_ctr.level = 1;
3332
3333         rex.in.server = NULL;
3334         rex.in.info_ctr = &info_ctr;
3335         rex.in.devmode_ctr = &devmode_ctr;
3336         rex.in.secdesc_ctr = &secdesc_ctr;
3337         rex.in.userlevel_ctr = &userlevel_ctr;
3338         rex.out.handle = &handle;
3339
3340         r.in.server = NULL;
3341         r.in.info_ctr = &info_ctr;
3342         r.in.devmode_ctr = &devmode_ctr;
3343         r.in.secdesc_ctr = &secdesc_ctr;
3344         r.out.handle = &handle;
3345
3346  again:
3347
3348         /* try to add printer to printer list (level 2) */
3349
3350         ZERO_STRUCT(info2);
3351
3352         info_ctr.info.info2 = &info2;
3353         info_ctr.level = 2;
3354
3355         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3356                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3357                 "failed to add printer");
3358         result = ex ? rex.out.result : r.out.result;
3359         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
3360                 "unexpected result code");
3361
3362         info2.printername = printername;
3363
3364         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3365                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3366                 "failed to add printer");
3367         result = ex ? rex.out.result : r.out.result;
3368
3369         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
3370                 struct policy_handle printer_handle;
3371
3372                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, &printer_handle),
3373                         "failed to open printer handle");
3374
3375                 torture_assert(tctx, test_DeletePrinter(tctx, p, &printer_handle),
3376                         "failed to delete printer");
3377
3378                 torture_assert(tctx, test_ClosePrinter(tctx, p, &printer_handle),
3379                         "failed to close server handle");
3380
3381                 goto again;
3382         }
3383
3384         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
3385                 "unexpected result code");
3386
3387         info2.portname = portname;
3388
3389         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3390                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3391                 "failed to add printer");
3392         result = ex ? rex.out.result : r.out.result;
3393         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
3394                 "unexpected result code");
3395
3396         info2.drivername = drivername;
3397
3398         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3399                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3400                 "failed to add printer");
3401         result = ex ? rex.out.result : r.out.result;
3402         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
3403                 "unexpected result code");
3404
3405         info2.printprocessor = "winprint";
3406
3407         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3408                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3409                 "failed to add printer");
3410         result = ex ? rex.out.result : r.out.result;
3411         torture_assert_werr_ok(tctx, result,
3412                 "failed to add printer");
3413
3414         *handle_p = handle;
3415
3416         /* we are paranoid, really check if the printer is there now */
3417
3418         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3419                                                         PRINTER_ENUM_LOCAL, 1,
3420                                                         printername,
3421                                                         &found),
3422                         "failed to enum printers");
3423         torture_assert(tctx, found, "failed to find newly added printer");
3424
3425         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3426                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3427                 "failed to add printer");
3428         result = ex ? rex.out.result : r.out.result;
3429         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3430                 "unexpected result code");
3431
3432         return true;
3433 }
3434
3435 static bool test_AddPrinterEx(struct torture_context *tctx,
3436                               struct dcerpc_pipe *p,
3437                               struct policy_handle *handle_p,
3438                               const char *printername,
3439                               const char *drivername,
3440                               const char *portname)
3441 {
3442         bool ret = true;
3443
3444         if (!torture_setting_bool(tctx, "samba3", false)) {
3445                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
3446                         torture_comment(tctx, "failed to add printer to well known list\n");
3447                         ret = false;
3448                 }
3449         }
3450
3451         if (!test_AddPrinter_normal(tctx, p, handle_p,
3452                                     printername, drivername, portname,
3453                                     true)) {
3454                 torture_comment(tctx, "failed to add printer to printer list\n");
3455                 ret = false;
3456         }
3457
3458         return ret;
3459 }
3460
3461 static bool test_AddPrinter(struct torture_context *tctx,
3462                             struct dcerpc_pipe *p,
3463                             struct policy_handle *handle_p,
3464                             const char *printername,
3465                             const char *drivername,
3466                             const char *portname)
3467 {
3468         bool ret = true;
3469
3470         if (!torture_setting_bool(tctx, "samba3", false)) {
3471                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
3472                         torture_comment(tctx, "failed to add printer to well known list\n");
3473                         ret = false;
3474                 }
3475         }
3476
3477         if (!test_AddPrinter_normal(tctx, p, handle_p,
3478                                     printername, drivername, portname,
3479                                     false)) {
3480                 torture_comment(tctx, "failed to add printer to printer list\n");
3481                 ret = false;
3482         }
3483
3484         return ret;
3485 }
3486
3487 static bool test_printer_info(struct torture_context *tctx,
3488                               struct dcerpc_pipe *p,
3489                               struct policy_handle *handle)
3490 {
3491         bool ret = true;
3492
3493         if (!test_PrinterInfo(tctx, p, handle)) {
3494                 ret = false;
3495         }
3496
3497         if (!test_SetPrinter_errors(tctx, p, handle)) {
3498                 ret = false;
3499         }
3500
3501         return ret;
3502 }
3503
3504 static bool test_EnumPrinterKey(struct torture_context *tctx,
3505                                 struct dcerpc_pipe *p,
3506                                 struct policy_handle *handle,
3507                                 const char *key_name,
3508                                 const char ***array)
3509 {
3510         struct spoolss_EnumPrinterKey r;
3511         uint32_t needed = 0;
3512         union spoolss_KeyNames key_buffer;
3513         int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
3514         uint32_t _ndr_size;
3515         int i;
3516
3517         r.in.handle = handle;
3518         r.in.key_name = key_name;
3519         r.out.key_buffer = &key_buffer;
3520         r.out.needed = &needed;
3521         r.out._ndr_size = &_ndr_size;
3522
3523         for (i=0; i < ARRAY_SIZE(offered); i++) {
3524
3525                 if (offered[i] < 0 && needed) {
3526                         if (needed <= 4) {
3527                                 continue;
3528                         }
3529                         r.in.offered = needed + offered[i];
3530                 } else {
3531                         r.in.offered = offered[i];
3532                 }
3533
3534                 ZERO_STRUCT(key_buffer);
3535
3536                 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
3537
3538                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
3539                         "failed to call EnumPrinterKey");
3540                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3541
3542                         torture_assert(tctx, (_ndr_size == r.in.offered/2),
3543                                 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
3544                                         _ndr_size, r.in.offered/2));
3545
3546                         r.in.offered = needed;
3547                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
3548                                 "failed to call EnumPrinterKey");
3549                 }
3550
3551                 if (offered[i] > 0) {
3552                         torture_assert_werr_ok(tctx, r.out.result,
3553                                 "failed to call EnumPrinterKey");
3554                 }
3555
3556                 torture_assert(tctx, (_ndr_size == r.in.offered/2),
3557                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
3558                                 _ndr_size, r.in.offered/2));
3559
3560                 torture_assert(tctx, (*r.out.needed <= r.in.offered),
3561                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
3562
3563                 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
3564                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
3565
3566                 if (key_buffer.string_array) {
3567                         uint32_t calc_needed = 0;
3568                         int s;
3569                         for (s=0; key_buffer.string_array[s]; s++) {
3570                                 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
3571                         }
3572                         if (!key_buffer.string_array[0]) {
3573                                 calc_needed += 2;
3574                         }
3575                         calc_needed += 2;
3576
3577                         torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
3578                                 "EnumPrinterKey unexpected size");
3579                 }
3580         }
3581
3582         if (array) {
3583                 *array = key_buffer.string_array;
3584         }
3585
3586         return true;
3587 }
3588
3589 bool test_printer_keys(struct torture_context *tctx,
3590                        struct dcerpc_pipe *p,
3591                        struct policy_handle *handle)
3592 {
3593         const char **key_array = NULL;
3594         int i;
3595
3596         torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, "", &key_array),
3597                 "failed to call test_EnumPrinterKey");
3598
3599         for (i=0; key_array && key_array[i]; i++) {
3600                 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, key_array[i], NULL),
3601                         "failed to call test_EnumPrinterKey");
3602         }
3603         for (i=0; key_array && key_array[i]; i++) {
3604                 torture_assert(tctx, test_EnumPrinterDataEx(tctx, p, handle, key_array[i]),
3605                         "failed to call test_EnumPrinterDataEx");
3606         }
3607
3608         return true;
3609 }
3610
3611 static bool test_printer(struct torture_context *tctx,
3612                          struct dcerpc_pipe *p)
3613 {
3614         bool ret = true;
3615         struct policy_handle handle[2];
3616         bool found = false;
3617         const char *drivername = "Microsoft XPS Document Writer";
3618         const char *portname = "LPT1:";
3619
3620         /* test printer created via AddPrinter */
3621
3622         if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
3623                 return false;
3624         }
3625
3626         if (!test_printer_info(tctx, p, &handle[0])) {
3627                 ret = false;
3628         }
3629
3630         if (!test_printer_keys(tctx, p, &handle[0])) {
3631                 ret = false;
3632         }
3633
3634         if (!test_DeletePrinter(tctx, p, &handle[0])) {
3635                 ret = false;
3636         }
3637
3638         if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3639                                         TORTURE_PRINTER, &found)) {
3640                 ret = false;
3641         }
3642
3643         torture_assert(tctx, !found, "deleted printer still there");
3644
3645         /* test printer created via AddPrinterEx */
3646
3647         if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
3648                 return false;
3649         }
3650
3651         if (!test_printer_info(tctx, p, &handle[1])) {
3652                 ret = false;
3653         }
3654
3655         if (!test_printer_keys(tctx, p, &handle[1])) {
3656                 ret = false;
3657         }
3658
3659         if (!test_DeletePrinter(tctx, p, &handle[1])) {
3660                 ret = false;
3661         }
3662
3663         if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3664                                         TORTURE_PRINTER_EX, &found)) {
3665                 ret = false;
3666         }
3667
3668         torture_assert(tctx, !found, "deleted printer still there");
3669
3670         return ret;
3671 }
3672
3673 bool torture_rpc_spoolss(struct torture_context *torture)
3674 {
3675         NTSTATUS status;
3676         struct dcerpc_pipe *p;
3677         bool ret = true;
3678         struct test_spoolss_context *ctx;
3679
3680         status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
3681         if (!NT_STATUS_IS_OK(status)) {
3682                 return false;
3683         }
3684
3685         ctx = talloc_zero(torture, struct test_spoolss_context);
3686
3687         ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
3688         ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle);
3689         ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
3690         ret &= test_AddForm(torture, p, &ctx->server_handle, true);
3691         ret &= test_EnumPorts(torture, p, ctx);
3692         ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
3693         ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
3694         ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_NT_X86);
3695         ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
3696         ret &= test_EnumMonitors(torture, p, ctx);
3697         ret &= test_EnumPrintProcessors(torture, p, ctx);
3698         ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
3699         ret &= test_EnumPrinters(torture, p, ctx);
3700         ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
3701         ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
3702         ret &= test_OpenPrinter_badname(torture, p, "");
3703         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
3704         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
3705         ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
3706         ret &= test_OpenPrinter_badname(torture, p,
3707                                         talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
3708
3709
3710         ret &= test_AddPort(torture, p);
3711         ret &= test_EnumPorts_old(torture, p);
3712         ret &= test_EnumPrinters_old(torture, p);
3713         ret &= test_EnumPrinterDrivers_old(torture, p);
3714
3715         return ret;
3716 }
3717
3718 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
3719 {
3720         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
3721
3722         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
3723                                                         "printer", &ndr_table_spoolss);
3724
3725         torture_rpc_tcase_add_test(tcase, "printer", test_printer);
3726
3727         return suite;
3728 }