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