s4-smbtorture: add test_ChangeID to RPC-SPOOLSS.
[ira/wip.git] / source4 / torture / rpc / spoolss.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for spoolss rpc operations
4
5    Copyright (C) Tim Potter 2003
6    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 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
2670                                          struct dcerpc_pipe *p,
2671                                          struct policy_handle *handle,
2672                                          uint32_t *change_id)
2673 {
2674         enum winreg_Type type;
2675         union spoolss_PrinterData data;
2676
2677         torture_assert(tctx,
2678                 test_GetPrinterData(tctx, p, handle, "ChangeID", &type, &data),
2679                 "failed to call GetPrinterData");
2680
2681         torture_assert(tctx, type == REG_DWORD, "unexpected type");
2682
2683         *change_id = data.value;
2684
2685         return true;
2686 }
2687
2688 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
2689                                            struct dcerpc_pipe *p,
2690                                            struct policy_handle *handle,
2691                                            uint32_t *change_id)
2692 {
2693         enum winreg_Type type;
2694         union spoolss_PrinterData data;
2695
2696         torture_assert(tctx,
2697                 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data),
2698                 "failed to call GetPrinterData");
2699
2700         torture_assert(tctx, type == REG_DWORD, "unexpected type");
2701
2702         *change_id = data.value;
2703
2704         return true;
2705 }
2706
2707 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
2708                                          struct dcerpc_pipe *p,
2709                                          struct policy_handle *handle,
2710                                          uint32_t *change_id)
2711 {
2712         union spoolss_PrinterInfo info;
2713
2714         torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 0, &info),
2715                 "failed to query Printer level 0");
2716
2717         *change_id = info.info0.change_id;
2718
2719         return true;
2720 }
2721
2722 static bool test_ChangeID(struct torture_context *tctx,
2723                           struct dcerpc_pipe *p,
2724                           struct policy_handle *handle)
2725 {
2726         uint32_t change_id, change_id_ex, change_id_info;
2727         uint32_t change_id2, change_id_ex2, change_id_info2;
2728         union spoolss_PrinterInfo info;
2729         const char *comment;
2730
2731
2732         torture_comment(tctx, "Testing ChangeID: id change test #1\n");
2733
2734         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
2735                 "failed to query for ChangeID");
2736         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
2737                 "failed to query for ChangeID");
2738         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
2739                 "failed to query for ChangeID");
2740
2741         torture_assert_int_equal(tctx, change_id, change_id_ex,
2742                 "change_ids should all be equal");
2743         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
2744                 "change_ids should all be equal");
2745
2746
2747         torture_comment(tctx, "Testing ChangeID: id change test #2\n");
2748
2749         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
2750                 "failed to query for ChangeID");
2751         torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
2752                 "failed to query Printer level 2");
2753         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
2754                 "failed to query for ChangeID");
2755         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
2756                 "failed to query for ChangeID");
2757         torture_assert_int_equal(tctx, change_id, change_id_ex,
2758                 "change_id should not have changed");
2759         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
2760                 "change_id should not have changed");
2761
2762
2763         torture_comment(tctx, "Testing ChangeID: id change test #3\n");
2764
2765         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
2766                 "failed to query for ChangeID");
2767         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
2768                 "failed to query for ChangeID");
2769         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
2770                 "failed to query for ChangeID");
2771         torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
2772                 "failed to query Printer level 2");
2773         comment = talloc_strdup(tctx, info.info2.comment);
2774
2775         {
2776                 struct spoolss_SetPrinterInfoCtr info_ctr;
2777                 struct spoolss_DevmodeContainer devmode_ctr;
2778                 struct sec_desc_buf secdesc_ctr;
2779                 struct spoolss_SetPrinterInfo2 info2;
2780
2781                 ZERO_STRUCT(info_ctr);
2782                 ZERO_STRUCT(devmode_ctr);
2783                 ZERO_STRUCT(secdesc_ctr);
2784
2785                 info2.servername        = info.info2.servername;
2786                 info2.printername       = info.info2.printername;
2787                 info2.sharename         = info.info2.sharename;
2788                 info2.portname          = info.info2.portname;
2789                 info2.drivername        = info.info2.drivername;
2790                 info2.comment           = "torture_comment";
2791                 info2.location          = info.info2.location;
2792                 info2.devmode_ptr       = 0;
2793                 info2.sepfile           = info.info2.sepfile;
2794                 info2.printprocessor    = info.info2.printprocessor;
2795                 info2.datatype          = info.info2.datatype;
2796                 info2.parameters        = info.info2.parameters;
2797                 info2.secdesc_ptr       = 0;
2798                 info2.attributes        = info.info2.attributes;
2799                 info2.priority          = info.info2.priority;
2800                 info2.defaultpriority   = info.info2.defaultpriority;
2801                 info2.starttime         = info.info2.starttime;
2802                 info2.untiltime         = info.info2.untiltime;
2803                 info2.status            = info.info2.status;
2804                 info2.cjobs             = info.info2.cjobs;
2805                 info2.averageppm        = info.info2.averageppm;
2806
2807                 info_ctr.level = 2;
2808                 info_ctr.info.info2 = &info2;
2809
2810                 torture_assert(tctx, test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
2811                         "failed to call SetPrinter");
2812
2813                 info2.comment           = comment;
2814
2815                 torture_assert(tctx, test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
2816                         "failed to call SetPrinter");
2817
2818         }
2819
2820         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id2),
2821                 "failed to query for ChangeID");
2822         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
2823                 "failed to query for ChangeID");
2824         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info2),
2825                 "failed to query for ChangeID");
2826
2827         torture_assert_int_equal(tctx, change_id2, change_id_ex2,
2828                 "change_ids should all be equal");
2829         torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
2830                 "change_ids should all be equal");
2831
2832         torture_assert(tctx, (change_id < change_id2),
2833                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
2834                 change_id2, change_id));
2835         torture_assert(tctx, (change_id_ex < change_id_ex2),
2836                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
2837                 change_id_ex2, change_id_ex));
2838         torture_assert(tctx, (change_id_info < change_id_info2),
2839                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
2840                 change_id_info2, change_id_info));
2841
2842         return true;
2843 }
2844
2845 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
2846                                        struct dcerpc_pipe *p,
2847                                        struct policy_handle *handle)
2848 {
2849         NTSTATUS status;
2850         struct dcerpc_binding *b;
2851         struct dcerpc_pipe *p2;
2852         struct spoolss_ClosePrinter cp;
2853
2854         /* only makes sense on SMB */
2855         if (p->conn->transport.transport != NCACN_NP) {
2856                 return true;
2857         }
2858
2859         torture_comment(tctx, "testing close on secondary pipe\n");
2860
2861         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
2862         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
2863
2864         status = dcerpc_secondary_connection(p, &p2, b);
2865         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
2866
2867         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
2868         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
2869
2870         cp.in.handle = handle;
2871         cp.out.handle = handle;
2872
2873         status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
2874         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
2875                         "ERROR: Allowed close on secondary connection");
2876
2877         torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
2878                                  "Unexpected fault code");
2879
2880         talloc_free(p2);
2881
2882         return true;
2883 }
2884
2885 static bool test_OpenPrinter_badname(struct torture_context *tctx,
2886                                      struct dcerpc_pipe *p, const char *name)
2887 {
2888         NTSTATUS status;
2889         struct spoolss_OpenPrinter op;
2890         struct spoolss_OpenPrinterEx opEx;
2891         struct policy_handle handle;
2892         bool ret = true;
2893
2894         op.in.printername       = name;
2895         op.in.datatype          = NULL;
2896         op.in.devmode_ctr.devmode= NULL;
2897         op.in.access_mask       = 0;
2898         op.out.handle           = &handle;
2899
2900         torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
2901
2902         status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
2903         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2904         if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
2905                 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
2906                         name, win_errstr(op.out.result));
2907         }
2908
2909         if (W_ERROR_IS_OK(op.out.result)) {
2910                 ret &=test_ClosePrinter(tctx, p, &handle);
2911         }
2912
2913         opEx.in.printername             = name;
2914         opEx.in.datatype                = NULL;
2915         opEx.in.devmode_ctr.devmode     = NULL;
2916         opEx.in.access_mask             = 0;
2917         opEx.in.level                   = 1;
2918         opEx.in.userlevel.level1        = NULL;
2919         opEx.out.handle                 = &handle;
2920
2921         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
2922
2923         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
2924         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2925         if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
2926                 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
2927                         name, win_errstr(opEx.out.result));
2928         }
2929
2930         if (W_ERROR_IS_OK(opEx.out.result)) {
2931                 ret &=test_ClosePrinter(tctx, p, &handle);
2932         }
2933
2934         return ret;
2935 }
2936
2937 static bool test_OpenPrinter(struct torture_context *tctx,
2938                              struct dcerpc_pipe *p,
2939                              const char *name)
2940 {
2941         NTSTATUS status;
2942         struct spoolss_OpenPrinter r;
2943         struct policy_handle handle;
2944         bool ret = true;
2945
2946         r.in.printername        = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
2947         r.in.datatype           = NULL;
2948         r.in.devmode_ctr.devmode= NULL;
2949         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
2950         r.out.handle            = &handle;
2951
2952         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
2953
2954         status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
2955
2956         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2957
2958         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
2959
2960         if (!test_GetPrinter(tctx, p, &handle)) {
2961                 ret = false;
2962         }
2963
2964         if (!torture_setting_bool(tctx, "samba3", false)) {
2965                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2966                         ret = false;
2967                 }
2968         }
2969
2970         if (!test_ClosePrinter(tctx, p, &handle)) {
2971                 ret = false;
2972         }
2973
2974         return ret;
2975 }
2976
2977 static bool call_OpenPrinterEx(struct torture_context *tctx,
2978                                struct dcerpc_pipe *p,
2979                                const char *name, struct policy_handle *handle)
2980 {
2981         struct spoolss_OpenPrinterEx r;
2982         struct spoolss_UserLevel1 userlevel1;
2983         NTSTATUS status;
2984
2985         if (name && name[0]) {
2986                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
2987                                                    dcerpc_server_name(p), name);
2988         } else {
2989                 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
2990                                                    dcerpc_server_name(p));
2991         }
2992
2993         r.in.datatype           = NULL;
2994         r.in.devmode_ctr.devmode= NULL;
2995         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
2996         r.in.level              = 1;
2997         r.in.userlevel.level1   = &userlevel1;
2998         r.out.handle = handle;
2999
3000         userlevel1.size = 1234;
3001         userlevel1.client = "hello";
3002         userlevel1.user = "spottyfoot!";
3003         userlevel1.build = 1;
3004         userlevel1.major = 2;
3005         userlevel1.minor = 3;
3006         userlevel1.processor = 4;
3007
3008         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
3009
3010         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
3011
3012         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
3013
3014         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
3015
3016         return true;
3017 }
3018
3019 static bool test_OpenPrinterEx(struct torture_context *tctx,
3020                                struct dcerpc_pipe *p,
3021                                const char *name)
3022 {
3023         struct policy_handle handle;
3024         bool ret = true;
3025
3026         if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
3027                 return false;
3028         }
3029
3030         if (!test_GetPrinter(tctx, p, &handle)) {
3031                 ret = false;
3032         }
3033
3034         if (!test_EnumForms(tctx, p, &handle, false)) {
3035                 ret = false;
3036         }
3037
3038         if (!test_AddForm(tctx, p, &handle, false)) {
3039                 ret = false;
3040         }
3041
3042         if (!test_EnumPrinterData(tctx, p, &handle)) {
3043                 ret = false;
3044         }
3045
3046         if (!test_EnumPrinterDataEx(tctx, p, &handle, "PrinterDriverData")) {
3047                 ret = false;
3048         }
3049
3050         if (!test_printer_keys(tctx, p, &handle)) {
3051                 ret = false;
3052         }
3053
3054         if (!test_PausePrinter(tctx, p, &handle)) {
3055                 ret = false;
3056         }
3057
3058         if (!test_DoPrintTest(tctx, p, &handle)) {
3059                 ret = false;
3060         }
3061
3062         if (!test_ResumePrinter(tctx, p, &handle)) {
3063                 ret = false;
3064         }
3065
3066         if (!test_SetPrinterData(tctx, p, &handle)) {
3067                 ret = false;
3068         }
3069
3070         if (!test_SetPrinterDataEx(tctx, p, &handle)) {
3071                 ret = false;
3072         }
3073
3074         if (!test_ChangeID(tctx, p, &handle)) {
3075                 ret = false;
3076         }
3077
3078         if (!torture_setting_bool(tctx, "samba3", false)) {
3079                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
3080                         ret = false;
3081                 }
3082         }
3083
3084         if (!test_ClosePrinter(tctx, p, &handle)) {
3085                 ret = false;
3086         }
3087
3088         return ret;
3089 }
3090
3091 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
3092 {
3093         struct spoolss_EnumPrinters r;
3094         NTSTATUS status;
3095         uint16_t levels[] = {1, 2, 4, 5};
3096         int i;
3097         bool ret = true;
3098
3099         for (i=0;i<ARRAY_SIZE(levels);i++) {
3100                 union spoolss_PrinterInfo *info;
3101                 int j;
3102                 uint32_t needed;
3103                 uint32_t count;
3104
3105                 r.in.flags      = PRINTER_ENUM_LOCAL;
3106                 r.in.server     = "";
3107                 r.in.level      = levels[i];
3108                 r.in.buffer     = NULL;
3109                 r.in.offered    = 0;
3110                 r.out.needed    = &needed;
3111                 r.out.count     = &count;
3112                 r.out.info      = &info;
3113
3114                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
3115
3116                 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
3117                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
3118
3119                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3120                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3121                         data_blob_clear(&blob);
3122                         r.in.buffer = &blob;
3123                         r.in.offered = needed;
3124                         status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
3125                 }
3126
3127                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
3128
3129                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
3130
3131                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3132
3133                 if (!info) {
3134                         torture_comment(tctx, "No printers returned\n");
3135                         return true;
3136                 }
3137
3138                 for (j=0;j<count;j++) {
3139                         if (r.in.level == 1) {
3140                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
3141                                 char *slash, *name;
3142                                 name = unc;
3143                                 if (unc[0] == '\\' && unc[1] == '\\') {
3144                                         unc +=2;
3145                                 }
3146                                 slash = strchr(unc, '\\');
3147                                 if (slash) {
3148                                         slash++;
3149                                         name = slash;
3150                                 }
3151                                 if (!test_OpenPrinter(tctx, p, name)) {
3152                                         ret = false;
3153                                 }
3154                                 if (!test_OpenPrinterEx(tctx, p, name)) {
3155                                         ret = false;
3156                                 }
3157                         }
3158                 }
3159         }
3160
3161         return ret;
3162 }
3163
3164 static bool test_GetPrinterDriver(struct torture_context *tctx,
3165                                   struct dcerpc_pipe *p,
3166                                   struct policy_handle *handle,
3167                                   const char *driver_name)
3168 {
3169         struct spoolss_GetPrinterDriver r;
3170         uint32_t needed;
3171
3172         r.in.handle = handle;
3173         r.in.architecture = "W32X86";
3174         r.in.level = 1;
3175         r.in.buffer = NULL;
3176         r.in.offered = 0;
3177         r.out.needed = &needed;
3178
3179         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
3180
3181         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
3182                 "failed to call GetPrinterDriver");
3183         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3184                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3185                 data_blob_clear(&blob);
3186                 r.in.buffer = &blob;
3187                 r.in.offered = needed;
3188                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
3189                         "failed to call GetPrinterDriver");
3190         }
3191
3192         torture_assert_werr_ok(tctx, r.out.result,
3193                 "failed to call GetPrinterDriver");
3194
3195         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3196
3197         return true;
3198 }
3199
3200 static bool test_GetPrinterDriver2(struct torture_context *tctx,
3201                                    struct dcerpc_pipe *p,
3202                                    struct policy_handle *handle,
3203                                    const char *driver_name)
3204 {
3205         struct spoolss_GetPrinterDriver2 r;
3206         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
3207         uint32_t needed;
3208         uint32_t server_major_version;
3209         uint32_t server_minor_version;
3210         int i;
3211
3212         r.in.handle = handle;
3213         r.in.architecture = SPOOLSS_ARCHITECTURE_NT_X86;
3214         r.in.client_major_version = 3;
3215         r.in.client_minor_version = 0;
3216         r.out.needed = &needed;
3217         r.out.server_major_version = &server_major_version;
3218         r.out.server_minor_version = &server_minor_version;
3219
3220         for (i=0;i<ARRAY_SIZE(levels);i++) {
3221
3222                 r.in.buffer = NULL;
3223                 r.in.offered = 0;
3224                 r.in.level = levels[i];
3225
3226                 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
3227                         driver_name, r.in.level);
3228
3229                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
3230                         "failed to call GetPrinterDriver2");
3231                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3232                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3233                         data_blob_clear(&blob);
3234                         r.in.buffer = &blob;
3235                         r.in.offered = needed;
3236                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
3237                                 "failed to call GetPrinterDriver2");
3238                 }
3239
3240                 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
3241                         switch (r.in.level) {
3242                         case 101:
3243                         case 8:
3244                                 continue;
3245                         default:
3246                                 break;
3247                         }
3248                 }
3249
3250                 torture_assert_werr_ok(tctx, r.out.result,
3251                         "failed to call GetPrinterDriver2");
3252
3253                 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3254         }
3255
3256         return true;
3257 }
3258
3259 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
3260                                         struct dcerpc_pipe *p)
3261 {
3262         struct spoolss_EnumPrinterDrivers r;
3263         NTSTATUS status;
3264         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
3265         int i;
3266
3267         for (i=0;i<ARRAY_SIZE(levels);i++) {
3268
3269                 uint32_t needed;
3270                 uint32_t count;
3271                 union spoolss_DriverInfo *info;
3272
3273                 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
3274                 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
3275                 r.in.level = levels[i];
3276                 r.in.buffer = NULL;
3277                 r.in.offered = 0;
3278                 r.out.needed = &needed;
3279                 r.out.count = &count;
3280                 r.out.info = &info;
3281
3282                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
3283
3284                 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
3285
3286                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
3287
3288                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3289                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3290                         data_blob_clear(&blob);
3291                         r.in.buffer = &blob;
3292                         r.in.offered = needed;
3293                         status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
3294                 }
3295
3296                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
3297
3298                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
3299
3300                 if (!info) {
3301                         torture_comment(tctx, "No printer drivers returned\n");
3302                         break;
3303                 }
3304
3305                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3306         }
3307
3308         return true;
3309 }
3310
3311 static bool test_DeletePrinter(struct torture_context *tctx,
3312                                struct dcerpc_pipe *p,
3313                                struct policy_handle *handle)
3314 {
3315         struct spoolss_DeletePrinter r;
3316
3317         torture_comment(tctx, "Testing DeletePrinter\n");
3318
3319         r.in.handle = handle;
3320
3321         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter(p, tctx, &r),
3322                 "failed to delete printer");
3323         torture_assert_werr_ok(tctx, r.out.result,
3324                 "failed to delete printer");
3325
3326         return true;
3327 }
3328
3329 static bool test_EnumPrinters_findname(struct torture_context *tctx,
3330                                        struct dcerpc_pipe *p,
3331                                        uint32_t flags,
3332                                        uint32_t level,
3333                                        const char *name,
3334                                        bool *found)
3335 {
3336         struct spoolss_EnumPrinters e;
3337         uint32_t count;
3338         union spoolss_PrinterInfo *info;
3339         uint32_t needed;
3340         int i;
3341
3342         *found = false;
3343
3344         e.in.flags = flags;
3345         e.in.server = NULL;
3346         e.in.level = level;
3347         e.in.buffer = NULL;
3348         e.in.offered = 0;
3349         e.out.count = &count;
3350         e.out.info = &info;
3351         e.out.needed = &needed;
3352
3353         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
3354                 "failed to enum printers");
3355
3356         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
3357                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3358                 data_blob_clear(&blob);
3359                 e.in.buffer = &blob;
3360                 e.in.offered = needed;
3361
3362                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
3363                         "failed to enum printers");
3364         }
3365
3366         torture_assert_werr_ok(tctx, e.out.result,
3367                 "failed to enum printers");
3368
3369         for (i=0; i < count; i++) {
3370
3371                 const char *current = NULL;
3372
3373                 switch (level) {
3374                 case 1:
3375                         current = info[i].info1.name;
3376                         break;
3377                 }
3378
3379                 if (strequal(current, name)) {
3380                         *found = true;
3381                         break;
3382                 }
3383         }
3384
3385         return true;
3386 }
3387
3388 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
3389                                       struct dcerpc_pipe *p,
3390                                       const char *printername,
3391                                       bool ex)
3392 {
3393         WERROR result;
3394         struct spoolss_AddPrinter r;
3395         struct spoolss_AddPrinterEx rex;
3396         struct spoolss_SetPrinterInfoCtr info_ctr;
3397         struct spoolss_SetPrinterInfo1 info1;
3398         struct spoolss_DevmodeContainer devmode_ctr;
3399         struct sec_desc_buf secdesc_ctr;
3400         struct spoolss_UserLevelCtr userlevel_ctr;
3401         struct policy_handle handle;
3402         bool found = false;
3403
3404         ZERO_STRUCT(devmode_ctr);
3405         ZERO_STRUCT(secdesc_ctr);
3406         ZERO_STRUCT(userlevel_ctr);
3407         ZERO_STRUCT(info1);
3408
3409         torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
3410
3411         /* try to add printer to wellknown printer list (level 1) */
3412
3413         userlevel_ctr.level = 1;
3414
3415         info_ctr.info.info1 = &info1;
3416         info_ctr.level = 1;
3417
3418         rex.in.server = NULL;
3419         rex.in.info_ctr = &info_ctr;
3420         rex.in.devmode_ctr = &devmode_ctr;
3421         rex.in.secdesc_ctr = &secdesc_ctr;
3422         rex.in.userlevel_ctr = &userlevel_ctr;
3423         rex.out.handle = &handle;
3424
3425         r.in.server = NULL;
3426         r.in.info_ctr = &info_ctr;
3427         r.in.devmode_ctr = &devmode_ctr;
3428         r.in.secdesc_ctr = &secdesc_ctr;
3429         r.out.handle = &handle;
3430
3431         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3432                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3433                 "failed to add printer");
3434         result = ex ? rex.out.result : r.out.result;
3435         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
3436                 "unexpected result code");
3437
3438         info1.name = printername;
3439         info1.flags = PRINTER_ATTRIBUTE_SHARED;
3440
3441         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3442                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3443                 "failed to add printer");
3444         result = ex ? rex.out.result : r.out.result;
3445         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3446                 "unexpected result code");
3447
3448         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
3449            better do a real check to see the printer is really there */
3450
3451         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3452                                                         PRINTER_ENUM_NETWORK, 1,
3453                                                         printername,
3454                                                         &found),
3455                         "failed to enum printers");
3456
3457         torture_assert(tctx, found, "failed to find newly added printer");
3458
3459         info1.flags = 0;
3460
3461         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3462                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3463                 "failed to add printer");
3464         result = ex ? rex.out.result : r.out.result;
3465         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3466                 "unexpected result code");
3467
3468         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
3469            better do a real check to see the printer has really been removed
3470            from the well known printer list */
3471
3472         found = false;
3473
3474         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3475                                                         PRINTER_ENUM_NETWORK, 1,
3476                                                         printername,
3477                                                         &found),
3478                         "failed to enum printers");
3479 #if 0
3480         torture_assert(tctx, !found, "printer still in well known printer list");
3481 #endif
3482         return true;
3483 }
3484
3485 static bool test_AddPrinter_normal(struct torture_context *tctx,
3486                                    struct dcerpc_pipe *p,
3487                                    struct policy_handle *handle_p,
3488                                    const char *printername,
3489                                    const char *drivername,
3490                                    const char *portname,
3491                                    bool ex)
3492 {
3493         WERROR result;
3494         struct spoolss_AddPrinter r;
3495         struct spoolss_AddPrinterEx rex;
3496         struct spoolss_SetPrinterInfoCtr info_ctr;
3497         struct spoolss_SetPrinterInfo2 info2;
3498         struct spoolss_DevmodeContainer devmode_ctr;
3499         struct sec_desc_buf secdesc_ctr;
3500         struct spoolss_UserLevelCtr userlevel_ctr;
3501         struct policy_handle handle;
3502         bool found = false;
3503
3504         ZERO_STRUCT(devmode_ctr);
3505         ZERO_STRUCT(secdesc_ctr);
3506         ZERO_STRUCT(userlevel_ctr);
3507
3508         torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
3509
3510         userlevel_ctr.level = 1;
3511
3512         rex.in.server = NULL;
3513         rex.in.info_ctr = &info_ctr;
3514         rex.in.devmode_ctr = &devmode_ctr;
3515         rex.in.secdesc_ctr = &secdesc_ctr;
3516         rex.in.userlevel_ctr = &userlevel_ctr;
3517         rex.out.handle = &handle;
3518
3519         r.in.server = NULL;
3520         r.in.info_ctr = &info_ctr;
3521         r.in.devmode_ctr = &devmode_ctr;
3522         r.in.secdesc_ctr = &secdesc_ctr;
3523         r.out.handle = &handle;
3524
3525  again:
3526
3527         /* try to add printer to printer list (level 2) */
3528
3529         ZERO_STRUCT(info2);
3530
3531         info_ctr.info.info2 = &info2;
3532         info_ctr.level = 2;
3533
3534         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3535                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3536                 "failed to add printer");
3537         result = ex ? rex.out.result : r.out.result;
3538         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
3539                 "unexpected result code");
3540
3541         info2.printername = printername;
3542
3543         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3544                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3545                 "failed to add printer");
3546         result = ex ? rex.out.result : r.out.result;
3547
3548         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
3549                 struct policy_handle printer_handle;
3550
3551                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, &printer_handle),
3552                         "failed to open printer handle");
3553
3554                 torture_assert(tctx, test_DeletePrinter(tctx, p, &printer_handle),
3555                         "failed to delete printer");
3556
3557                 torture_assert(tctx, test_ClosePrinter(tctx, p, &printer_handle),
3558                         "failed to close server handle");
3559
3560                 goto again;
3561         }
3562
3563         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
3564                 "unexpected result code");
3565
3566         info2.portname = portname;
3567
3568         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3569                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3570                 "failed to add printer");
3571         result = ex ? rex.out.result : r.out.result;
3572         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
3573                 "unexpected result code");
3574
3575         info2.drivername = drivername;
3576
3577         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3578                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3579                 "failed to add printer");
3580         result = ex ? rex.out.result : r.out.result;
3581         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
3582                 "unexpected result code");
3583
3584         info2.printprocessor = "winprint";
3585
3586         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3587                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3588                 "failed to add printer");
3589         result = ex ? rex.out.result : r.out.result;
3590         torture_assert_werr_ok(tctx, result,
3591                 "failed to add printer");
3592
3593         *handle_p = handle;
3594
3595         /* we are paranoid, really check if the printer is there now */
3596
3597         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
3598                                                         PRINTER_ENUM_LOCAL, 1,
3599                                                         printername,
3600                                                         &found),
3601                         "failed to enum printers");
3602         torture_assert(tctx, found, "failed to find newly added printer");
3603
3604         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
3605                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
3606                 "failed to add printer");
3607         result = ex ? rex.out.result : r.out.result;
3608         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
3609                 "unexpected result code");
3610
3611         return true;
3612 }
3613
3614 static bool test_AddPrinterEx(struct torture_context *tctx,
3615                               struct dcerpc_pipe *p,
3616                               struct policy_handle *handle_p,
3617                               const char *printername,
3618                               const char *drivername,
3619                               const char *portname)
3620 {
3621         bool ret = true;
3622
3623         if (!torture_setting_bool(tctx, "samba3", false)) {
3624                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
3625                         torture_comment(tctx, "failed to add printer to well known list\n");
3626                         ret = false;
3627                 }
3628         }
3629
3630         if (!test_AddPrinter_normal(tctx, p, handle_p,
3631                                     printername, drivername, portname,
3632                                     true)) {
3633                 torture_comment(tctx, "failed to add printer to printer list\n");
3634                 ret = false;
3635         }
3636
3637         return ret;
3638 }
3639
3640 static bool test_AddPrinter(struct torture_context *tctx,
3641                             struct dcerpc_pipe *p,
3642                             struct policy_handle *handle_p,
3643                             const char *printername,
3644                             const char *drivername,
3645                             const char *portname)
3646 {
3647         bool ret = true;
3648
3649         if (!torture_setting_bool(tctx, "samba3", false)) {
3650                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
3651                         torture_comment(tctx, "failed to add printer to well known list\n");
3652                         ret = false;
3653                 }
3654         }
3655
3656         if (!test_AddPrinter_normal(tctx, p, handle_p,
3657                                     printername, drivername, portname,
3658                                     false)) {
3659                 torture_comment(tctx, "failed to add printer to printer list\n");
3660                 ret = false;
3661         }
3662
3663         return ret;
3664 }
3665
3666 static bool test_printer_info(struct torture_context *tctx,
3667                               struct dcerpc_pipe *p,
3668                               struct policy_handle *handle)
3669 {
3670         bool ret = true;
3671
3672         if (!test_PrinterInfo(tctx, p, handle)) {
3673                 ret = false;
3674         }
3675
3676         if (!test_SetPrinter_errors(tctx, p, handle)) {
3677                 ret = false;
3678         }
3679
3680         return ret;
3681 }
3682
3683 static bool test_EnumPrinterKey(struct torture_context *tctx,
3684                                 struct dcerpc_pipe *p,
3685                                 struct policy_handle *handle,
3686                                 const char *key_name,
3687                                 const char ***array)
3688 {
3689         struct spoolss_EnumPrinterKey r;
3690         uint32_t needed = 0;
3691         union spoolss_KeyNames key_buffer;
3692         int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
3693         uint32_t _ndr_size;
3694         int i;
3695
3696         r.in.handle = handle;
3697         r.in.key_name = key_name;
3698         r.out.key_buffer = &key_buffer;
3699         r.out.needed = &needed;
3700         r.out._ndr_size = &_ndr_size;
3701
3702         for (i=0; i < ARRAY_SIZE(offered); i++) {
3703
3704                 if (offered[i] < 0 && needed) {
3705                         if (needed <= 4) {
3706                                 continue;
3707                         }
3708                         r.in.offered = needed + offered[i];
3709                 } else {
3710                         r.in.offered = offered[i];
3711                 }
3712
3713                 ZERO_STRUCT(key_buffer);
3714
3715                 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
3716
3717                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
3718                         "failed to call EnumPrinterKey");
3719                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3720
3721                         torture_assert(tctx, (_ndr_size == r.in.offered/2),
3722                                 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
3723                                         _ndr_size, r.in.offered/2));
3724
3725                         r.in.offered = needed;
3726                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
3727                                 "failed to call EnumPrinterKey");
3728                 }
3729
3730                 if (offered[i] > 0) {
3731                         torture_assert_werr_ok(tctx, r.out.result,
3732                                 "failed to call EnumPrinterKey");
3733                 }
3734
3735                 torture_assert(tctx, (_ndr_size == r.in.offered/2),
3736                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
3737                                 _ndr_size, r.in.offered/2));
3738
3739                 torture_assert(tctx, (*r.out.needed <= r.in.offered),
3740                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
3741
3742                 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
3743                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
3744
3745                 if (key_buffer.string_array) {
3746                         uint32_t calc_needed = 0;
3747                         int s;
3748                         for (s=0; key_buffer.string_array[s]; s++) {
3749                                 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
3750                         }
3751                         if (!key_buffer.string_array[0]) {
3752                                 calc_needed += 2;
3753                         }
3754                         calc_needed += 2;
3755
3756                         torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
3757                                 "EnumPrinterKey unexpected size");
3758                 }
3759         }
3760
3761         if (array) {
3762                 *array = key_buffer.string_array;
3763         }
3764
3765         return true;
3766 }
3767
3768 bool test_printer_keys(struct torture_context *tctx,
3769                        struct dcerpc_pipe *p,
3770                        struct policy_handle *handle)
3771 {
3772         const char **key_array = NULL;
3773         int i;
3774
3775         torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, "", &key_array),
3776                 "failed to call test_EnumPrinterKey");
3777
3778         for (i=0; key_array && key_array[i]; i++) {
3779                 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, key_array[i], NULL),
3780                         "failed to call test_EnumPrinterKey");
3781         }
3782         for (i=0; key_array && key_array[i]; i++) {
3783                 torture_assert(tctx, test_EnumPrinterDataEx(tctx, p, handle, key_array[i]),
3784                         "failed to call test_EnumPrinterDataEx");
3785         }
3786
3787         return true;
3788 }
3789
3790 static bool test_printer(struct torture_context *tctx,
3791                          struct dcerpc_pipe *p)
3792 {
3793         bool ret = true;
3794         struct policy_handle handle[2];
3795         bool found = false;
3796         const char *drivername = "Microsoft XPS Document Writer";
3797         const char *portname = "LPT1:";
3798
3799         /* test printer created via AddPrinter */
3800
3801         if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
3802                 return false;
3803         }
3804
3805         if (!test_printer_info(tctx, p, &handle[0])) {
3806                 ret = false;
3807         }
3808
3809         if (!test_printer_keys(tctx, p, &handle[0])) {
3810                 ret = false;
3811         }
3812
3813         if (!test_DeletePrinter(tctx, p, &handle[0])) {
3814                 ret = false;
3815         }
3816
3817         if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3818                                         TORTURE_PRINTER, &found)) {
3819                 ret = false;
3820         }
3821
3822         torture_assert(tctx, !found, "deleted printer still there");
3823
3824         /* test printer created via AddPrinterEx */
3825
3826         if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
3827                 return false;
3828         }
3829
3830         if (!test_printer_info(tctx, p, &handle[1])) {
3831                 ret = false;
3832         }
3833
3834         if (!test_printer_keys(tctx, p, &handle[1])) {
3835                 ret = false;
3836         }
3837
3838         if (!test_DeletePrinter(tctx, p, &handle[1])) {
3839                 ret = false;
3840         }
3841
3842         if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3843                                         TORTURE_PRINTER_EX, &found)) {
3844                 ret = false;
3845         }
3846
3847         torture_assert(tctx, !found, "deleted printer still there");
3848
3849         return ret;
3850 }
3851
3852 bool torture_rpc_spoolss(struct torture_context *torture)
3853 {
3854         NTSTATUS status;
3855         struct dcerpc_pipe *p;
3856         bool ret = true;
3857         struct test_spoolss_context *ctx;
3858
3859         status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
3860         if (!NT_STATUS_IS_OK(status)) {
3861                 return false;
3862         }
3863
3864         ctx = talloc_zero(torture, struct test_spoolss_context);
3865
3866         ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
3867         ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle);
3868         ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
3869         ret &= test_AddForm(torture, p, &ctx->server_handle, true);
3870         ret &= test_EnumPorts(torture, p, ctx);
3871         ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
3872         ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
3873         ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_NT_X86);
3874         ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
3875         ret &= test_EnumMonitors(torture, p, ctx);
3876         ret &= test_EnumPrintProcessors(torture, p, ctx);
3877         ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
3878         ret &= test_EnumPrinters(torture, p, ctx);
3879         ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
3880         ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
3881         ret &= test_OpenPrinter_badname(torture, p, "");
3882         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
3883         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
3884         ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
3885         ret &= test_OpenPrinter_badname(torture, p,
3886                                         talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
3887
3888
3889         ret &= test_AddPort(torture, p);
3890         ret &= test_EnumPorts_old(torture, p);
3891         ret &= test_EnumPrinters_old(torture, p);
3892         ret &= test_EnumPrinterDrivers_old(torture, p);
3893
3894         return ret;
3895 }
3896
3897 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
3898 {
3899         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
3900
3901         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
3902                                                         "printer", &ndr_table_spoolss);
3903
3904         torture_rpc_tcase_add_test(tcase, "printer", test_printer);
3905
3906         return suite;
3907 }