s3-spoolss: be very strict on OpenPrinter{Ex} failures for bad names.
[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         torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
4051                 "unexpected result");
4052
4053         if (W_ERROR_IS_OK(op.out.result)) {
4054                 ret &=test_ClosePrinter(tctx, p, &handle);
4055         }
4056
4057         opEx.in.printername             = name;
4058         opEx.in.datatype                = NULL;
4059         opEx.in.devmode_ctr.devmode     = NULL;
4060         opEx.in.access_mask             = 0;
4061         opEx.in.level                   = 1;
4062         opEx.in.userlevel.level1        = NULL;
4063         opEx.out.handle                 = &handle;
4064
4065         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
4066
4067         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
4068         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
4069         torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
4070                 "unexpected result");
4071
4072         if (W_ERROR_IS_OK(opEx.out.result)) {
4073                 ret &=test_ClosePrinter(tctx, p, &handle);
4074         }
4075
4076         return ret;
4077 }
4078
4079 static bool test_OpenPrinter(struct torture_context *tctx,
4080                              struct dcerpc_pipe *p,
4081                              const char *name,
4082                              const char *environment)
4083 {
4084         NTSTATUS status;
4085         struct spoolss_OpenPrinter r;
4086         struct policy_handle handle;
4087         bool ret = true;
4088
4089         r.in.printername        = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
4090         r.in.datatype           = NULL;
4091         r.in.devmode_ctr.devmode= NULL;
4092         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
4093         r.out.handle            = &handle;
4094
4095         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
4096
4097         status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
4098
4099         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
4100
4101         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
4102
4103         if (!test_GetPrinter(tctx, p, &handle, environment)) {
4104                 ret = false;
4105         }
4106
4107         if (!torture_setting_bool(tctx, "samba3", false)) {
4108                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
4109                         ret = false;
4110                 }
4111         }
4112
4113         if (!test_ClosePrinter(tctx, p, &handle)) {
4114                 ret = false;
4115         }
4116
4117         return ret;
4118 }
4119
4120 static bool call_OpenPrinterEx(struct torture_context *tctx,
4121                                struct dcerpc_pipe *p,
4122                                const char *name,
4123                                struct spoolss_DeviceMode *devmode,
4124                                struct policy_handle *handle)
4125 {
4126         struct spoolss_OpenPrinterEx r;
4127         struct spoolss_UserLevel1 userlevel1;
4128         NTSTATUS status;
4129
4130         if (name && name[0]) {
4131                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
4132                                                    dcerpc_server_name(p), name);
4133         } else {
4134                 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
4135                                                    dcerpc_server_name(p));
4136         }
4137
4138         r.in.datatype           = NULL;
4139         r.in.devmode_ctr.devmode= devmode;
4140         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
4141         r.in.level              = 1;
4142         r.in.userlevel.level1   = &userlevel1;
4143         r.out.handle = handle;
4144
4145         userlevel1.size = 1234;
4146         userlevel1.client = "hello";
4147         userlevel1.user = "spottyfoot!";
4148         userlevel1.build = 1;
4149         userlevel1.major = 2;
4150         userlevel1.minor = 3;
4151         userlevel1.processor = 4;
4152
4153         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
4154
4155         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
4156
4157         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
4158
4159         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
4160
4161         return true;
4162 }
4163
4164 static bool test_printer_rename(struct torture_context *tctx,
4165                                 struct dcerpc_pipe *p,
4166                                 struct policy_handle *handle,
4167                                 const char *name)
4168 {
4169         bool ret = true;
4170         union spoolss_PrinterInfo info;
4171         union spoolss_SetPrinterInfo sinfo;
4172         struct spoolss_SetPrinterInfoCtr info_ctr;
4173         struct spoolss_DevmodeContainer devmode_ctr;
4174         struct sec_desc_buf secdesc_ctr;
4175         const char *printer_name;
4176         const char *printer_name_orig;
4177         const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
4178         struct policy_handle new_handle;
4179         const char *q;
4180
4181         ZERO_STRUCT(devmode_ctr);
4182         ZERO_STRUCT(secdesc_ctr);
4183
4184         torture_comment(tctx, "Testing Printer rename operations\n");
4185
4186         torture_assert(tctx,
4187                 test_GetPrinter_level(tctx, p, handle, 2, &info),
4188                 "failed to call GetPrinter level 2");
4189
4190         printer_name_orig = talloc_strdup(tctx, info.info2.printername);
4191
4192         q = strrchr(info.info2.printername, '\\');
4193         if (q) {
4194                 torture_warning(tctx,
4195                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
4196         }
4197
4198         torture_assert(tctx,
4199                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
4200
4201         sinfo.info2->printername = printer_name_new;
4202
4203         info_ctr.level = 2;
4204         info_ctr.info = sinfo;
4205
4206         torture_assert(tctx,
4207                 test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
4208                 "failed to call SetPrinter level 2");
4209
4210         torture_assert(tctx,
4211                 test_GetPrinter_level(tctx, p, handle, 2, &info),
4212                 "failed to call GetPrinter level 2");
4213
4214         printer_name = talloc_strdup(tctx, info.info2.printername);
4215
4216         q = strrchr(info.info2.printername, '\\');
4217         if (q) {
4218                 torture_warning(tctx,
4219                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
4220                 q++;
4221                 printer_name = q;
4222         }
4223
4224         torture_assert_str_equal(tctx, printer_name, printer_name_new,
4225                 "new printer name was not set");
4226
4227         torture_assert(tctx,
4228                 test_OpenPrinter_badname(tctx, p, printer_name_orig),
4229                 "still can open printer with oldname");
4230
4231         torture_assert(tctx,
4232                 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
4233                 "failed to open printer with new name");
4234
4235         torture_assert(tctx,
4236                 test_GetPrinter_level(tctx, p, &new_handle, 2, &info),
4237                 "failed to call GetPrinter level 2");
4238
4239         /* FIXME: we openend with servername! */
4240         printer_name = talloc_asprintf(tctx, "\\\\%s\\%s",
4241                 dcerpc_server_name(p), printer_name_new);
4242
4243         torture_assert_str_equal(tctx, info.info2.printername, printer_name,
4244                 "new printer name was not set");
4245
4246         torture_assert(tctx,
4247                 test_ClosePrinter(tctx, p, &new_handle),
4248                 "failed to close printer");
4249
4250         return ret;
4251 }
4252
4253
4254 static bool test_OpenPrinterEx(struct torture_context *tctx,
4255                                struct dcerpc_pipe *p,
4256                                const char *name,
4257                                const char *environment)
4258 {
4259         struct policy_handle handle;
4260         bool ret = true;
4261
4262         if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
4263                 return false;
4264         }
4265
4266         if (!test_PrinterInfo_SD(tctx, p, &handle)) {
4267                 ret = false;
4268         }
4269
4270         if (!test_GetPrinter(tctx, p, &handle, environment)) {
4271                 ret = false;
4272         }
4273
4274         if (!test_EnumForms(tctx, p, &handle, false)) {
4275                 ret = false;
4276         }
4277
4278         if (!test_AddForm(tctx, p, &handle, false)) {
4279                 ret = false;
4280         }
4281
4282         if (!test_EnumPrinterData_all(tctx, p, &handle)) {
4283                 ret = false;
4284         }
4285
4286         if (!test_EnumPrinterDataEx(tctx, p, &handle, "PrinterDriverData", NULL, NULL)) {
4287                 ret = false;
4288         }
4289
4290         if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
4291                 ret = false;
4292         }
4293
4294         if (!test_printer_keys(tctx, p, &handle)) {
4295                 ret = false;
4296         }
4297
4298         if (!test_PausePrinter(tctx, p, &handle)) {
4299                 ret = false;
4300         }
4301
4302         if (!test_DoPrintTest(tctx, p, &handle)) {
4303                 ret = false;
4304         }
4305
4306         if (!test_ResumePrinter(tctx, p, &handle)) {
4307                 ret = false;
4308         }
4309
4310         if (!test_SetPrinterData_matrix(tctx, p, &handle, name, NULL, NULL)) {
4311                 ret = false;
4312         }
4313
4314         if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
4315                 ret = false;
4316         }
4317
4318         if (!torture_setting_bool(tctx, "samba3", false)) {
4319                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
4320                         ret = false;
4321                 }
4322         }
4323
4324         if (!test_ClosePrinter(tctx, p, &handle)) {
4325                 ret = false;
4326         }
4327
4328         return ret;
4329 }
4330
4331 static bool test_EnumPrinters_old(struct torture_context *tctx,
4332                                   struct dcerpc_pipe *p,
4333                                   const char *environment)
4334 {
4335         struct spoolss_EnumPrinters r;
4336         NTSTATUS status;
4337         uint16_t levels[] = {1, 2, 4, 5};
4338         int i;
4339         bool ret = true;
4340
4341         for (i=0;i<ARRAY_SIZE(levels);i++) {
4342                 union spoolss_PrinterInfo *info;
4343                 int j;
4344                 uint32_t needed;
4345                 uint32_t count;
4346
4347                 r.in.flags      = PRINTER_ENUM_LOCAL;
4348                 r.in.server     = "";
4349                 r.in.level      = levels[i];
4350                 r.in.buffer     = NULL;
4351                 r.in.offered    = 0;
4352                 r.out.needed    = &needed;
4353                 r.out.count     = &count;
4354                 r.out.info      = &info;
4355
4356                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
4357
4358                 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
4359                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
4360
4361                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4362                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4363                         data_blob_clear(&blob);
4364                         r.in.buffer = &blob;
4365                         r.in.offered = needed;
4366                         status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
4367                 }
4368
4369                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
4370
4371                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
4372
4373                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4374
4375                 if (!info) {
4376                         torture_comment(tctx, "No printers returned\n");
4377                         return true;
4378                 }
4379
4380                 for (j=0;j<count;j++) {
4381                         if (r.in.level == 1) {
4382                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
4383                                 char *slash, *name;
4384                                 name = unc;
4385                                 if (unc[0] == '\\' && unc[1] == '\\') {
4386                                         unc +=2;
4387                                 }
4388                                 slash = strchr(unc, '\\');
4389                                 if (slash) {
4390                                         slash++;
4391                                         name = slash;
4392                                 }
4393                                 if (!test_OpenPrinter(tctx, p, name, environment)) {
4394                                         ret = false;
4395                                 }
4396                                 if (!test_OpenPrinterEx(tctx, p, name, environment)) {
4397                                         ret = false;
4398                                 }
4399                         }
4400                 }
4401         }
4402
4403         return ret;
4404 }
4405
4406 static bool test_GetPrinterDriver(struct torture_context *tctx,
4407                                   struct dcerpc_pipe *p,
4408                                   struct policy_handle *handle,
4409                                   const char *driver_name)
4410 {
4411         struct spoolss_GetPrinterDriver r;
4412         uint32_t needed;
4413
4414         r.in.handle = handle;
4415         r.in.architecture = "W32X86";
4416         r.in.level = 1;
4417         r.in.buffer = NULL;
4418         r.in.offered = 0;
4419         r.out.needed = &needed;
4420
4421         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
4422
4423         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
4424                 "failed to call GetPrinterDriver");
4425         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4426                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4427                 data_blob_clear(&blob);
4428                 r.in.buffer = &blob;
4429                 r.in.offered = needed;
4430                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
4431                         "failed to call GetPrinterDriver");
4432         }
4433
4434         torture_assert_werr_ok(tctx, r.out.result,
4435                 "failed to call GetPrinterDriver");
4436
4437         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4438
4439         return true;
4440 }
4441
4442 static bool test_GetPrinterDriver2(struct torture_context *tctx,
4443                                    struct dcerpc_pipe *p,
4444                                    struct policy_handle *handle,
4445                                    const char *driver_name,
4446                                    const char *architecture)
4447 {
4448         struct spoolss_GetPrinterDriver2 r;
4449         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
4450         uint32_t needed;
4451         uint32_t server_major_version;
4452         uint32_t server_minor_version;
4453         int i;
4454
4455         r.in.handle = handle;
4456         r.in.architecture = architecture;
4457         r.in.client_major_version = 3;
4458         r.in.client_minor_version = 0;
4459         r.out.needed = &needed;
4460         r.out.server_major_version = &server_major_version;
4461         r.out.server_minor_version = &server_minor_version;
4462
4463         for (i=0;i<ARRAY_SIZE(levels);i++) {
4464
4465                 r.in.buffer = NULL;
4466                 r.in.offered = 0;
4467                 r.in.level = levels[i];
4468
4469                 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
4470                         driver_name, r.in.level);
4471
4472                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
4473                         "failed to call GetPrinterDriver2");
4474                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4475                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4476                         data_blob_clear(&blob);
4477                         r.in.buffer = &blob;
4478                         r.in.offered = needed;
4479                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
4480                                 "failed to call GetPrinterDriver2");
4481                 }
4482
4483                 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
4484                         switch (r.in.level) {
4485                         case 101:
4486                         case 8:
4487                                 continue;
4488                         default:
4489                                 break;
4490                         }
4491                 }
4492
4493                 torture_assert_werr_ok(tctx, r.out.result,
4494                         "failed to call GetPrinterDriver2");
4495
4496                 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4497         }
4498
4499         return true;
4500 }
4501
4502 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
4503                                         struct dcerpc_pipe *p,
4504                                         const char *environment)
4505 {
4506         struct spoolss_EnumPrinterDrivers r;
4507         NTSTATUS status;
4508         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
4509         int i;
4510
4511         for (i=0;i<ARRAY_SIZE(levels);i++) {
4512
4513                 uint32_t needed;
4514                 uint32_t count;
4515                 union spoolss_DriverInfo *info;
4516
4517                 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
4518                 r.in.environment = environment;
4519                 r.in.level = levels[i];
4520                 r.in.buffer = NULL;
4521                 r.in.offered = 0;
4522                 r.out.needed = &needed;
4523                 r.out.count = &count;
4524                 r.out.info = &info;
4525
4526                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
4527
4528                 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
4529
4530                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
4531
4532                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4533                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4534                         data_blob_clear(&blob);
4535                         r.in.buffer = &blob;
4536                         r.in.offered = needed;
4537                         status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
4538                 }
4539
4540                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
4541
4542                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
4543
4544                 if (!info) {
4545                         torture_comment(tctx, "No printer drivers returned\n");
4546                         break;
4547                 }
4548
4549                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4550         }
4551
4552         return true;
4553 }
4554
4555 static bool test_DeletePrinter(struct torture_context *tctx,
4556                                struct dcerpc_pipe *p,
4557                                struct policy_handle *handle)
4558 {
4559         struct spoolss_DeletePrinter r;
4560
4561         torture_comment(tctx, "Testing DeletePrinter\n");
4562
4563         r.in.handle = handle;
4564
4565         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter(p, tctx, &r),
4566                 "failed to delete printer");
4567         torture_assert_werr_ok(tctx, r.out.result,
4568                 "failed to delete printer");
4569
4570         return true;
4571 }
4572
4573 static bool test_EnumPrinters_findname(struct torture_context *tctx,
4574                                        struct dcerpc_pipe *p,
4575                                        uint32_t flags,
4576                                        uint32_t level,
4577                                        const char *name,
4578                                        bool *found)
4579 {
4580         struct spoolss_EnumPrinters e;
4581         uint32_t count;
4582         union spoolss_PrinterInfo *info;
4583         uint32_t needed;
4584         int i;
4585
4586         *found = false;
4587
4588         e.in.flags = flags;
4589         e.in.server = NULL;
4590         e.in.level = level;
4591         e.in.buffer = NULL;
4592         e.in.offered = 0;
4593         e.out.count = &count;
4594         e.out.info = &info;
4595         e.out.needed = &needed;
4596
4597         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
4598                 "failed to enum printers");
4599
4600         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
4601                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4602                 data_blob_clear(&blob);
4603                 e.in.buffer = &blob;
4604                 e.in.offered = needed;
4605
4606                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
4607                         "failed to enum printers");
4608         }
4609
4610         torture_assert_werr_ok(tctx, e.out.result,
4611                 "failed to enum printers");
4612
4613         for (i=0; i < count; i++) {
4614
4615                 const char *current = NULL;
4616                 const char *q;
4617
4618                 switch (level) {
4619                 case 1:
4620                         current = info[i].info1.name;
4621                         break;
4622                 }
4623
4624                 if (strequal(current, name)) {
4625                         *found = true;
4626                         break;
4627                 }
4628
4629                 q = strrchr(current, '\\');
4630                 if (q) {
4631                         if (!e.in.server) {
4632                                 torture_warning(tctx,
4633                                         "server returns printername %s incl. servername although we did not set servername", current);
4634                         }
4635                         q++;
4636                         if (strequal(q, name)) {
4637                                 *found = true;
4638                                 break;
4639                         }
4640                 }
4641         }
4642
4643         return true;
4644 }
4645
4646 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
4647                                       struct dcerpc_pipe *p,
4648                                       const char *printername,
4649                                       bool ex)
4650 {
4651         WERROR result;
4652         struct spoolss_AddPrinter r;
4653         struct spoolss_AddPrinterEx rex;
4654         struct spoolss_SetPrinterInfoCtr info_ctr;
4655         struct spoolss_SetPrinterInfo1 info1;
4656         struct spoolss_DevmodeContainer devmode_ctr;
4657         struct sec_desc_buf secdesc_ctr;
4658         struct spoolss_UserLevelCtr userlevel_ctr;
4659         struct policy_handle handle;
4660         bool found = false;
4661
4662         ZERO_STRUCT(devmode_ctr);
4663         ZERO_STRUCT(secdesc_ctr);
4664         ZERO_STRUCT(userlevel_ctr);
4665         ZERO_STRUCT(info1);
4666
4667         torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
4668
4669         /* try to add printer to wellknown printer list (level 1) */
4670
4671         userlevel_ctr.level = 1;
4672
4673         info_ctr.info.info1 = &info1;
4674         info_ctr.level = 1;
4675
4676         rex.in.server = NULL;
4677         rex.in.info_ctr = &info_ctr;
4678         rex.in.devmode_ctr = &devmode_ctr;
4679         rex.in.secdesc_ctr = &secdesc_ctr;
4680         rex.in.userlevel_ctr = &userlevel_ctr;
4681         rex.out.handle = &handle;
4682
4683         r.in.server = NULL;
4684         r.in.info_ctr = &info_ctr;
4685         r.in.devmode_ctr = &devmode_ctr;
4686         r.in.secdesc_ctr = &secdesc_ctr;
4687         r.out.handle = &handle;
4688
4689         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4690                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4691                 "failed to add printer");
4692         result = ex ? rex.out.result : r.out.result;
4693         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
4694                 "unexpected result code");
4695
4696         info1.name = printername;
4697         info1.flags = PRINTER_ATTRIBUTE_SHARED;
4698
4699         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4700                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4701                 "failed to add printer");
4702         result = ex ? rex.out.result : r.out.result;
4703         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4704                 "unexpected result code");
4705
4706         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
4707            better do a real check to see the printer is really there */
4708
4709         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4710                                                         PRINTER_ENUM_NETWORK, 1,
4711                                                         printername,
4712                                                         &found),
4713                         "failed to enum printers");
4714
4715         torture_assert(tctx, found, "failed to find newly added printer");
4716
4717         info1.flags = 0;
4718
4719         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4720                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4721                 "failed to add printer");
4722         result = ex ? rex.out.result : r.out.result;
4723         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4724                 "unexpected result code");
4725
4726         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
4727            better do a real check to see the printer has really been removed
4728            from the well known printer list */
4729
4730         found = false;
4731
4732         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4733                                                         PRINTER_ENUM_NETWORK, 1,
4734                                                         printername,
4735                                                         &found),
4736                         "failed to enum printers");
4737 #if 0
4738         torture_assert(tctx, !found, "printer still in well known printer list");
4739 #endif
4740         return true;
4741 }
4742
4743 static bool test_AddPrinter_normal(struct torture_context *tctx,
4744                                    struct dcerpc_pipe *p,
4745                                    struct policy_handle *handle_p,
4746                                    const char *printername,
4747                                    const char *drivername,
4748                                    const char *portname,
4749                                    bool ex)
4750 {
4751         WERROR result;
4752         struct spoolss_AddPrinter r;
4753         struct spoolss_AddPrinterEx rex;
4754         struct spoolss_SetPrinterInfoCtr info_ctr;
4755         struct spoolss_SetPrinterInfo2 info2;
4756         struct spoolss_DevmodeContainer devmode_ctr;
4757         struct sec_desc_buf secdesc_ctr;
4758         struct spoolss_UserLevelCtr userlevel_ctr;
4759         struct policy_handle handle;
4760         bool found = false;
4761         bool existing_printer_deleted = false;
4762
4763         ZERO_STRUCT(devmode_ctr);
4764         ZERO_STRUCT(secdesc_ctr);
4765         ZERO_STRUCT(userlevel_ctr);
4766
4767         torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
4768
4769         userlevel_ctr.level = 1;
4770
4771         rex.in.server = NULL;
4772         rex.in.info_ctr = &info_ctr;
4773         rex.in.devmode_ctr = &devmode_ctr;
4774         rex.in.secdesc_ctr = &secdesc_ctr;
4775         rex.in.userlevel_ctr = &userlevel_ctr;
4776         rex.out.handle = &handle;
4777
4778         r.in.server = NULL;
4779         r.in.info_ctr = &info_ctr;
4780         r.in.devmode_ctr = &devmode_ctr;
4781         r.in.secdesc_ctr = &secdesc_ctr;
4782         r.out.handle = &handle;
4783
4784  again:
4785
4786         /* try to add printer to printer list (level 2) */
4787
4788         ZERO_STRUCT(info2);
4789
4790         info_ctr.info.info2 = &info2;
4791         info_ctr.level = 2;
4792
4793         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4794                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4795                 "failed to add printer");
4796         result = ex ? rex.out.result : r.out.result;
4797         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
4798                 "unexpected result code");
4799
4800         info2.printername = printername;
4801
4802         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4803                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4804                 "failed to add printer");
4805         result = ex ? rex.out.result : r.out.result;
4806
4807         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
4808                 struct policy_handle printer_handle;
4809
4810                 if (existing_printer_deleted) {
4811                         torture_fail(tctx, "already deleted printer still existing?");
4812                 }
4813
4814                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
4815                         "failed to open printer handle");
4816
4817                 torture_assert(tctx, test_DeletePrinter(tctx, p, &printer_handle),
4818                         "failed to delete printer");
4819
4820                 torture_assert(tctx, test_ClosePrinter(tctx, p, &printer_handle),
4821                         "failed to close server handle");
4822
4823                 existing_printer_deleted = true;
4824
4825                 goto again;
4826         }
4827
4828         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
4829                 "unexpected result code");
4830
4831         info2.portname = portname;
4832
4833         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4834                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4835                 "failed to add printer");
4836         result = ex ? rex.out.result : r.out.result;
4837         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
4838                 "unexpected result code");
4839
4840         info2.drivername = drivername;
4841
4842         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4843                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4844                 "failed to add printer");
4845         result = ex ? rex.out.result : r.out.result;
4846
4847         /* w2k8r2 allows to add printer w/o defining printprocessor */
4848
4849         if (!W_ERROR_IS_OK(result)) {
4850                 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
4851                         "unexpected result code");
4852
4853                 info2.printprocessor = "winprint";
4854
4855                 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4856                                                       dcerpc_spoolss_AddPrinter(p, tctx, &r),
4857                         "failed to add printer");
4858                 result = ex ? rex.out.result : r.out.result;
4859                 torture_assert_werr_ok(tctx, result,
4860                         "failed to add printer");
4861         }
4862
4863         *handle_p = handle;
4864
4865         /* we are paranoid, really check if the printer is there now */
4866
4867         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4868                                                         PRINTER_ENUM_LOCAL, 1,
4869                                                         printername,
4870                                                         &found),
4871                         "failed to enum printers");
4872         torture_assert(tctx, found, "failed to find newly added printer");
4873
4874         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4875                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4876                 "failed to add printer");
4877         result = ex ? rex.out.result : r.out.result;
4878         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4879                 "unexpected result code");
4880
4881         return true;
4882 }
4883
4884 static bool test_AddPrinterEx(struct torture_context *tctx,
4885                               struct dcerpc_pipe *p,
4886                               struct policy_handle *handle_p,
4887                               const char *printername,
4888                               const char *drivername,
4889                               const char *portname)
4890 {
4891         bool ret = true;
4892
4893         if (!torture_setting_bool(tctx, "samba3", false)) {
4894                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
4895                         torture_comment(tctx, "failed to add printer to well known list\n");
4896                         ret = false;
4897                 }
4898         }
4899
4900         if (!test_AddPrinter_normal(tctx, p, handle_p,
4901                                     printername, drivername, portname,
4902                                     true)) {
4903                 torture_comment(tctx, "failed to add printer to printer list\n");
4904                 ret = false;
4905         }
4906
4907         return ret;
4908 }
4909
4910 static bool test_AddPrinter(struct torture_context *tctx,
4911                             struct dcerpc_pipe *p,
4912                             struct policy_handle *handle_p,
4913                             const char *printername,
4914                             const char *drivername,
4915                             const char *portname)
4916 {
4917         bool ret = true;
4918
4919         if (!torture_setting_bool(tctx, "samba3", false)) {
4920                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
4921                         torture_comment(tctx, "failed to add printer to well known list\n");
4922                         ret = false;
4923                 }
4924         }
4925
4926         if (!test_AddPrinter_normal(tctx, p, handle_p,
4927                                     printername, drivername, portname,
4928                                     false)) {
4929                 torture_comment(tctx, "failed to add printer to printer list\n");
4930                 ret = false;
4931         }
4932
4933         return ret;
4934 }
4935
4936 static bool test_printer_info(struct torture_context *tctx,
4937                               struct dcerpc_pipe *p,
4938                               struct policy_handle *handle)
4939 {
4940         bool ret = true;
4941
4942         if (torture_setting_bool(tctx, "samba3", false)) {
4943                 torture_skip(tctx, "skipping printer info cross tests against samba 3");
4944         }
4945
4946         if (!test_PrinterInfo(tctx, p, handle)) {
4947                 ret = false;
4948         }
4949
4950         if (!test_SetPrinter_errors(tctx, p, handle)) {
4951                 ret = false;
4952         }
4953
4954         return ret;
4955 }
4956
4957 static bool test_EnumPrinterKey(struct torture_context *tctx,
4958                                 struct dcerpc_pipe *p,
4959                                 struct policy_handle *handle,
4960                                 const char *key_name,
4961                                 const char ***array)
4962 {
4963         struct spoolss_EnumPrinterKey r;
4964         uint32_t needed = 0;
4965         union spoolss_KeyNames key_buffer;
4966         int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
4967         uint32_t _ndr_size;
4968         int i;
4969
4970         r.in.handle = handle;
4971         r.in.key_name = key_name;
4972         r.out.key_buffer = &key_buffer;
4973         r.out.needed = &needed;
4974         r.out._ndr_size = &_ndr_size;
4975
4976         for (i=0; i < ARRAY_SIZE(offered); i++) {
4977
4978                 if (offered[i] < 0 && needed) {
4979                         if (needed <= 4) {
4980                                 continue;
4981                         }
4982                         r.in.offered = needed + offered[i];
4983                 } else {
4984                         r.in.offered = offered[i];
4985                 }
4986
4987                 ZERO_STRUCT(key_buffer);
4988
4989                 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
4990
4991                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
4992                         "failed to call EnumPrinterKey");
4993                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4994
4995                         torture_assert(tctx, (_ndr_size == r.in.offered/2),
4996                                 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
4997                                         _ndr_size, r.in.offered/2));
4998
4999                         r.in.offered = needed;
5000                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
5001                                 "failed to call EnumPrinterKey");
5002                 }
5003
5004                 if (offered[i] > 0) {
5005                         torture_assert_werr_ok(tctx, r.out.result,
5006                                 "failed to call EnumPrinterKey");
5007                 }
5008
5009                 torture_assert(tctx, (_ndr_size == r.in.offered/2),
5010                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
5011                                 _ndr_size, r.in.offered/2));
5012
5013                 torture_assert(tctx, (*r.out.needed <= r.in.offered),
5014                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
5015
5016                 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
5017                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
5018
5019                 if (key_buffer.string_array) {
5020                         uint32_t calc_needed = 0;
5021                         int s;
5022                         for (s=0; key_buffer.string_array[s]; s++) {
5023                                 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
5024                         }
5025                         if (!key_buffer.string_array[0]) {
5026                                 calc_needed += 2;
5027                         }
5028                         calc_needed += 2;
5029
5030                         torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
5031                                 "EnumPrinterKey unexpected size");
5032                 }
5033         }
5034
5035         if (array) {
5036                 *array = key_buffer.string_array;
5037         }
5038
5039         return true;
5040 }
5041
5042 bool test_printer_keys(struct torture_context *tctx,
5043                        struct dcerpc_pipe *p,
5044                        struct policy_handle *handle)
5045 {
5046         const char **key_array = NULL;
5047         int i;
5048
5049         torture_comment(tctx, "\nTesting Printer Keys\n");
5050
5051         torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, "", &key_array),
5052                 "failed to call test_EnumPrinterKey");
5053
5054         for (i=0; key_array && key_array[i]; i++) {
5055                 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, key_array[i], NULL),
5056                         "failed to call test_EnumPrinterKey");
5057         }
5058         for (i=0; key_array && key_array[i]; i++) {
5059                 torture_assert(tctx, test_EnumPrinterDataEx(tctx, p, handle, key_array[i], NULL, NULL),
5060                         "failed to call test_EnumPrinterDataEx");
5061         }
5062
5063         return true;
5064 }
5065
5066 static bool test_one_printer(struct torture_context *tctx,
5067                              struct dcerpc_pipe *p,
5068                              struct policy_handle *handle,
5069                              const char *name)
5070 {
5071         bool ret = true;
5072
5073         if (!test_printer_info(tctx, p, handle)) {
5074                 ret = false;
5075         }
5076
5077         if (!test_PrinterInfo_SD(tctx, p, handle)) {
5078                 ret = false;
5079         }
5080
5081         if (!test_PrinterInfo_DevMode(tctx, p, handle, name)) {
5082                 ret = false;
5083         }
5084
5085         if (!test_ChangeID(tctx, p, handle)) {
5086                 ret = false;
5087         }
5088
5089         if (!test_printer_keys(tctx, p, handle)) {
5090                 ret = false;
5091         }
5092
5093         if (!test_EnumPrinterData_consistency(tctx, p, handle)) {
5094                 ret = false;
5095         }
5096
5097         if (!test_SetPrinterDataEx_matrix(tctx, p, handle, name, NULL, NULL)) {
5098                 ret = false;
5099         }
5100
5101         if (!test_PrinterData_winreg(tctx, p, handle, name)) {
5102                 ret = false;
5103         }
5104
5105         if (!test_printer_rename(tctx, p, handle, name)) {
5106                 ret = false;
5107         }
5108
5109         return ret;
5110 }
5111
5112 static bool test_printer(struct torture_context *tctx,
5113                          struct dcerpc_pipe *p)
5114 {
5115         bool ret = true;
5116         struct policy_handle handle[2];
5117         bool found = false;
5118         const char *drivername = "Microsoft XPS Document Writer";
5119         const char *portname = "LPT1:";
5120
5121         /* test printer created via AddPrinter */
5122
5123         if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
5124                 return false;
5125         }
5126
5127         if (!test_one_printer(tctx, p, &handle[0], TORTURE_PRINTER)) {
5128                 ret = false;
5129         }
5130
5131         if (!test_DeletePrinter(tctx, p, &handle[0])) {
5132                 ret = false;
5133         }
5134
5135         if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
5136                                         TORTURE_PRINTER, &found)) {
5137                 ret = false;
5138         }
5139
5140         torture_assert(tctx, !found, "deleted printer still there");
5141
5142         /* test printer created via AddPrinterEx */
5143
5144         if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
5145                 return false;
5146         }
5147
5148         if (!test_one_printer(tctx, p, &handle[1], TORTURE_PRINTER_EX)) {
5149                 ret = false;
5150         }
5151
5152         if (!test_DeletePrinter(tctx, p, &handle[1])) {
5153                 ret = false;
5154         }
5155
5156         if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
5157                                         TORTURE_PRINTER_EX, &found)) {
5158                 ret = false;
5159         }
5160
5161         torture_assert(tctx, !found, "deleted printer still there");
5162
5163         return ret;
5164 }
5165
5166 static bool test_architecture_buffer(struct torture_context *tctx,
5167                                      struct dcerpc_pipe *p)
5168 {
5169         struct spoolss_OpenPrinterEx r;
5170         struct spoolss_UserLevel1 u1;
5171         struct policy_handle handle;
5172         uint32_t architectures[] = {
5173                 PROCESSOR_ARCHITECTURE_INTEL,
5174                 PROCESSOR_ARCHITECTURE_IA64,
5175                 PROCESSOR_ARCHITECTURE_AMD64
5176         };
5177         uint32_t needed[3];
5178         int i;
5179
5180         for (i=0; i < ARRAY_SIZE(architectures); i++) {
5181
5182                 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
5183
5184                 u1.size = 0;
5185                 u1.client = NULL;
5186                 u1.user = NULL;
5187                 u1.build = 0;
5188                 u1.major = 3;
5189                 u1.minor = 0;
5190                 u1.processor = architectures[i];
5191
5192                 r.in.printername        = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
5193                 r.in.datatype           = NULL;
5194                 r.in.devmode_ctr.devmode= NULL;
5195                 r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
5196                 r.in.level               = 1;
5197                 r.in.userlevel.level1   = &u1;
5198                 r.out.handle            = &handle;
5199
5200                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx(p, tctx, &r), "");
5201                 torture_assert_werr_ok(tctx, r.out.result, "");
5202
5203                 {
5204                         struct spoolss_EnumPrinters e;
5205                         uint32_t count;
5206                         union spoolss_PrinterInfo *info;
5207
5208                         e.in.flags = PRINTER_ENUM_LOCAL;
5209                         e.in.server = NULL;
5210                         e.in.level = 2;
5211                         e.in.buffer = NULL;
5212                         e.in.offered = 0;
5213                         e.out.count = &count;
5214                         e.out.info = &info;
5215                         e.out.needed = &needed[i];
5216
5217                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e), "");
5218 #if 0
5219                         torture_comment(tctx, "needed was %d\n", needed[i]);
5220 #endif
5221                 }
5222
5223                 torture_assert(tctx, test_ClosePrinter(tctx, p, &handle), "");
5224         }
5225
5226         for (i=1; i < ARRAY_SIZE(architectures); i++) {
5227                 if (needed[i-1] != needed[i]) {
5228                         torture_fail(tctx,
5229                                 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
5230                                                 needed[i-1], architectures[i-1], needed[i], architectures[i]));
5231                 }
5232         }
5233
5234         return true;
5235 }
5236
5237 bool torture_rpc_spoolss(struct torture_context *torture)
5238 {
5239         NTSTATUS status;
5240         struct dcerpc_pipe *p;
5241         bool ret = true;
5242         struct test_spoolss_context *ctx;
5243         const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
5244
5245         status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
5246         if (!NT_STATUS_IS_OK(status)) {
5247                 return false;
5248         }
5249
5250         ctx = talloc_zero(torture, struct test_spoolss_context);
5251
5252         ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
5253         ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle, &environment);
5254         ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
5255         ret &= test_AddForm(torture, p, &ctx->server_handle, true);
5256         ret &= test_EnumPorts(torture, p, ctx);
5257         ret &= test_GetPrinterDriverDirectory(torture, p, ctx, environment);
5258         ret &= test_GetPrintProcessorDirectory(torture, p, ctx, environment);
5259         ret &= test_EnumPrinterDrivers(torture, p, ctx, environment);
5260         ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
5261         ret &= test_EnumMonitors(torture, p, ctx);
5262         ret &= test_EnumPrintProcessors(torture, p, ctx, environment);
5263         ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
5264         ret &= test_EnumPrinters(torture, p, ctx);
5265         ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
5266         ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
5267         ret &= test_OpenPrinter_badname(torture, p, "");
5268         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
5269         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
5270         ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
5271         ret &= test_OpenPrinter_badname(torture, p,
5272                                         talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
5273
5274
5275         ret &= test_AddPort(torture, p);
5276         ret &= test_EnumPorts_old(torture, p);
5277         ret &= test_EnumPrinters_old(torture, p, environment);
5278         ret &= test_EnumPrinterDrivers_old(torture, p, environment);
5279         ret &= test_architecture_buffer(torture, p);
5280
5281         return ret;
5282 }
5283
5284 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
5285 {
5286         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
5287
5288         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
5289                                                         "printer", &ndr_table_spoolss);
5290
5291         torture_rpc_tcase_add_test(tcase, "printer", test_printer);
5292
5293         return suite;
5294 }