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