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