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