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