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