3b13426c8a7e4f401ca278e164b1427b280a7dfb
[sfrench/samba-autobuild/.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, "Testing 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\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, "Testing 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\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         torture_comment(tctx, "Testing EnumPrinterData\n");
3082
3083         do {
3084                 torture_assert(tctx,
3085                         test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3086                                              &type, &value_needed, &data_needed,
3087                                              &value_name, &data, &result),
3088                         "EnumPrinterData failed");
3089
3090                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3091                         break;
3092                 }
3093
3094                 torture_assert(tctx,
3095                         test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3096                                              &type, &value_needed, &data_needed,
3097                                              &value_name, &data, &result),
3098                         "EnumPrinterData failed");
3099
3100                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3101                         break;
3102                 }
3103
3104                 enum_index++;
3105
3106         } while (W_ERROR_IS_OK(result));
3107
3108         torture_comment(tctx, "EnumPrinterData test succeeded\n");
3109
3110         return true;
3111 }
3112
3113 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3114                                    struct dcerpc_pipe *p,
3115                                    struct policy_handle *handle,
3116                                    const char *key_name,
3117                                    uint32_t *count_p,
3118                                    struct spoolss_PrinterEnumValues **info_p)
3119 {
3120         struct spoolss_EnumPrinterDataEx r;
3121         struct spoolss_PrinterEnumValues *info;
3122         uint32_t needed;
3123         uint32_t count;
3124
3125         r.in.handle = handle;
3126         r.in.key_name = key_name;
3127         r.in.offered = 0;
3128         r.out.needed = &needed;
3129         r.out.count = &count;
3130         r.out.info = &info;
3131
3132         torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3133
3134         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
3135                 "EnumPrinterDataEx failed");
3136         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3137                 r.in.offered = needed;
3138                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
3139                         "EnumPrinterDataEx failed");
3140         }
3141
3142         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3143
3144         CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3145
3146         if (count_p) {
3147                 *count_p = count;
3148         }
3149         if (info_p) {
3150                 *info_p = info;
3151         }
3152
3153         return true;
3154 }
3155
3156 static bool test_SetPrinterData(struct torture_context *tctx,
3157                                 struct dcerpc_pipe *p,
3158                                 struct policy_handle *handle,
3159                                 const char *value_name,
3160                                 enum winreg_Type type,
3161                                 uint8_t *data,
3162                                 uint32_t offered);
3163 static bool test_DeletePrinterData(struct torture_context *tctx,
3164                                    struct dcerpc_pipe *p,
3165                                    struct policy_handle *handle,
3166                                    const char *value_name);
3167
3168 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3169                                              struct dcerpc_pipe *p,
3170                                              struct policy_handle *handle)
3171 {
3172         uint32_t count;
3173         struct spoolss_PrinterEnumValues *info;
3174         int i;
3175         uint32_t value_needed, data_needed;
3176         uint32_t value_offered, data_offered;
3177         WERROR result;
3178
3179         enum winreg_Type type;
3180         DATA_BLOB blob;
3181
3182         torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3183
3184         torture_assert(tctx,
3185                 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3186                                   "REG_SZ", "torture_data1", &type, &blob), "");
3187
3188         torture_assert(tctx,
3189                 test_SetPrinterData(tctx, p, handle, "torture_value1", type, blob.data, blob.length),
3190                 "SetPrinterData failed");
3191
3192         blob = data_blob_string_const("torture_data2");
3193
3194         torture_assert(tctx,
3195                 test_SetPrinterData(tctx, p, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3196                 "SetPrinterData failed");
3197
3198         blob = data_blob_talloc(tctx, NULL, 4);
3199         SIVAL(blob.data, 0, 0x11223344);
3200
3201         torture_assert(tctx,
3202                 test_SetPrinterData(tctx, p, handle, "torture_value3", type, blob.data, blob.length),
3203                 "SetPrinterData failed");
3204
3205         torture_assert(tctx,
3206                 test_EnumPrinterDataEx(tctx, p, handle, "PrinterDriverData", &count, &info),
3207                 "failed to call EnumPrinterDataEx");
3208
3209         /* get the max sizes for value and data */
3210
3211         torture_assert(tctx,
3212                 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3213                                      NULL, &value_needed, &data_needed,
3214                                      NULL, NULL, &result),
3215                 "EnumPrinterData failed");
3216         torture_assert_werr_ok(tctx, result, "unexpected result");
3217
3218         /* check if the reply from the EnumPrinterData really matches max values */
3219
3220         for (i=0; i < count; i++) {
3221                 if (info[i].value_name_len > value_needed) {
3222                         torture_fail(tctx,
3223                                 talloc_asprintf(tctx,
3224                                 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3225                                 info[i].value_name_len, value_needed));
3226                 }
3227                 if (info[i].data_length > data_needed) {
3228                         torture_fail(tctx,
3229                                 talloc_asprintf(tctx,
3230                                 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3231                                 info[i].data_length, data_needed));
3232                 }
3233         }
3234
3235         /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3236          * sort or not sort the replies by value name, we should be able to do
3237          * the following entry comparison */
3238
3239         data_offered = data_needed;
3240         value_offered = value_needed;
3241
3242         for (i=0; i < count; i++) {
3243
3244                 const char *value_name;
3245                 uint8_t *data;
3246
3247                 torture_assert(tctx,
3248                         test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3249                                              &type, &value_needed, &data_needed,
3250                                              &value_name, &data, &result),
3251                         "EnumPrinterData failed");
3252
3253                 if (i -1 == count) {
3254                         torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3255                                 "unexpected result");
3256                         break;
3257                 } else {
3258                         torture_assert_werr_ok(tctx, result, "unexpected result");
3259                 }
3260
3261                 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3262                 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3263                 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
3264                 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
3265                 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
3266         }
3267
3268         torture_assert(tctx,
3269                 test_DeletePrinterData(tctx, p, handle, "torture_value1"),
3270                 "DeletePrinterData failed");
3271         torture_assert(tctx,
3272                 test_DeletePrinterData(tctx, p, handle, "torture_value2"),
3273                 "DeletePrinterData failed");
3274         torture_assert(tctx,
3275                 test_DeletePrinterData(tctx, p, handle, "torture_value3"),
3276                 "DeletePrinterData failed");
3277
3278         torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
3279
3280         return true;
3281 }
3282
3283 static bool test_DeletePrinterData(struct torture_context *tctx,
3284                                    struct dcerpc_pipe *p,
3285                                    struct policy_handle *handle,
3286                                    const char *value_name)
3287 {
3288         NTSTATUS status;
3289         struct spoolss_DeletePrinterData r;
3290
3291         r.in.handle = handle;
3292         r.in.value_name = value_name;
3293
3294         torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
3295                 r.in.value_name);
3296
3297         status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
3298
3299         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
3300         torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
3301
3302         return true;
3303 }
3304
3305 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
3306                                      struct dcerpc_pipe *p,
3307                                      struct policy_handle *handle,
3308                                      const char *key_name,
3309                                      const char *value_name)
3310 {
3311         struct spoolss_DeletePrinterDataEx r;
3312
3313         r.in.handle = handle;
3314         r.in.key_name = key_name;
3315         r.in.value_name = value_name;
3316
3317         torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
3318                 r.in.key_name, r.in.value_name);
3319
3320         torture_assert_ntstatus_ok(tctx,
3321                 dcerpc_spoolss_DeletePrinterDataEx(p, tctx, &r),
3322                 "DeletePrinterDataEx failed");
3323         torture_assert_werr_ok(tctx, r.out.result,
3324                 "DeletePrinterDataEx failed");
3325
3326         return true;
3327 }
3328
3329 static bool test_DeletePrinterKey(struct torture_context *tctx,
3330                                   struct dcerpc_pipe *p,
3331                                   struct policy_handle *handle,
3332                                   const char *key_name)
3333 {
3334         struct spoolss_DeletePrinterKey r;
3335
3336         r.in.handle = handle;
3337         r.in.key_name = key_name;
3338
3339         torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
3340
3341         if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
3342                 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
3343                 return true;
3344         }
3345
3346         torture_assert_ntstatus_ok(tctx,
3347                 dcerpc_spoolss_DeletePrinterKey(p, tctx, &r),
3348                 "DeletePrinterKey failed");
3349         torture_assert_werr_ok(tctx, r.out.result,
3350                 "DeletePrinterKey failed");
3351
3352         return true;
3353 }
3354
3355 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
3356                                  struct dcerpc_pipe *p,
3357                                  struct policy_handle *handle)
3358 {
3359         struct winreg_OpenHKLM r;
3360
3361         r.in.system_name = NULL;
3362         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3363         r.out.handle = handle;
3364
3365         torture_comment(tctx, "Testing winreg_OpenHKLM\n");
3366
3367         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM(p, tctx, &r), "OpenHKLM failed");
3368         torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
3369
3370         return true;
3371 }
3372
3373 static void init_winreg_String(struct winreg_String *name, const char *s)
3374 {
3375         name->name = s;
3376         if (s) {
3377                 name->name_len = 2 * (strlen_m(s) + 1);
3378                 name->name_size = name->name_len;
3379         } else {
3380                 name->name_len = 0;
3381                 name->name_size = 0;
3382         }
3383 }
3384
3385 static bool test_winreg_OpenKey(struct torture_context *tctx,
3386                                 struct dcerpc_pipe *p,
3387                                 struct policy_handle *hive_handle,
3388                                 const char *keyname,
3389                                 struct policy_handle *key_handle)
3390 {
3391         struct winreg_OpenKey r;
3392
3393         r.in.parent_handle = hive_handle;
3394         init_winreg_String(&r.in.keyname, keyname);
3395         r.in.options = REG_KEYTYPE_NON_VOLATILE;
3396         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3397         r.out.handle = key_handle;
3398
3399         torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
3400
3401         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey(p, tctx, &r), "OpenKey failed");
3402         torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
3403
3404         return true;
3405 }
3406
3407 static bool test_winreg_CloseKey(struct torture_context *tctx,
3408                                  struct dcerpc_pipe *p,
3409                                  struct policy_handle *handle)
3410 {
3411         struct winreg_CloseKey r;
3412
3413         r.in.handle = handle;
3414         r.out.handle = handle;
3415
3416         torture_comment(tctx, "Testing winreg_CloseKey\n");
3417
3418         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey(p, tctx, &r), "CloseKey failed");
3419         torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
3420
3421         return true;
3422 }
3423
3424 bool test_winreg_QueryValue(struct torture_context *tctx,
3425                             struct dcerpc_pipe *p,
3426                             struct policy_handle *handle,
3427                             const char *value_name,
3428                             enum winreg_Type *type_p,
3429                             uint32_t *data_size_p,
3430                             uint32_t *data_length_p,
3431                             uint8_t **data_p)
3432 {
3433         struct winreg_QueryValue r;
3434         enum winreg_Type type = REG_NONE;
3435         uint32_t data_size = 0;
3436         uint32_t data_length = 0;
3437         struct winreg_String valuename;
3438         uint8_t *data = NULL;
3439
3440         init_winreg_String(&valuename, value_name);
3441
3442         data = talloc_zero_array(tctx, uint8_t, 0);
3443
3444         r.in.handle = handle;
3445         r.in.value_name = &valuename;
3446         r.in.type = &type;
3447         r.in.data_size = &data_size;
3448         r.in.data_length = &data_length;
3449         r.in.data = data;
3450         r.out.type = &type;
3451         r.out.data = data;
3452         r.out.data_size = &data_size;
3453         r.out.data_length = &data_length;
3454
3455         torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
3456
3457         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue(p, tctx, &r), "QueryValue failed");
3458         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3459                 *r.in.data_size = *r.out.data_size;
3460                 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
3461                 r.in.data = data;
3462                 r.out.data = data;
3463                 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue(p, tctx, &r), "QueryValue failed");
3464         }
3465         torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
3466
3467         if (type_p) {
3468                 *type_p = *r.out.type;
3469         }
3470         if (data_size_p) {
3471                 *data_size_p = *r.out.data_size;
3472         }
3473         if (data_length_p) {
3474                 *data_length_p = *r.out.data_length;
3475         }
3476         if (data_p) {
3477                 *data_p = r.out.data;
3478         }
3479
3480         return true;
3481 }
3482
3483 static bool test_winreg_query_printerdata(struct torture_context *tctx,
3484                                           struct dcerpc_pipe *p,
3485                                           struct policy_handle *handle,
3486                                           const char *printer_name,
3487                                           const char *key_name,
3488                                           const char *value_name,
3489                                           enum winreg_Type *w_type,
3490                                           uint32_t *w_size,
3491                                           uint32_t *w_length,
3492                                           uint8_t **w_data)
3493 {
3494         const char *printer_key;
3495         struct policy_handle key_handle;
3496
3497         printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
3498                 TOP_LEVEL_PRINTER_KEY, printer_name, key_name);
3499
3500         torture_assert(tctx,
3501                 test_winreg_OpenKey(tctx, p, handle, printer_key, &key_handle), "");
3502
3503         torture_assert(tctx,
3504                 test_winreg_QueryValue(tctx, p, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
3505
3506         torture_assert(tctx,
3507                 test_winreg_CloseKey(tctx, p, &key_handle), "");
3508
3509         return true;
3510 }
3511
3512 static bool test_SetPrinterData(struct torture_context *tctx,
3513                                 struct dcerpc_pipe *p,
3514                                 struct policy_handle *handle,
3515                                 const char *value_name,
3516                                 enum winreg_Type type,
3517                                 uint8_t *data,
3518                                 uint32_t offered)
3519 {
3520         struct spoolss_SetPrinterData r;
3521
3522         r.in.handle = handle;
3523         r.in.value_name = value_name;
3524         r.in.type = type;
3525         r.in.data = data;
3526         r.in.offered = offered;
3527
3528         torture_comment(tctx, "Testing SetPrinterData(%s)\n",
3529                 r.in.value_name);
3530
3531         torture_assert_ntstatus_ok(tctx,
3532                 dcerpc_spoolss_SetPrinterData(p, tctx, &r),
3533                 "SetPrinterData failed");
3534         torture_assert_werr_ok(tctx, r.out.result,
3535                 "SetPrinterData failed");
3536
3537         return true;
3538 }
3539
3540 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
3541                                        struct dcerpc_pipe *p,
3542                                        struct policy_handle *handle,
3543                                        const char *printer_name,
3544                                        struct dcerpc_pipe *winreg_pipe,
3545                                        struct policy_handle *hive_handle)
3546 {
3547         const char *values[] = {
3548                 "spootyfoot",
3549                 "spooty\\foot",
3550 #if 0
3551         /* FIXME: not working with s3 atm. */
3552                 "spooty,foot",
3553                 "spooty,fo,ot",
3554 #endif
3555                 "spooty foot",
3556 #if 0
3557         /* FIXME: not working with s3 atm. */
3558                 "spooty\\fo,ot",
3559                 "spooty,fo\\ot"
3560 #endif
3561         };
3562         int i;
3563
3564         for (i=0; i < ARRAY_SIZE(values); i++) {
3565
3566                 enum winreg_Type type;
3567                 DATA_BLOB blob;
3568                 uint8_t *data;
3569                 uint32_t needed;
3570
3571                 torture_assert(tctx,
3572                         reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3573                                           "REG_SZ", "dog", &type, &blob), "");
3574
3575                 torture_assert(tctx,
3576                         test_SetPrinterData(tctx, p, handle, values[i], REG_SZ, blob.data, blob.length),
3577                         "SetPrinterData failed");
3578
3579                 torture_assert(tctx,
3580                         test_GetPrinterData(tctx, p, handle, values[i], &type, &data, &needed),
3581                         "GetPrinterData failed");
3582
3583                 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
3584                 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
3585                 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
3586
3587                 if (winreg_pipe && hive_handle) {
3588
3589                         enum winreg_Type w_type;
3590                         uint32_t w_size;
3591                         uint32_t w_length;
3592                         uint8_t *w_data;
3593
3594                         torture_assert(tctx,
3595                                 test_winreg_query_printerdata(tctx, winreg_pipe, hive_handle,
3596                                         printer_name, "PrinterDriverData", values[i],
3597                                         &w_type, &w_size, &w_length, &w_data), "");
3598
3599                         torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
3600                         torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
3601                         torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
3602                         torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
3603                 }
3604
3605                 torture_assert(tctx,
3606                         test_DeletePrinterData(tctx, p, handle, values[i]),
3607                         "DeletePrinterData failed");
3608         }
3609
3610         return true;
3611 }
3612
3613
3614 static bool test_EnumPrinterKey(struct torture_context *tctx,
3615                                 struct dcerpc_pipe *p,
3616                                 struct policy_handle *handle,
3617                                 const char *key_name,
3618                                 const char ***array);
3619
3620 static bool test_SetPrinterDataEx(struct torture_context *tctx,
3621                                   struct dcerpc_pipe *p,
3622                                   struct policy_handle *handle,
3623                                   const char *key_name,
3624                                   const char *value_name,
3625                                   enum winreg_Type type,
3626                                   uint8_t *data,
3627                                   uint32_t offered)
3628 {
3629         NTSTATUS status;
3630         struct spoolss_SetPrinterDataEx r;
3631
3632         r.in.handle = handle;
3633         r.in.key_name = key_name;
3634         r.in.value_name = value_name;
3635         r.in.type = type;
3636         r.in.data = data;
3637         r.in.offered = offered;
3638
3639         torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
3640                 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
3641
3642         status = dcerpc_spoolss_SetPrinterDataEx(p, tctx, &r);
3643
3644         torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
3645         torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
3646
3647         return true;
3648 }
3649
3650 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
3651                                          struct dcerpc_pipe *p,
3652                                          struct policy_handle *handle,
3653                                          const char *printername,
3654                                          struct dcerpc_pipe *winreg_pipe,
3655                                          struct policy_handle *hive_handle)
3656 {
3657         const char *value_name = "dog";
3658         const char *keys[] = {
3659                 "torturedataex",
3660                 "torture data ex",
3661 #if 0
3662         /* FIXME: not working with s3 atm. */
3663                 "torturedataex_with_subkey\\subkey",
3664                 "torturedataex_with_subkey\\subkey:0",
3665                 "torturedataex_with_subkey\\subkey:1",
3666                 "torturedataex_with_subkey\\subkey\\subsubkey",
3667                 "torturedataex_with_subkey\\subkey\\subsubkey:0",
3668                 "torturedataex_with_subkey\\subkey\\subsubkey:1",
3669 #endif
3670                 "torture,data",
3671 #if 0
3672         /* FIXME: not working with s3 atm. */
3673
3674                 "torture,data,ex",
3675                 "torture,data\\ex",
3676                 "torture\\data,ex"
3677 #endif
3678         };
3679         enum winreg_Type types[] = {
3680                 REG_SZ,
3681                 REG_DWORD,
3682                 REG_BINARY
3683         };
3684         const char *str = "abcdefghijklmnopqrstuvwxzy";
3685         int i, t, s;
3686
3687
3688         for (i=0; i < ARRAY_SIZE(keys); i++) {
3689         for (t=0; t < ARRAY_SIZE(types); t++) {
3690         for (s=0; s < strlen(str); s++) {
3691
3692                 char *c;
3693                 const char *key;
3694                 enum winreg_Type type;
3695                 const char *string = talloc_strndup(tctx, str, s);
3696                 DATA_BLOB blob = data_blob_string_const(string);
3697                 const char **subkeys;
3698                 DATA_BLOB data;
3699                 uint8_t *data_out;
3700                 uint32_t needed, offered = 0;
3701                 uint32_t ecount;
3702                 struct spoolss_PrinterEnumValues *einfo;
3703
3704                 switch (types[t]) {
3705                 case REG_BINARY:
3706                 case REG_DWORD:
3707                         data = blob;
3708                         offered = blob.length;
3709                         break;
3710                 case REG_SZ:
3711                         torture_assert(tctx,
3712                                 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3713                                                   "REG_SZ", string, &type, &data), "");
3714                         offered = data.length;
3715                         /*strlen_m_term(data.string)*2;*/
3716                         break;
3717                 default:
3718                         torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
3719                 }
3720
3721                 torture_assert(tctx,
3722                         test_SetPrinterDataEx(tctx, p, handle, keys[i], value_name, types[t], data.data, offered),
3723                         "failed to call SetPrinterDataEx");
3724
3725                 torture_assert(tctx,
3726                         test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &data_out, &needed),
3727                         "failed to call GetPrinterDataEx");
3728
3729                 torture_assert(tctx,
3730                         test_EnumPrinterDataEx(tctx, p, handle, keys[i], &ecount, &einfo),
3731                         "failed to call EnumPrinterDataEx");
3732
3733                 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
3734                 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
3735                 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
3736
3737                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
3738                 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
3739                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
3740                 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
3741                 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
3742                 if (einfo[0].data_length > 0) {
3743                         torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
3744                 }
3745
3746                 if (winreg_pipe && hive_handle) {
3747
3748                         enum winreg_Type w_type;
3749                         uint32_t w_size;
3750                         uint32_t w_length;
3751                         uint8_t *w_data;
3752
3753                         torture_assert(tctx,
3754                                 test_winreg_query_printerdata(tctx, winreg_pipe, hive_handle,
3755                                         printername, keys[i], value_name,
3756                                         &w_type, &w_size, &w_length, &w_data), "");
3757
3758                         torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
3759                         torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
3760                         torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
3761                         torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
3762                 }
3763
3764                 key = talloc_strdup(tctx, keys[i]);
3765
3766                 if (!test_DeletePrinterDataEx(tctx, p, handle, keys[i], value_name)) {
3767                         return false;
3768                 }
3769
3770                 c = strchr(key, '\\');
3771                 if (c) {
3772                         int k;
3773
3774                         /* we have subkeys */
3775
3776                         *c = 0;
3777
3778                         if (!test_EnumPrinterKey(tctx, p, handle, key, &subkeys)) {
3779                                 return false;
3780                         }
3781
3782                         for (k=0; subkeys && subkeys[k]; k++) {
3783
3784                                 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
3785
3786                                 if (!test_DeletePrinterKey(tctx, p, handle, current_key)) {
3787                                         return false;
3788                                 }
3789                         }
3790
3791                         if (!test_DeletePrinterKey(tctx, p, handle, key)) {
3792                                 return false;
3793                         }
3794
3795                 } else {
3796                         if (!test_DeletePrinterKey(tctx, p, handle, key)) {
3797                                 return false;
3798                         }
3799                 }
3800         }
3801         }
3802         }
3803
3804         return true;
3805 }
3806
3807 static bool test_PrinterData_winreg(struct torture_context *tctx,
3808                                     struct dcerpc_pipe *p,
3809                                     struct policy_handle *handle,
3810                                     const char *printer_name)
3811 {
3812         struct dcerpc_pipe *p2;
3813         bool ret = true;
3814         struct policy_handle hive_handle;
3815
3816         torture_assert_ntstatus_ok(tctx,
3817                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
3818                 "could not open winreg pipe");
3819
3820         torture_assert(tctx, test_winreg_OpenHKLM(tctx, p2, &hive_handle), "");
3821
3822         ret &= test_SetPrinterData_matrix(tctx, p, handle, printer_name, p2, &hive_handle);
3823         ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, p2, &hive_handle);
3824
3825         test_winreg_CloseKey(tctx, p2, &hive_handle);
3826
3827         talloc_free(p2);
3828
3829         return ret;
3830 }
3831
3832 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
3833                                          struct dcerpc_pipe *p,
3834                                          struct policy_handle *handle,
3835                                          uint32_t *change_id)
3836 {
3837         enum winreg_Type type;
3838         uint8_t *data;
3839         uint32_t needed;
3840
3841         torture_assert(tctx,
3842                 test_GetPrinterData(tctx, p, handle, "ChangeID", &type, &data, &needed),
3843                 "failed to call GetPrinterData");
3844
3845         torture_assert(tctx, type == REG_DWORD, "unexpected type");
3846         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
3847
3848         *change_id = IVAL(data, 0);
3849
3850         return true;
3851 }
3852
3853 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
3854                                            struct dcerpc_pipe *p,
3855                                            struct policy_handle *handle,
3856                                            uint32_t *change_id)
3857 {
3858         enum winreg_Type type;
3859         uint8_t *data;
3860         uint32_t needed;
3861
3862         torture_assert(tctx,
3863                 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
3864                 "failed to call GetPrinterData");
3865
3866         torture_assert(tctx, type == REG_DWORD, "unexpected type");
3867         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
3868
3869         *change_id = IVAL(data, 0);
3870
3871         return true;
3872 }
3873
3874 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
3875                                          struct dcerpc_pipe *p,
3876                                          struct policy_handle *handle,
3877                                          uint32_t *change_id)
3878 {
3879         union spoolss_PrinterInfo info;
3880
3881         torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 0, &info),
3882                 "failed to query Printer level 0");
3883
3884         *change_id = info.info0.change_id;
3885
3886         return true;
3887 }
3888
3889 static bool test_ChangeID(struct torture_context *tctx,
3890                           struct dcerpc_pipe *p,
3891                           struct policy_handle *handle)
3892 {
3893         uint32_t change_id, change_id_ex, change_id_info;
3894         uint32_t change_id2, change_id_ex2, change_id_info2;
3895         union spoolss_PrinterInfo info;
3896         const char *comment;
3897
3898
3899         torture_comment(tctx, "Testing ChangeID: id change test #1\n");
3900
3901         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3902                 "failed to query for ChangeID");
3903         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3904                 "failed to query for ChangeID");
3905         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3906                 "failed to query for ChangeID");
3907
3908         torture_assert_int_equal(tctx, change_id, change_id_ex,
3909                 "change_ids should all be equal");
3910         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
3911                 "change_ids should all be equal");
3912
3913
3914         torture_comment(tctx, "Testing ChangeID: id change test #2\n");
3915
3916         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3917                 "failed to query for ChangeID");
3918         torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
3919                 "failed to query Printer level 2");
3920         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3921                 "failed to query for ChangeID");
3922         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3923                 "failed to query for ChangeID");
3924         torture_assert_int_equal(tctx, change_id, change_id_ex,
3925                 "change_id should not have changed");
3926         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
3927                 "change_id should not have changed");
3928
3929
3930         torture_comment(tctx, "Testing ChangeID: id change test #3\n");
3931
3932         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3933                 "failed to query for ChangeID");
3934         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3935                 "failed to query for ChangeID");
3936         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3937                 "failed to query for ChangeID");
3938         torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
3939                 "failed to query Printer level 2");
3940         comment = talloc_strdup(tctx, info.info2.comment);
3941
3942         {
3943                 struct spoolss_SetPrinterInfoCtr info_ctr;
3944                 struct spoolss_DevmodeContainer devmode_ctr;
3945                 struct sec_desc_buf secdesc_ctr;
3946                 union spoolss_SetPrinterInfo sinfo;
3947
3948                 ZERO_STRUCT(info_ctr);
3949                 ZERO_STRUCT(devmode_ctr);
3950                 ZERO_STRUCT(secdesc_ctr);
3951
3952
3953                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
3954                 sinfo.info2->comment    = "torture_comment";
3955
3956                 info_ctr.level = 2;
3957                 info_ctr.info = sinfo;
3958
3959                 torture_assert(tctx, test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
3960                         "failed to call SetPrinter");
3961
3962                 sinfo.info2->comment    = comment;
3963
3964                 torture_assert(tctx, test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
3965                         "failed to call SetPrinter");
3966
3967         }
3968
3969         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id2),
3970                 "failed to query for ChangeID");
3971         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
3972                 "failed to query for ChangeID");
3973         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info2),
3974                 "failed to query for ChangeID");
3975
3976         torture_assert_int_equal(tctx, change_id2, change_id_ex2,
3977                 "change_ids should all be equal");
3978         torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
3979                 "change_ids should all be equal");
3980
3981         torture_assert(tctx, (change_id < change_id2),
3982                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3983                 change_id2, change_id));
3984         torture_assert(tctx, (change_id_ex < change_id_ex2),
3985                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3986                 change_id_ex2, change_id_ex));
3987         torture_assert(tctx, (change_id_info < change_id_info2),
3988                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3989                 change_id_info2, change_id_info));
3990
3991         torture_comment(tctx, "ChangeID tests succeeded\n\n");
3992
3993         return true;
3994 }
3995
3996 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
3997                                        struct dcerpc_pipe *p,
3998                                        struct policy_handle *handle)
3999 {
4000         NTSTATUS status;
4001         struct dcerpc_binding *b;
4002         struct dcerpc_pipe *p2;
4003         struct spoolss_ClosePrinter cp;
4004
4005         /* only makes sense on SMB */
4006         if (p->conn->transport.transport != NCACN_NP) {
4007                 return true;
4008         }
4009
4010         torture_comment(tctx, "testing close on secondary pipe\n");
4011
4012         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
4013         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
4014
4015         status = dcerpc_secondary_connection(p, &p2, b);
4016         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
4017
4018         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
4019         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
4020
4021         cp.in.handle = handle;
4022         cp.out.handle = handle;
4023
4024         status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
4025         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
4026                         "ERROR: Allowed close on secondary connection");
4027
4028         torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
4029                                  "Unexpected fault code");
4030
4031         talloc_free(p2);
4032
4033         return true;
4034 }
4035
4036 static bool test_OpenPrinter_badname(struct torture_context *tctx,
4037                                      struct dcerpc_pipe *p, const char *name)
4038 {
4039         NTSTATUS status;
4040         struct spoolss_OpenPrinter op;
4041         struct spoolss_OpenPrinterEx opEx;
4042         struct policy_handle handle;
4043         bool ret = true;
4044
4045         op.in.printername       = name;
4046         op.in.datatype          = NULL;
4047         op.in.devmode_ctr.devmode= NULL;
4048         op.in.access_mask       = 0;
4049         op.out.handle           = &handle;
4050
4051         torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
4052
4053         status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
4054         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
4055         torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
4056                 "unexpected result");
4057
4058         if (W_ERROR_IS_OK(op.out.result)) {
4059                 ret &=test_ClosePrinter(tctx, p, &handle);
4060         }
4061
4062         opEx.in.printername             = name;
4063         opEx.in.datatype                = NULL;
4064         opEx.in.devmode_ctr.devmode     = NULL;
4065         opEx.in.access_mask             = 0;
4066         opEx.in.level                   = 1;
4067         opEx.in.userlevel.level1        = NULL;
4068         opEx.out.handle                 = &handle;
4069
4070         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
4071
4072         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
4073         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
4074         torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
4075                 "unexpected result");
4076
4077         if (W_ERROR_IS_OK(opEx.out.result)) {
4078                 ret &=test_ClosePrinter(tctx, p, &handle);
4079         }
4080
4081         return ret;
4082 }
4083
4084 static bool test_OpenPrinter(struct torture_context *tctx,
4085                              struct dcerpc_pipe *p,
4086                              const char *name,
4087                              const char *environment)
4088 {
4089         NTSTATUS status;
4090         struct spoolss_OpenPrinter r;
4091         struct policy_handle handle;
4092         bool ret = true;
4093
4094         r.in.printername        = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
4095         r.in.datatype           = NULL;
4096         r.in.devmode_ctr.devmode= NULL;
4097         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
4098         r.out.handle            = &handle;
4099
4100         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
4101
4102         status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
4103
4104         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
4105
4106         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
4107
4108         if (!test_GetPrinter(tctx, p, &handle, environment)) {
4109                 ret = false;
4110         }
4111
4112         if (!torture_setting_bool(tctx, "samba3", false)) {
4113                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
4114                         ret = false;
4115                 }
4116         }
4117
4118         if (!test_ClosePrinter(tctx, p, &handle)) {
4119                 ret = false;
4120         }
4121
4122         return ret;
4123 }
4124
4125 static bool call_OpenPrinterEx(struct torture_context *tctx,
4126                                struct dcerpc_pipe *p,
4127                                const char *name,
4128                                struct spoolss_DeviceMode *devmode,
4129                                struct policy_handle *handle)
4130 {
4131         struct spoolss_OpenPrinterEx r;
4132         struct spoolss_UserLevel1 userlevel1;
4133         NTSTATUS status;
4134
4135         if (name && name[0]) {
4136                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
4137                                                    dcerpc_server_name(p), name);
4138         } else {
4139                 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
4140                                                    dcerpc_server_name(p));
4141         }
4142
4143         r.in.datatype           = NULL;
4144         r.in.devmode_ctr.devmode= devmode;
4145         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
4146         r.in.level              = 1;
4147         r.in.userlevel.level1   = &userlevel1;
4148         r.out.handle = handle;
4149
4150         userlevel1.size = 1234;
4151         userlevel1.client = "hello";
4152         userlevel1.user = "spottyfoot!";
4153         userlevel1.build = 1;
4154         userlevel1.major = 2;
4155         userlevel1.minor = 3;
4156         userlevel1.processor = 4;
4157
4158         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
4159
4160         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
4161
4162         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
4163
4164         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
4165
4166         return true;
4167 }
4168
4169 static bool test_printer_rename(struct torture_context *tctx,
4170                                 struct dcerpc_pipe *p,
4171                                 struct policy_handle *handle,
4172                                 const char *name)
4173 {
4174         bool ret = true;
4175         union spoolss_PrinterInfo info;
4176         union spoolss_SetPrinterInfo sinfo;
4177         struct spoolss_SetPrinterInfoCtr info_ctr;
4178         struct spoolss_DevmodeContainer devmode_ctr;
4179         struct sec_desc_buf secdesc_ctr;
4180         const char *printer_name;
4181         const char *printer_name_orig;
4182         const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
4183         struct policy_handle new_handle;
4184         const char *q;
4185
4186         ZERO_STRUCT(devmode_ctr);
4187         ZERO_STRUCT(secdesc_ctr);
4188
4189         torture_comment(tctx, "Testing Printer rename operations\n");
4190
4191         torture_assert(tctx,
4192                 test_GetPrinter_level(tctx, p, handle, 2, &info),
4193                 "failed to call GetPrinter level 2");
4194
4195         printer_name_orig = talloc_strdup(tctx, info.info2.printername);
4196
4197         q = strrchr(info.info2.printername, '\\');
4198         if (q) {
4199                 torture_warning(tctx,
4200                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
4201         }
4202
4203         torture_assert(tctx,
4204                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
4205
4206         sinfo.info2->printername = printer_name_new;
4207
4208         info_ctr.level = 2;
4209         info_ctr.info = sinfo;
4210
4211         torture_assert(tctx,
4212                 test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
4213                 "failed to call SetPrinter level 2");
4214
4215         torture_assert(tctx,
4216                 test_GetPrinter_level(tctx, p, handle, 2, &info),
4217                 "failed to call GetPrinter level 2");
4218
4219         printer_name = talloc_strdup(tctx, info.info2.printername);
4220
4221         q = strrchr(info.info2.printername, '\\');
4222         if (q) {
4223                 torture_warning(tctx,
4224                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
4225                 q++;
4226                 printer_name = q;
4227         }
4228
4229         torture_assert_str_equal(tctx, printer_name, printer_name_new,
4230                 "new printer name was not set");
4231
4232         torture_assert(tctx,
4233                 test_OpenPrinter_badname(tctx, p, printer_name_orig),
4234                 "still can open printer with oldname");
4235
4236         torture_assert(tctx,
4237                 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
4238                 "failed to open printer with new name");
4239
4240         torture_assert(tctx,
4241                 test_GetPrinter_level(tctx, p, &new_handle, 2, &info),
4242                 "failed to call GetPrinter level 2");
4243
4244         /* FIXME: we openend with servername! */
4245         printer_name = talloc_asprintf(tctx, "\\\\%s\\%s",
4246                 dcerpc_server_name(p), printer_name_new);
4247
4248         torture_assert_str_equal(tctx, info.info2.printername, printer_name,
4249                 "new printer name was not set");
4250
4251         torture_assert(tctx,
4252                 test_ClosePrinter(tctx, p, &new_handle),
4253                 "failed to close printer");
4254
4255         torture_comment(tctx, "Printer rename operations test succeeded\n\n");
4256
4257         return ret;
4258 }
4259
4260
4261 static bool test_OpenPrinterEx(struct torture_context *tctx,
4262                                struct dcerpc_pipe *p,
4263                                const char *name,
4264                                const char *environment)
4265 {
4266         struct policy_handle handle;
4267         bool ret = true;
4268
4269         if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
4270                 return false;
4271         }
4272
4273         if (!test_PrinterInfo_SD(tctx, p, &handle)) {
4274                 ret = false;
4275         }
4276
4277         if (!test_GetPrinter(tctx, p, &handle, environment)) {
4278                 ret = false;
4279         }
4280
4281         if (!test_EnumForms(tctx, p, &handle, false)) {
4282                 ret = false;
4283         }
4284
4285         if (!test_AddForm(tctx, p, &handle, false)) {
4286                 ret = false;
4287         }
4288
4289         if (!test_EnumPrinterData_all(tctx, p, &handle)) {
4290                 ret = false;
4291         }
4292
4293         if (!test_EnumPrinterDataEx(tctx, p, &handle, "PrinterDriverData", NULL, NULL)) {
4294                 ret = false;
4295         }
4296
4297         if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
4298                 ret = false;
4299         }
4300
4301         if (!test_printer_keys(tctx, p, &handle)) {
4302                 ret = false;
4303         }
4304
4305         if (!test_PausePrinter(tctx, p, &handle)) {
4306                 ret = false;
4307         }
4308
4309         if (!test_DoPrintTest(tctx, p, &handle)) {
4310                 ret = false;
4311         }
4312
4313         if (!test_ResumePrinter(tctx, p, &handle)) {
4314                 ret = false;
4315         }
4316
4317         if (!test_SetPrinterData_matrix(tctx, p, &handle, name, NULL, NULL)) {
4318                 ret = false;
4319         }
4320
4321         if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
4322                 ret = false;
4323         }
4324
4325         if (!torture_setting_bool(tctx, "samba3", false)) {
4326                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
4327                         ret = false;
4328                 }
4329         }
4330
4331         if (!test_ClosePrinter(tctx, p, &handle)) {
4332                 ret = false;
4333         }
4334
4335         return ret;
4336 }
4337
4338 static bool test_EnumPrinters_old(struct torture_context *tctx,
4339                                   struct dcerpc_pipe *p,
4340                                   const char *environment)
4341 {
4342         struct spoolss_EnumPrinters r;
4343         NTSTATUS status;
4344         uint16_t levels[] = {1, 2, 4, 5};
4345         int i;
4346         bool ret = true;
4347
4348         for (i=0;i<ARRAY_SIZE(levels);i++) {
4349                 union spoolss_PrinterInfo *info;
4350                 int j;
4351                 uint32_t needed;
4352                 uint32_t count;
4353
4354                 r.in.flags      = PRINTER_ENUM_LOCAL;
4355                 r.in.server     = "";
4356                 r.in.level      = levels[i];
4357                 r.in.buffer     = NULL;
4358                 r.in.offered    = 0;
4359                 r.out.needed    = &needed;
4360                 r.out.count     = &count;
4361                 r.out.info      = &info;
4362
4363                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
4364
4365                 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
4366                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
4367
4368                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4369                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4370                         data_blob_clear(&blob);
4371                         r.in.buffer = &blob;
4372                         r.in.offered = needed;
4373                         status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
4374                 }
4375
4376                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
4377
4378                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
4379
4380                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4381
4382                 if (!info) {
4383                         torture_comment(tctx, "No printers returned\n");
4384                         return true;
4385                 }
4386
4387                 for (j=0;j<count;j++) {
4388                         if (r.in.level == 1) {
4389                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
4390                                 char *slash, *name;
4391                                 name = unc;
4392                                 if (unc[0] == '\\' && unc[1] == '\\') {
4393                                         unc +=2;
4394                                 }
4395                                 slash = strchr(unc, '\\');
4396                                 if (slash) {
4397                                         slash++;
4398                                         name = slash;
4399                                 }
4400                                 if (!test_OpenPrinter(tctx, p, name, environment)) {
4401                                         ret = false;
4402                                 }
4403                                 if (!test_OpenPrinterEx(tctx, p, name, environment)) {
4404                                         ret = false;
4405                                 }
4406                         }
4407                 }
4408         }
4409
4410         return ret;
4411 }
4412
4413 static bool test_GetPrinterDriver(struct torture_context *tctx,
4414                                   struct dcerpc_pipe *p,
4415                                   struct policy_handle *handle,
4416                                   const char *driver_name)
4417 {
4418         struct spoolss_GetPrinterDriver r;
4419         uint32_t needed;
4420
4421         r.in.handle = handle;
4422         r.in.architecture = "W32X86";
4423         r.in.level = 1;
4424         r.in.buffer = NULL;
4425         r.in.offered = 0;
4426         r.out.needed = &needed;
4427
4428         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
4429
4430         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
4431                 "failed to call GetPrinterDriver");
4432         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4433                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4434                 data_blob_clear(&blob);
4435                 r.in.buffer = &blob;
4436                 r.in.offered = needed;
4437                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
4438                         "failed to call GetPrinterDriver");
4439         }
4440
4441         torture_assert_werr_ok(tctx, r.out.result,
4442                 "failed to call GetPrinterDriver");
4443
4444         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4445
4446         return true;
4447 }
4448
4449 static bool test_GetPrinterDriver2(struct torture_context *tctx,
4450                                    struct dcerpc_pipe *p,
4451                                    struct policy_handle *handle,
4452                                    const char *driver_name,
4453                                    const char *architecture)
4454 {
4455         struct spoolss_GetPrinterDriver2 r;
4456         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
4457         uint32_t needed;
4458         uint32_t server_major_version;
4459         uint32_t server_minor_version;
4460         int i;
4461
4462         r.in.handle = handle;
4463         r.in.architecture = architecture;
4464         r.in.client_major_version = 3;
4465         r.in.client_minor_version = 0;
4466         r.out.needed = &needed;
4467         r.out.server_major_version = &server_major_version;
4468         r.out.server_minor_version = &server_minor_version;
4469
4470         for (i=0;i<ARRAY_SIZE(levels);i++) {
4471
4472                 r.in.buffer = NULL;
4473                 r.in.offered = 0;
4474                 r.in.level = levels[i];
4475
4476                 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
4477                         driver_name, r.in.level);
4478
4479                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
4480                         "failed to call GetPrinterDriver2");
4481                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4482                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4483                         data_blob_clear(&blob);
4484                         r.in.buffer = &blob;
4485                         r.in.offered = needed;
4486                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
4487                                 "failed to call GetPrinterDriver2");
4488                 }
4489
4490                 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
4491                         switch (r.in.level) {
4492                         case 101:
4493                         case 8:
4494                                 continue;
4495                         default:
4496                                 break;
4497                         }
4498                 }
4499
4500                 torture_assert_werr_ok(tctx, r.out.result,
4501                         "failed to call GetPrinterDriver2");
4502
4503                 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4504         }
4505
4506         return true;
4507 }
4508
4509 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
4510                                         struct dcerpc_pipe *p,
4511                                         const char *environment)
4512 {
4513         struct spoolss_EnumPrinterDrivers r;
4514         NTSTATUS status;
4515         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
4516         int i;
4517
4518         for (i=0;i<ARRAY_SIZE(levels);i++) {
4519
4520                 uint32_t needed;
4521                 uint32_t count;
4522                 union spoolss_DriverInfo *info;
4523
4524                 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
4525                 r.in.environment = environment;
4526                 r.in.level = levels[i];
4527                 r.in.buffer = NULL;
4528                 r.in.offered = 0;
4529                 r.out.needed = &needed;
4530                 r.out.count = &count;
4531                 r.out.info = &info;
4532
4533                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
4534
4535                 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
4536
4537                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
4538
4539                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4540                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4541                         data_blob_clear(&blob);
4542                         r.in.buffer = &blob;
4543                         r.in.offered = needed;
4544                         status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
4545                 }
4546
4547                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
4548
4549                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
4550
4551                 if (!info) {
4552                         torture_comment(tctx, "No printer drivers returned\n");
4553                         break;
4554                 }
4555
4556                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4557         }
4558
4559         return true;
4560 }
4561
4562 static bool test_DeletePrinter(struct torture_context *tctx,
4563                                struct dcerpc_pipe *p,
4564                                struct policy_handle *handle)
4565 {
4566         struct spoolss_DeletePrinter r;
4567
4568         torture_comment(tctx, "Testing DeletePrinter\n");
4569
4570         r.in.handle = handle;
4571
4572         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter(p, tctx, &r),
4573                 "failed to delete printer");
4574         torture_assert_werr_ok(tctx, r.out.result,
4575                 "failed to delete printer");
4576
4577         return true;
4578 }
4579
4580 static bool test_EnumPrinters_findname(struct torture_context *tctx,
4581                                        struct dcerpc_pipe *p,
4582                                        uint32_t flags,
4583                                        uint32_t level,
4584                                        const char *name,
4585                                        bool *found)
4586 {
4587         struct spoolss_EnumPrinters e;
4588         uint32_t count;
4589         union spoolss_PrinterInfo *info;
4590         uint32_t needed;
4591         int i;
4592
4593         *found = false;
4594
4595         e.in.flags = flags;
4596         e.in.server = NULL;
4597         e.in.level = level;
4598         e.in.buffer = NULL;
4599         e.in.offered = 0;
4600         e.out.count = &count;
4601         e.out.info = &info;
4602         e.out.needed = &needed;
4603
4604         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
4605                 "failed to enum printers");
4606
4607         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
4608                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4609                 data_blob_clear(&blob);
4610                 e.in.buffer = &blob;
4611                 e.in.offered = needed;
4612
4613                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
4614                         "failed to enum printers");
4615         }
4616
4617         torture_assert_werr_ok(tctx, e.out.result,
4618                 "failed to enum printers");
4619
4620         for (i=0; i < count; i++) {
4621
4622                 const char *current = NULL;
4623                 const char *q;
4624
4625                 switch (level) {
4626                 case 1:
4627                         current = info[i].info1.name;
4628                         break;
4629                 }
4630
4631                 if (strequal(current, name)) {
4632                         *found = true;
4633                         break;
4634                 }
4635
4636                 q = strrchr(current, '\\');
4637                 if (q) {
4638                         if (!e.in.server) {
4639                                 torture_warning(tctx,
4640                                         "server returns printername %s incl. servername although we did not set servername", current);
4641                         }
4642                         q++;
4643                         if (strequal(q, name)) {
4644                                 *found = true;
4645                                 break;
4646                         }
4647                 }
4648         }
4649
4650         return true;
4651 }
4652
4653 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
4654                                       struct dcerpc_pipe *p,
4655                                       const char *printername,
4656                                       bool ex)
4657 {
4658         WERROR result;
4659         struct spoolss_AddPrinter r;
4660         struct spoolss_AddPrinterEx rex;
4661         struct spoolss_SetPrinterInfoCtr info_ctr;
4662         struct spoolss_SetPrinterInfo1 info1;
4663         struct spoolss_DevmodeContainer devmode_ctr;
4664         struct sec_desc_buf secdesc_ctr;
4665         struct spoolss_UserLevelCtr userlevel_ctr;
4666         struct policy_handle handle;
4667         bool found = false;
4668
4669         ZERO_STRUCT(devmode_ctr);
4670         ZERO_STRUCT(secdesc_ctr);
4671         ZERO_STRUCT(userlevel_ctr);
4672         ZERO_STRUCT(info1);
4673
4674         torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
4675
4676         /* try to add printer to wellknown printer list (level 1) */
4677
4678         userlevel_ctr.level = 1;
4679
4680         info_ctr.info.info1 = &info1;
4681         info_ctr.level = 1;
4682
4683         rex.in.server = NULL;
4684         rex.in.info_ctr = &info_ctr;
4685         rex.in.devmode_ctr = &devmode_ctr;
4686         rex.in.secdesc_ctr = &secdesc_ctr;
4687         rex.in.userlevel_ctr = &userlevel_ctr;
4688         rex.out.handle = &handle;
4689
4690         r.in.server = NULL;
4691         r.in.info_ctr = &info_ctr;
4692         r.in.devmode_ctr = &devmode_ctr;
4693         r.in.secdesc_ctr = &secdesc_ctr;
4694         r.out.handle = &handle;
4695
4696         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4697                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4698                 "failed to add printer");
4699         result = ex ? rex.out.result : r.out.result;
4700         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
4701                 "unexpected result code");
4702
4703         info1.name = printername;
4704         info1.flags = PRINTER_ATTRIBUTE_SHARED;
4705
4706         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4707                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4708                 "failed to add printer");
4709         result = ex ? rex.out.result : r.out.result;
4710         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4711                 "unexpected result code");
4712
4713         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
4714            better do a real check to see the printer is really there */
4715
4716         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4717                                                         PRINTER_ENUM_NETWORK, 1,
4718                                                         printername,
4719                                                         &found),
4720                         "failed to enum printers");
4721
4722         torture_assert(tctx, found, "failed to find newly added printer");
4723
4724         info1.flags = 0;
4725
4726         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4727                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4728                 "failed to add printer");
4729         result = ex ? rex.out.result : r.out.result;
4730         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4731                 "unexpected result code");
4732
4733         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
4734            better do a real check to see the printer has really been removed
4735            from the well known printer list */
4736
4737         found = false;
4738
4739         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4740                                                         PRINTER_ENUM_NETWORK, 1,
4741                                                         printername,
4742                                                         &found),
4743                         "failed to enum printers");
4744 #if 0
4745         torture_assert(tctx, !found, "printer still in well known printer list");
4746 #endif
4747         return true;
4748 }
4749
4750 static bool test_AddPrinter_normal(struct torture_context *tctx,
4751                                    struct dcerpc_pipe *p,
4752                                    struct policy_handle *handle_p,
4753                                    const char *printername,
4754                                    const char *drivername,
4755                                    const char *portname,
4756                                    bool ex)
4757 {
4758         WERROR result;
4759         struct spoolss_AddPrinter r;
4760         struct spoolss_AddPrinterEx rex;
4761         struct spoolss_SetPrinterInfoCtr info_ctr;
4762         struct spoolss_SetPrinterInfo2 info2;
4763         struct spoolss_DevmodeContainer devmode_ctr;
4764         struct sec_desc_buf secdesc_ctr;
4765         struct spoolss_UserLevelCtr userlevel_ctr;
4766         struct policy_handle handle;
4767         bool found = false;
4768         bool existing_printer_deleted = false;
4769
4770         ZERO_STRUCT(devmode_ctr);
4771         ZERO_STRUCT(secdesc_ctr);
4772         ZERO_STRUCT(userlevel_ctr);
4773
4774         torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
4775
4776         userlevel_ctr.level = 1;
4777
4778         rex.in.server = NULL;
4779         rex.in.info_ctr = &info_ctr;
4780         rex.in.devmode_ctr = &devmode_ctr;
4781         rex.in.secdesc_ctr = &secdesc_ctr;
4782         rex.in.userlevel_ctr = &userlevel_ctr;
4783         rex.out.handle = &handle;
4784
4785         r.in.server = NULL;
4786         r.in.info_ctr = &info_ctr;
4787         r.in.devmode_ctr = &devmode_ctr;
4788         r.in.secdesc_ctr = &secdesc_ctr;
4789         r.out.handle = &handle;
4790
4791  again:
4792
4793         /* try to add printer to printer list (level 2) */
4794
4795         ZERO_STRUCT(info2);
4796
4797         info_ctr.info.info2 = &info2;
4798         info_ctr.level = 2;
4799
4800         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4801                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4802                 "failed to add printer");
4803         result = ex ? rex.out.result : r.out.result;
4804         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
4805                 "unexpected result code");
4806
4807         info2.printername = printername;
4808
4809         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4810                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4811                 "failed to add printer");
4812         result = ex ? rex.out.result : r.out.result;
4813
4814         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
4815                 struct policy_handle printer_handle;
4816
4817                 if (existing_printer_deleted) {
4818                         torture_fail(tctx, "already deleted printer still existing?");
4819                 }
4820
4821                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
4822                         "failed to open printer handle");
4823
4824                 torture_assert(tctx, test_DeletePrinter(tctx, p, &printer_handle),
4825                         "failed to delete printer");
4826
4827                 torture_assert(tctx, test_ClosePrinter(tctx, p, &printer_handle),
4828                         "failed to close server handle");
4829
4830                 existing_printer_deleted = true;
4831
4832                 goto again;
4833         }
4834
4835         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
4836                 "unexpected result code");
4837
4838         info2.portname = portname;
4839
4840         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4841                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4842                 "failed to add printer");
4843         result = ex ? rex.out.result : r.out.result;
4844         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
4845                 "unexpected result code");
4846
4847         info2.drivername = drivername;
4848
4849         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4850                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4851                 "failed to add printer");
4852         result = ex ? rex.out.result : r.out.result;
4853
4854         /* w2k8r2 allows to add printer w/o defining printprocessor */
4855
4856         if (!W_ERROR_IS_OK(result)) {
4857                 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
4858                         "unexpected result code");
4859
4860                 info2.printprocessor = "winprint";
4861
4862                 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4863                                                       dcerpc_spoolss_AddPrinter(p, tctx, &r),
4864                         "failed to add printer");
4865                 result = ex ? rex.out.result : r.out.result;
4866                 torture_assert_werr_ok(tctx, result,
4867                         "failed to add printer");
4868         }
4869
4870         *handle_p = handle;
4871
4872         /* we are paranoid, really check if the printer is there now */
4873
4874         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4875                                                         PRINTER_ENUM_LOCAL, 1,
4876                                                         printername,
4877                                                         &found),
4878                         "failed to enum printers");
4879         torture_assert(tctx, found, "failed to find newly added printer");
4880
4881         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4882                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
4883                 "failed to add printer");
4884         result = ex ? rex.out.result : r.out.result;
4885         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4886                 "unexpected result code");
4887
4888         return true;
4889 }
4890
4891 static bool test_AddPrinterEx(struct torture_context *tctx,
4892                               struct dcerpc_pipe *p,
4893                               struct policy_handle *handle_p,
4894                               const char *printername,
4895                               const char *drivername,
4896                               const char *portname)
4897 {
4898         bool ret = true;
4899
4900         if (!torture_setting_bool(tctx, "samba3", false)) {
4901                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
4902                         torture_comment(tctx, "failed to add printer to well known list\n");
4903                         ret = false;
4904                 }
4905         }
4906
4907         if (!test_AddPrinter_normal(tctx, p, handle_p,
4908                                     printername, drivername, portname,
4909                                     true)) {
4910                 torture_comment(tctx, "failed to add printer to printer list\n");
4911                 ret = false;
4912         }
4913
4914         return ret;
4915 }
4916
4917 static bool test_AddPrinter(struct torture_context *tctx,
4918                             struct dcerpc_pipe *p,
4919                             struct policy_handle *handle_p,
4920                             const char *printername,
4921                             const char *drivername,
4922                             const char *portname)
4923 {
4924         bool ret = true;
4925
4926         if (!torture_setting_bool(tctx, "samba3", false)) {
4927                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
4928                         torture_comment(tctx, "failed to add printer to well known list\n");
4929                         ret = false;
4930                 }
4931         }
4932
4933         if (!test_AddPrinter_normal(tctx, p, handle_p,
4934                                     printername, drivername, portname,
4935                                     false)) {
4936                 torture_comment(tctx, "failed to add printer to printer list\n");
4937                 ret = false;
4938         }
4939
4940         return ret;
4941 }
4942
4943 static bool test_printer_info(struct torture_context *tctx,
4944                               struct dcerpc_pipe *p,
4945                               struct policy_handle *handle)
4946 {
4947         bool ret = true;
4948
4949         if (torture_setting_bool(tctx, "samba3", false)) {
4950                 torture_skip(tctx, "skipping printer info cross tests against samba 3");
4951         }
4952
4953         if (!test_PrinterInfo(tctx, p, handle)) {
4954                 ret = false;
4955         }
4956
4957         if (!test_SetPrinter_errors(tctx, p, handle)) {
4958                 ret = false;
4959         }
4960
4961         return ret;
4962 }
4963
4964 static bool test_EnumPrinterKey(struct torture_context *tctx,
4965                                 struct dcerpc_pipe *p,
4966                                 struct policy_handle *handle,
4967                                 const char *key_name,
4968                                 const char ***array)
4969 {
4970         struct spoolss_EnumPrinterKey r;
4971         uint32_t needed = 0;
4972         union spoolss_KeyNames key_buffer;
4973         int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
4974         uint32_t _ndr_size;
4975         int i;
4976
4977         r.in.handle = handle;
4978         r.in.key_name = key_name;
4979         r.out.key_buffer = &key_buffer;
4980         r.out.needed = &needed;
4981         r.out._ndr_size = &_ndr_size;
4982
4983         for (i=0; i < ARRAY_SIZE(offered); i++) {
4984
4985                 if (offered[i] < 0 && needed) {
4986                         if (needed <= 4) {
4987                                 continue;
4988                         }
4989                         r.in.offered = needed + offered[i];
4990                 } else {
4991                         r.in.offered = offered[i];
4992                 }
4993
4994                 ZERO_STRUCT(key_buffer);
4995
4996                 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
4997
4998                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
4999                         "failed to call EnumPrinterKey");
5000                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
5001
5002                         torture_assert(tctx, (_ndr_size == r.in.offered/2),
5003                                 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
5004                                         _ndr_size, r.in.offered/2));
5005
5006                         r.in.offered = needed;
5007                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
5008                                 "failed to call EnumPrinterKey");
5009                 }
5010
5011                 if (offered[i] > 0) {
5012                         torture_assert_werr_ok(tctx, r.out.result,
5013                                 "failed to call EnumPrinterKey");
5014                 }
5015
5016                 torture_assert(tctx, (_ndr_size == r.in.offered/2),
5017                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
5018                                 _ndr_size, r.in.offered/2));
5019
5020                 torture_assert(tctx, (*r.out.needed <= r.in.offered),
5021                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
5022
5023                 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
5024                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
5025
5026                 if (key_buffer.string_array) {
5027                         uint32_t calc_needed = 0;
5028                         int s;
5029                         for (s=0; key_buffer.string_array[s]; s++) {
5030                                 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
5031                         }
5032                         if (!key_buffer.string_array[0]) {
5033                                 calc_needed += 2;
5034                         }
5035                         calc_needed += 2;
5036
5037                         torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
5038                                 "EnumPrinterKey unexpected size");
5039                 }
5040         }
5041
5042         if (array) {
5043                 *array = key_buffer.string_array;
5044         }
5045
5046         return true;
5047 }
5048
5049 bool test_printer_keys(struct torture_context *tctx,
5050                        struct dcerpc_pipe *p,
5051                        struct policy_handle *handle)
5052 {
5053         const char **key_array = NULL;
5054         int i;
5055
5056         torture_comment(tctx, "Testing Printer Keys\n");
5057
5058         torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, "", &key_array),
5059                 "failed to call test_EnumPrinterKey");
5060
5061         for (i=0; key_array && key_array[i]; i++) {
5062                 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, key_array[i], NULL),
5063                         "failed to call test_EnumPrinterKey");
5064         }
5065         for (i=0; key_array && key_array[i]; i++) {
5066                 torture_assert(tctx, test_EnumPrinterDataEx(tctx, p, handle, key_array[i], NULL, NULL),
5067                         "failed to call test_EnumPrinterDataEx");
5068         }
5069
5070         torture_comment(tctx, "Printer Keys test succeeded\n\n");
5071
5072         return true;
5073 }
5074
5075 static bool test_one_printer(struct torture_context *tctx,
5076                              struct dcerpc_pipe *p,
5077                              struct policy_handle *handle,
5078                              const char *name)
5079 {
5080         bool ret = true;
5081
5082         if (!test_printer_info(tctx, p, handle)) {
5083                 ret = false;
5084         }
5085
5086         if (!test_PrinterInfo_SD(tctx, p, handle)) {
5087                 ret = false;
5088         }
5089
5090         if (!test_PrinterInfo_DevMode(tctx, p, handle, name)) {
5091                 ret = false;
5092         }
5093
5094         if (!test_ChangeID(tctx, p, handle)) {
5095                 ret = false;
5096         }
5097
5098         if (!test_printer_keys(tctx, p, handle)) {
5099                 ret = false;
5100         }
5101
5102         if (!test_EnumPrinterData_consistency(tctx, p, handle)) {
5103                 ret = false;
5104         }
5105
5106         if (!test_SetPrinterDataEx_matrix(tctx, p, handle, name, NULL, NULL)) {
5107                 ret = false;
5108         }
5109
5110         if (!test_PrinterData_winreg(tctx, p, handle, name)) {
5111                 ret = false;
5112         }
5113
5114         if (!test_printer_rename(tctx, p, handle, name)) {
5115                 ret = false;
5116         }
5117
5118         return ret;
5119 }
5120
5121 static bool test_printer(struct torture_context *tctx,
5122                          struct dcerpc_pipe *p)
5123 {
5124         bool ret = true;
5125         struct policy_handle handle[2];
5126         bool found = false;
5127         const char *drivername = "Microsoft XPS Document Writer";
5128         const char *portname = "LPT1:";
5129
5130         /* test printer created via AddPrinter */
5131
5132         if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
5133                 return false;
5134         }
5135
5136         if (!test_one_printer(tctx, p, &handle[0], TORTURE_PRINTER)) {
5137                 ret = false;
5138         }
5139
5140         if (!test_DeletePrinter(tctx, p, &handle[0])) {
5141                 ret = false;
5142         }
5143
5144         if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
5145                                         TORTURE_PRINTER, &found)) {
5146                 ret = false;
5147         }
5148
5149         torture_assert(tctx, !found, "deleted printer still there");
5150
5151         /* test printer created via AddPrinterEx */
5152
5153         if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
5154                 return false;
5155         }
5156
5157         if (!test_one_printer(tctx, p, &handle[1], TORTURE_PRINTER_EX)) {
5158                 ret = false;
5159         }
5160
5161         if (!test_DeletePrinter(tctx, p, &handle[1])) {
5162                 ret = false;
5163         }
5164
5165         if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
5166                                         TORTURE_PRINTER_EX, &found)) {
5167                 ret = false;
5168         }
5169
5170         torture_assert(tctx, !found, "deleted printer still there");
5171
5172         return ret;
5173 }
5174
5175 static bool test_architecture_buffer(struct torture_context *tctx,
5176                                      struct dcerpc_pipe *p)
5177 {
5178         struct spoolss_OpenPrinterEx r;
5179         struct spoolss_UserLevel1 u1;
5180         struct policy_handle handle;
5181         uint32_t architectures[] = {
5182                 PROCESSOR_ARCHITECTURE_INTEL,
5183                 PROCESSOR_ARCHITECTURE_IA64,
5184                 PROCESSOR_ARCHITECTURE_AMD64
5185         };
5186         uint32_t needed[3];
5187         int i;
5188
5189         for (i=0; i < ARRAY_SIZE(architectures); i++) {
5190
5191                 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
5192
5193                 u1.size = 0;
5194                 u1.client = NULL;
5195                 u1.user = NULL;
5196                 u1.build = 0;
5197                 u1.major = 3;
5198                 u1.minor = 0;
5199                 u1.processor = architectures[i];
5200
5201                 r.in.printername        = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
5202                 r.in.datatype           = NULL;
5203                 r.in.devmode_ctr.devmode= NULL;
5204                 r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
5205                 r.in.level               = 1;
5206                 r.in.userlevel.level1   = &u1;
5207                 r.out.handle            = &handle;
5208
5209                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx(p, tctx, &r), "");
5210                 torture_assert_werr_ok(tctx, r.out.result, "");
5211
5212                 {
5213                         struct spoolss_EnumPrinters e;
5214                         uint32_t count;
5215                         union spoolss_PrinterInfo *info;
5216
5217                         e.in.flags = PRINTER_ENUM_LOCAL;
5218                         e.in.server = NULL;
5219                         e.in.level = 2;
5220                         e.in.buffer = NULL;
5221                         e.in.offered = 0;
5222                         e.out.count = &count;
5223                         e.out.info = &info;
5224                         e.out.needed = &needed[i];
5225
5226                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e), "");
5227 #if 0
5228                         torture_comment(tctx, "needed was %d\n", needed[i]);
5229 #endif
5230                 }
5231
5232                 torture_assert(tctx, test_ClosePrinter(tctx, p, &handle), "");
5233         }
5234
5235         for (i=1; i < ARRAY_SIZE(architectures); i++) {
5236                 if (needed[i-1] != needed[i]) {
5237                         torture_fail(tctx,
5238                                 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
5239                                                 needed[i-1], architectures[i-1], needed[i], architectures[i]));
5240                 }
5241         }
5242
5243         return true;
5244 }
5245
5246 bool torture_rpc_spoolss(struct torture_context *torture)
5247 {
5248         NTSTATUS status;
5249         struct dcerpc_pipe *p;
5250         bool ret = true;
5251         struct test_spoolss_context *ctx;
5252         const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
5253
5254         status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
5255         if (!NT_STATUS_IS_OK(status)) {
5256                 return false;
5257         }
5258
5259         ctx = talloc_zero(torture, struct test_spoolss_context);
5260
5261         ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
5262         ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle, &environment);
5263         ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
5264         ret &= test_AddForm(torture, p, &ctx->server_handle, true);
5265         ret &= test_EnumPorts(torture, p, ctx);
5266         ret &= test_GetPrinterDriverDirectory(torture, p, ctx, environment);
5267         ret &= test_GetPrintProcessorDirectory(torture, p, ctx, environment);
5268         ret &= test_EnumPrinterDrivers(torture, p, ctx, environment);
5269         ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
5270         ret &= test_EnumMonitors(torture, p, ctx);
5271         ret &= test_EnumPrintProcessors(torture, p, ctx, environment);
5272         ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
5273         ret &= test_EnumPrinters(torture, p, ctx);
5274         ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
5275         ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
5276         ret &= test_OpenPrinter_badname(torture, p, "");
5277         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
5278         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
5279         ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
5280         ret &= test_OpenPrinter_badname(torture, p,
5281                                         talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
5282
5283
5284         ret &= test_AddPort(torture, p);
5285         ret &= test_EnumPorts_old(torture, p);
5286         ret &= test_EnumPrinters_old(torture, p, environment);
5287         ret &= test_EnumPrinterDrivers_old(torture, p, environment);
5288         ret &= test_architecture_buffer(torture, p);
5289
5290         return ret;
5291 }
5292
5293 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
5294 {
5295         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
5296
5297         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
5298                                                         "printer", &ndr_table_spoolss);
5299
5300         torture_rpc_tcase_add_test(tcase, "printer", test_printer);
5301
5302         return suite;
5303 }