s4-smbtorture: finally test REG_MULTI_SZ in winreg/driverinfo consistency tests.
[metze/samba/wip.git] / source4 / torture / rpc / spoolss.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for spoolss rpc operations
4
5    Copyright (C) Tim Potter 2003
6    Copyright (C) Stefan Metzmacher 2005
7    Copyright (C) Jelmer Vernooij 2007
8    Copyright (C) Guenther Deschner 2009-2010
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "torture/torture.h"
26 #include "librpc/gen_ndr/ndr_misc.h"
27 #include "librpc/gen_ndr/ndr_spoolss.h"
28 #include "librpc/gen_ndr/ndr_spoolss_c.h"
29 #include "librpc/gen_ndr/ndr_winreg_c.h"
30 #include "librpc/gen_ndr/ndr_security.h"
31 #include "libcli/security/security.h"
32 #include "torture/rpc/torture_rpc.h"
33 #include "param/param.h"
34 #include "lib/registry/registry.h"
35 #include "libcli/libcli.h"
36 #include "libcli/raw/raw_proto.h"
37 #include "libcli/resolve/resolve.h"
38 #include "lib/cmdline/popt_common.h"
39 #include "system/filesys.h"
40
41 #define TORTURE_WELLKNOWN_PRINTER       "torture_wkn_printer"
42 #define TORTURE_PRINTER                 "torture_printer"
43 #define TORTURE_WELLKNOWN_PRINTER_EX    "torture_wkn_printer_ex"
44 #define TORTURE_PRINTER_EX              "torture_printer_ex"
45 #define TORTURE_DRIVER                  "torture_driver"
46 #define TORTURE_DRIVER_EX               "torture_driver_ex"
47
48 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
49 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
50 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
51 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
52 #define TOP_LEVEL_CONTROL_PRINTERS_KEY TOP_LEVEL_CONTROL_KEY "\\Printers"
53 #define TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY TOP_LEVEL_CONTROL_KEY "\\Environments"
54
55 struct test_spoolss_context {
56         /* print server handle */
57         struct policy_handle server_handle;
58
59         /* for EnumPorts */
60         uint32_t port_count[3];
61         union spoolss_PortInfo *ports[3];
62
63         /* for EnumPrinterDrivers */
64         uint32_t driver_count[8];
65         union spoolss_DriverInfo *drivers[8];
66
67         /* for EnumMonitors */
68         uint32_t monitor_count[3];
69         union spoolss_MonitorInfo *monitors[3];
70
71         /* for EnumPrintProcessors */
72         uint32_t print_processor_count[2];
73         union spoolss_PrintProcessorInfo *print_processors[2];
74
75         /* for EnumPrinters */
76         uint32_t printer_count[6];
77         union spoolss_PrinterInfo *printers[6];
78 };
79
80 struct torture_driver_context {
81         struct {
82                 const char *driver_directory;
83                 const char *environment;
84         } local;
85         struct {
86                 const char *driver_directory;
87                 const char *environment;
88         } remote;
89         struct spoolss_AddDriverInfo8 info8;
90         bool ex;
91 };
92
93 #define COMPARE_STRING(tctx, c,r,e) \
94         torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
95
96 /* not every compiler supports __typeof__() */
97 #if (__GNUC__ >= 3)
98 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
99         if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
100                 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
101         }\
102         if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
103                 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
104         }\
105 } while(0)
106 #else
107 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
108 #endif
109
110 #define COMPARE_UINT32(tctx, c, r, e) do {\
111         _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
112         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
113 } while(0)
114
115 #define COMPARE_UINT64(tctx, c, r, e) do {\
116         _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
117         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
118 } while(0)
119
120
121 #define COMPARE_NTTIME(tctx, c, r, e) do {\
122         _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
123         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
124 } while(0)
125
126 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
127         int __i; \
128         if (!c.e && !r.e) { \
129                 break; \
130         } \
131         if (c.e && !r.e) { \
132                 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
133         } \
134         if (!c.e && r.e) { \
135                 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
136         } \
137         for (__i=0;c.e[__i] != NULL; __i++) { \
138                 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
139         } \
140 } while(0)
141
142 #define CHECK_ALIGN(size, n) do {\
143         if (size % n) {\
144                 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
145                         size, n, size + n - (size % n));\
146         }\
147 } while(0)
148
149 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
150
151 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, ic, needed, align) do { \
152         if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
153         uint32_t size = ndr_size_##fn##_info(tctx, ic, level, count, info);\
154         uint32_t round_size = DO_ROUND(size, align);\
155         if (round_size != needed) {\
156                 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
157                 CHECK_ALIGN(size, align);\
158         }\
159         }\
160 } while(0)
161
162 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, ic, needed, align) do { \
163         if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
164         uint32_t size = ndr_size_##fn##_info(tctx, ic, count, info);\
165         uint32_t round_size = DO_ROUND(size, align);\
166         if (round_size != needed) {\
167                 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
168                 CHECK_ALIGN(size, align);\
169         }\
170         }\
171 } while(0)
172
173 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, ic, needed, align) do { \
174         if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
175         uint32_t size = ndr_size_##fn(info, level, ic, 0);\
176         uint32_t round_size = DO_ROUND(size, align);\
177         if (round_size != needed) {\
178                 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
179                 CHECK_ALIGN(size, align);\
180         }\
181         }\
182 } while(0)
183
184 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context *tctx,
185                                           const union spoolss_PrinterInfo *i,
186                                           uint32_t level,
187                                           union spoolss_SetPrinterInfo *s)
188 {
189         switch (level) {
190         case 0:
191                 s->info0                        = talloc(tctx, struct spoolss_SetPrinterInfo0);
192                 break;
193         case 2:
194                 s->info2                        = talloc(tctx, struct spoolss_SetPrinterInfo2);
195                 s->info2->servername            = i->info2.servername;
196                 s->info2->printername           = i->info2.printername;
197                 s->info2->sharename             = i->info2.sharename;
198                 s->info2->portname              = i->info2.portname;
199                 s->info2->drivername            = i->info2.drivername;
200                 s->info2->comment               = i->info2.comment;
201                 s->info2->location              = i->info2.location;
202                 s->info2->devmode_ptr           = 0;
203                 s->info2->sepfile               = i->info2.sepfile;
204                 s->info2->printprocessor        = i->info2.printprocessor;
205                 s->info2->datatype              = i->info2.datatype;
206                 s->info2->parameters            = i->info2.parameters;
207                 s->info2->secdesc_ptr           = 0;
208                 s->info2->attributes            = i->info2.attributes;
209                 s->info2->priority              = i->info2.priority;
210                 s->info2->defaultpriority       = i->info2.defaultpriority;
211                 s->info2->starttime             = i->info2.starttime;
212                 s->info2->untiltime             = i->info2.untiltime;
213                 s->info2->status                = i->info2.status;
214                 s->info2->cjobs                 = i->info2.cjobs;
215                 s->info2->averageppm            = i->info2.averageppm;
216                 break;
217         case 3:
218         case 4:
219         case 5:
220         case 6:
221         case 7:
222         case 8:
223         case 9:
224         default:
225                 return false;
226         }
227
228         return true;
229 }
230
231 static bool test_OpenPrinter_server(struct torture_context *tctx,
232                                     struct dcerpc_pipe *p,
233                                     struct policy_handle *server_handle)
234 {
235         NTSTATUS status;
236         struct spoolss_OpenPrinter op;
237         struct dcerpc_binding_handle *b = p->binding_handle;
238
239         op.in.printername       = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
240         op.in.datatype          = NULL;
241         op.in.devmode_ctr.devmode= NULL;
242         op.in.access_mask       = 0;
243         op.out.handle           = server_handle;
244
245         torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
246
247         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
248         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
249         torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
250
251         return true;
252 }
253
254 static bool test_EnumPorts(struct torture_context *tctx,
255                            struct dcerpc_binding_handle *b,
256                            struct test_spoolss_context *ctx)
257 {
258         NTSTATUS status;
259         struct spoolss_EnumPorts r;
260         uint16_t levels[] = { 1, 2 };
261         int i, j;
262
263         for (i=0;i<ARRAY_SIZE(levels);i++) {
264                 int level = levels[i];
265                 DATA_BLOB blob;
266                 uint32_t needed;
267                 uint32_t count;
268                 union spoolss_PortInfo *info;
269
270                 r.in.servername = "";
271                 r.in.level = level;
272                 r.in.buffer = NULL;
273                 r.in.offered = 0;
274                 r.out.needed = &needed;
275                 r.out.count = &count;
276                 r.out.info = &info;
277
278                 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
279
280                 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
281                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
282                 if (W_ERROR_IS_OK(r.out.result)) {
283                         /* TODO: do some more checks here */
284                         continue;
285                 }
286                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
287                         "EnumPorts unexpected return code");
288
289                 blob = data_blob_talloc_zero(ctx, needed);
290                 r.in.buffer = &blob;
291                 r.in.offered = needed;
292
293                 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
294                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
295
296                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
297
298                 torture_assert(tctx, info, "EnumPorts returned no info");
299
300                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
301
302                 ctx->port_count[level]  = count;
303                 ctx->ports[level]       = info;
304         }
305
306         for (i=1;i<ARRAY_SIZE(levels);i++) {
307                 int level = levels[i];
308                 int old_level = levels[i-1];
309                 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
310                         "EnumPorts invalid value");
311         }
312         /* if the array sizes are not the same we would maybe segfault in the following code */
313
314         for (i=0;i<ARRAY_SIZE(levels);i++) {
315                 int level = levels[i];
316                 for (j=0;j<ctx->port_count[level];j++) {
317                         union spoolss_PortInfo *cur = &ctx->ports[level][j];
318                         union spoolss_PortInfo *ref = &ctx->ports[2][j];
319                         switch (level) {
320                         case 1:
321                                 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
322                                 break;
323                         case 2:
324                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
325                                 break;
326                         }
327                 }
328         }
329
330         return true;
331 }
332
333 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
334                                             struct dcerpc_pipe *p,
335                                             const char *environment)
336 {
337         NTSTATUS status;
338         struct dcerpc_binding_handle *b = p->binding_handle;
339         struct spoolss_GetPrintProcessorDirectory r;
340         struct {
341                 uint16_t level;
342                 const char *server;
343         } levels[] = {{
344                         .level  = 1,
345                         .server = NULL
346                 },{
347                         .level  = 1,
348                         .server = ""
349                 },{
350                         .level  = 78,
351                         .server = ""
352                 },{
353                         .level  = 1,
354                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
355                 },{
356                         .level  = 1024,
357                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
358                 }
359         };
360         int i;
361         uint32_t needed;
362
363         for (i=0;i<ARRAY_SIZE(levels);i++) {
364                 int level = levels[i].level;
365                 DATA_BLOB blob;
366
367                 r.in.server             = levels[i].server;
368                 r.in.environment        = environment;
369                 r.in.level              = level;
370                 r.in.buffer             = NULL;
371                 r.in.offered            = 0;
372                 r.out.needed            = &needed;
373
374                 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
375
376                 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
377                 torture_assert_ntstatus_ok(tctx, status,
378                         "dcerpc_spoolss_GetPrintProcessorDirectory failed");
379                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
380                         "GetPrintProcessorDirectory unexpected return code");
381
382                 blob = data_blob_talloc_zero(tctx, needed);
383                 r.in.buffer = &blob;
384                 r.in.offered = needed;
385
386                 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
387                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
388
389                 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
390
391                 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
392         }
393
394         return true;
395 }
396
397
398 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
399                                            struct dcerpc_pipe *p,
400                                            const char *environment)
401 {
402         NTSTATUS status;
403         struct dcerpc_binding_handle *b = p->binding_handle;
404         struct spoolss_GetPrinterDriverDirectory r;
405         struct {
406                 uint16_t level;
407                 const char *server;
408         } levels[] = {{
409                         .level  = 1,
410                         .server = NULL
411                 },{
412                         .level  = 1,
413                         .server = ""
414                 },{
415                         .level  = 78,
416                         .server = ""
417                 },{
418                         .level  = 1,
419                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
420                 },{
421                         .level  = 1024,
422                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
423                 }
424         };
425         int i;
426         uint32_t needed;
427
428         for (i=0;i<ARRAY_SIZE(levels);i++) {
429                 int level = levels[i].level;
430                 DATA_BLOB blob;
431
432                 r.in.server             = levels[i].server;
433                 r.in.environment        = environment;
434                 r.in.level              = level;
435                 r.in.buffer             = NULL;
436                 r.in.offered            = 0;
437                 r.out.needed            = &needed;
438
439                 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
440
441                 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
442                 torture_assert_ntstatus_ok(tctx, status,
443                         "dcerpc_spoolss_GetPrinterDriverDirectory failed");
444                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
445                         "GetPrinterDriverDirectory unexpected return code");
446
447                 blob = data_blob_talloc_zero(tctx, needed);
448                 r.in.buffer = &blob;
449                 r.in.offered = needed;
450
451                 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
452                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
453
454                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
455
456                 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
457         }
458
459         return true;
460 }
461
462 static bool test_EnumPrinterDrivers_args(struct torture_context *tctx,
463                                          struct dcerpc_binding_handle *b,
464                                          const char *server_name,
465                                          const char *environment,
466                                          uint32_t level,
467                                          uint32_t *count_p,
468                                          union spoolss_DriverInfo **info_p)
469 {
470         struct spoolss_EnumPrinterDrivers r;
471         uint32_t needed;
472         uint32_t count;
473         union spoolss_DriverInfo *info;
474
475         r.in.server             = server_name;
476         r.in.environment        = environment;
477         r.in.level              = level;
478         r.in.buffer             = NULL;
479         r.in.offered            = 0;
480         r.out.needed            = &needed;
481         r.out.count             = &count;
482         r.out.info              = &info;
483
484         torture_comment(tctx, "Testing EnumPrinterDrivers(%s) level %u\n",
485                 r.in.environment, r.in.level);
486
487         torture_assert_ntstatus_ok(tctx,
488                 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
489                 "EnumPrinterDrivers failed");
490         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
491                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
492                 r.in.buffer = &blob;
493                 r.in.offered = needed;
494
495                 torture_assert_ntstatus_ok(tctx,
496                         dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
497                         "EnumPrinterDrivers failed");
498         }
499
500         torture_assert_werr_ok(tctx, r.out.result,
501                 "EnumPrinterDrivers failed");
502
503         if (count_p) {
504                 *count_p = count;
505         }
506         if (info_p) {
507                 *info_p = info;
508         }
509
510         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
511
512         return true;
513
514 }
515
516 static bool test_EnumPrinterDrivers_findone(struct torture_context *tctx,
517                                             struct dcerpc_binding_handle *b,
518                                             const char *server_name,
519                                             const char *environment,
520                                             uint32_t level,
521                                             const char *driver_name)
522 {
523         uint32_t count;
524         union spoolss_DriverInfo *info;
525         int i;
526
527         torture_assert(tctx,
528                 test_EnumPrinterDrivers_args(tctx, b, server_name, environment, level, &count, &info),
529                 "failed to enumerate printer drivers");
530
531         for (i=0; i < count; i++) {
532                 const char *driver_name_ret;
533                 switch (level) {
534                 case 1:
535                         driver_name_ret = info[i].info1.driver_name;
536                         break;
537                 case 2:
538                         driver_name_ret = info[i].info2.driver_name;
539                         break;
540                 case 3:
541                         driver_name_ret = info[i].info3.driver_name;
542                         break;
543                 case 4:
544                         driver_name_ret = info[i].info4.driver_name;
545                         break;
546                 case 5:
547                         driver_name_ret = info[i].info5.driver_name;
548                         break;
549                 case 6:
550                         driver_name_ret = info[i].info6.driver_name;
551                         break;
552                 case 7:
553                         driver_name_ret = info[i].info7.driver_name;
554                         break;
555                 case 8:
556                         driver_name_ret = info[i].info8.driver_name;
557                         break;
558                 default:
559                         break;
560                 }
561                 if (strequal(driver_name, driver_name_ret)) {
562                         return true;
563                 }
564         }
565
566         return false;
567 }
568
569 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
570                                     struct dcerpc_pipe *p,
571                                     struct test_spoolss_context *ctx,
572                                     const char *architecture)
573 {
574         struct dcerpc_binding_handle *b = p->binding_handle;
575         uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
576         int i, j;
577
578         /* FIXME: gd, come back and fix "" as server, and handle
579          * priority of returned error codes in torture test and samba 3
580          * server */
581         const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
582
583         for (i=0;i<ARRAY_SIZE(levels);i++) {
584                 int level = levels[i];
585                 uint32_t count;
586                 union spoolss_DriverInfo *info;
587
588                 torture_assert(tctx,
589                         test_EnumPrinterDrivers_args(tctx, b, server_name, architecture, level, &count, &info),
590                         "failed to enumerate drivers");
591
592                 ctx->driver_count[level]        = count;
593                 ctx->drivers[level]             = info;
594         }
595
596         for (i=1;i<ARRAY_SIZE(levels);i++) {
597                 int level = levels[i];
598                 int old_level = levels[i-1];
599
600                 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
601                         "EnumPrinterDrivers invalid value");
602         }
603
604         for (i=0;i<ARRAY_SIZE(levels);i++) {
605                 int level = levels[i];
606
607                 for (j=0;j<ctx->driver_count[level];j++) {
608                         union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
609                         union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
610
611                         switch (level) {
612                         case 1:
613                                 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
614                                 break;
615                         case 2:
616                                 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
617                                 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
618                                 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
619                                 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
620                                 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
621                                 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
622                                 break;
623                         case 3:
624                                 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
625                                 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
626                                 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
627                                 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
628                                 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
629                                 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
630                                 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
631                                 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
632                                 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
633                                 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
634                                 break;
635                         case 4:
636                                 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
637                                 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
638                                 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
639                                 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
640                                 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
641                                 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
642                                 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
643                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
644                                 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
645                                 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
646                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
647                                 break;
648                         case 5:
649                                 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
650                                 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
651                                 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
652                                 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
653                                 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
654                                 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
655                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
656                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
657                                 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
658                                 break;
659                         case 6:
660                                 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
661                                 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
662                                 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
663                                 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
664                                 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
665                                 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
666                                 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
667                                 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
668                                 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
669                                 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
670                                 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
671                                 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
672                                 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
673                                 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
674                                 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
675                                 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
676                                 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
677                                 break;
678                         case 8:
679                                 /* level 8 is our reference, and it makes no sense to compare it to itself */
680                                 break;
681                         }
682                 }
683         }
684
685         return true;
686 }
687
688 static bool test_EnumMonitors(struct torture_context *tctx,
689                               struct dcerpc_binding_handle *b,
690                               struct test_spoolss_context *ctx)
691 {
692         NTSTATUS status;
693         struct spoolss_EnumMonitors r;
694         uint16_t levels[] = { 1, 2 };
695         int i, j;
696
697         for (i=0;i<ARRAY_SIZE(levels);i++) {
698                 int level = levels[i];
699                 DATA_BLOB blob;
700                 uint32_t needed;
701                 uint32_t count;
702                 union spoolss_MonitorInfo *info;
703
704                 r.in.servername = "";
705                 r.in.level = level;
706                 r.in.buffer = NULL;
707                 r.in.offered = 0;
708                 r.out.needed = &needed;
709                 r.out.count = &count;
710                 r.out.info = &info;
711
712                 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
713
714                 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
715                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
716                 if (W_ERROR_IS_OK(r.out.result)) {
717                         /* TODO: do some more checks here */
718                         continue;
719                 }
720                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
721                         "EnumMonitors failed");
722
723                 blob = data_blob_talloc_zero(ctx, needed);
724                 r.in.buffer = &blob;
725                 r.in.offered = needed;
726
727                 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
728                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
729
730                 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
731
732                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
733
734                 ctx->monitor_count[level]       = count;
735                 ctx->monitors[level]            = info;
736         }
737
738         for (i=1;i<ARRAY_SIZE(levels);i++) {
739                 int level = levels[i];
740                 int old_level = levels[i-1];
741                 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
742                                          "EnumMonitors invalid value");
743         }
744
745         for (i=0;i<ARRAY_SIZE(levels);i++) {
746                 int level = levels[i];
747                 for (j=0;j<ctx->monitor_count[level];j++) {
748                         union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
749                         union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
750                         switch (level) {
751                         case 1:
752                                 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
753                                 break;
754                         case 2:
755                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
756                                 break;
757                         }
758                 }
759         }
760
761         return true;
762 }
763
764 static bool test_EnumPrintProcessors(struct torture_context *tctx,
765                                      struct dcerpc_binding_handle *b,
766                                      struct test_spoolss_context *ctx,
767                                      const char *environment)
768 {
769         NTSTATUS status;
770         struct spoolss_EnumPrintProcessors r;
771         uint16_t levels[] = { 1 };
772         int i, j;
773
774         for (i=0;i<ARRAY_SIZE(levels);i++) {
775                 int level = levels[i];
776                 DATA_BLOB blob;
777                 uint32_t needed;
778                 uint32_t count;
779                 union spoolss_PrintProcessorInfo *info;
780
781                 r.in.servername = "";
782                 r.in.environment = environment;
783                 r.in.level = level;
784                 r.in.buffer = NULL;
785                 r.in.offered = 0;
786                 r.out.needed = &needed;
787                 r.out.count = &count;
788                 r.out.info = &info;
789
790                 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
791
792                 status = dcerpc_spoolss_EnumPrintProcessors_r(b, ctx, &r);
793                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
794                 if (W_ERROR_IS_OK(r.out.result)) {
795                         /* TODO: do some more checks here */
796                         continue;
797                 }
798                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
799                         "EnumPrintProcessors unexpected return code");
800
801                 blob = data_blob_talloc_zero(ctx, needed);
802                 r.in.buffer = &blob;
803                 r.in.offered = needed;
804
805                 status = dcerpc_spoolss_EnumPrintProcessors_r(b, ctx, &r);
806                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
807
808                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
809
810                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
811
812                 ctx->print_processor_count[level]       = count;
813                 ctx->print_processors[level]            = info;
814         }
815
816         for (i=1;i<ARRAY_SIZE(levels);i++) {
817                 int level = levels[i];
818                 int old_level = levels[i-1];
819                 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
820                         "EnumPrintProcessors failed");
821         }
822
823         for (i=0;i<ARRAY_SIZE(levels);i++) {
824                 int level = levels[i];
825                 for (j=0;j<ctx->print_processor_count[level];j++) {
826 #if 0
827                         union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
828                         union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
829 #endif
830                         switch (level) {
831                         case 1:
832                                 /* level 1 is our reference, and it makes no sense to compare it to itself */
833                                 break;
834                         }
835                 }
836         }
837
838         return true;
839 }
840
841 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
842                                         struct dcerpc_binding_handle *b)
843 {
844         NTSTATUS status;
845         struct spoolss_EnumPrintProcDataTypes r;
846         uint16_t levels[] = { 1 };
847         int i;
848
849         for (i=0;i<ARRAY_SIZE(levels);i++) {
850                 int level = levels[i];
851                 DATA_BLOB blob;
852                 uint32_t needed;
853                 uint32_t count;
854                 union spoolss_PrintProcDataTypesInfo *info;
855
856                 r.in.servername = "";
857                 r.in.print_processor_name = "winprint";
858                 r.in.level = level;
859                 r.in.buffer = NULL;
860                 r.in.offered = 0;
861                 r.out.needed = &needed;
862                 r.out.count = &count;
863                 r.out.info = &info;
864
865                 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
866
867                 status = dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r);
868                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
869                 if (W_ERROR_IS_OK(r.out.result)) {
870                         /* TODO: do some more checks here */
871                         continue;
872                 }
873                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
874                         "EnumPrintProcDataTypes unexpected return code");
875
876                 blob = data_blob_talloc_zero(tctx, needed);
877                 r.in.buffer = &blob;
878                 r.in.offered = needed;
879
880                 status = dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r);
881                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
882
883                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
884
885                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
886
887         }
888
889         return true;
890 }
891
892
893 static bool test_EnumPrinters(struct torture_context *tctx,
894                               struct dcerpc_binding_handle *b,
895                               struct test_spoolss_context *ctx)
896 {
897         struct spoolss_EnumPrinters r;
898         NTSTATUS status;
899         uint16_t levels[] = { 0, 1, 2, 4, 5 };
900         int i, j;
901
902         for (i=0;i<ARRAY_SIZE(levels);i++) {
903                 int level = levels[i];
904                 DATA_BLOB blob;
905                 uint32_t needed;
906                 uint32_t count;
907                 union spoolss_PrinterInfo *info;
908
909                 r.in.flags      = PRINTER_ENUM_LOCAL;
910                 r.in.server     = "";
911                 r.in.level      = level;
912                 r.in.buffer     = NULL;
913                 r.in.offered    = 0;
914                 r.out.needed    = &needed;
915                 r.out.count     = &count;
916                 r.out.info      = &info;
917
918                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
919
920                 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
921                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
922                 if (W_ERROR_IS_OK(r.out.result)) {
923                         /* TODO: do some more checks here */
924                         continue;
925                 }
926                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
927                         "EnumPrinters unexpected return code");
928
929                 blob = data_blob_talloc_zero(ctx, needed);
930                 r.in.buffer = &blob;
931                 r.in.offered = needed;
932
933                 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
934                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
935
936                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
937
938                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
939
940                 ctx->printer_count[level]       = count;
941                 ctx->printers[level]            = info;
942         }
943
944         for (i=1;i<ARRAY_SIZE(levels);i++) {
945                 int level = levels[i];
946                 int old_level = levels[i-1];
947                 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
948                                          "EnumPrinters invalid value");
949         }
950
951         for (i=0;i<ARRAY_SIZE(levels);i++) {
952                 int level = levels[i];
953                 for (j=0;j<ctx->printer_count[level];j++) {
954                         union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
955                         union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
956                         switch (level) {
957                         case 0:
958                                 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
959                                 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
960                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
961                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
962                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
963                                 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
964                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
965                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
966                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
967                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
968                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
969                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
970                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
971                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
972                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
973                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
974                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
975                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
976                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
977                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
978                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
979                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
980                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
981                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
982                                 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
983                                 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
984                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
985                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
986                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
987                                 break;
988                         case 1:
989                                 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
990                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
991                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
992                                 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
993                                 break;
994                         case 2:
995                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
996                                 break;
997                         case 4:
998                                 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
999                                 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
1000                                 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
1001                                 break;
1002                         case 5:
1003                                 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
1004                                 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
1005                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
1006                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
1007                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
1008                                 break;
1009                         }
1010                 }
1011         }
1012
1013         /* TODO:
1014          *      - verify that the port of a printer was in the list returned by EnumPorts
1015          */
1016
1017         return true;
1018 }
1019
1020 static bool test_GetPrinterDriver2(struct torture_context *tctx,
1021                                    struct dcerpc_binding_handle *b,
1022                                    struct policy_handle *handle,
1023                                    const char *driver_name,
1024                                    const char *environment);
1025
1026 bool test_GetPrinter_level(struct torture_context *tctx,
1027                            struct dcerpc_binding_handle *b,
1028                            struct policy_handle *handle,
1029                            uint32_t level,
1030                            union spoolss_PrinterInfo *info)
1031 {
1032         struct spoolss_GetPrinter r;
1033         uint32_t needed;
1034
1035         r.in.handle = handle;
1036         r.in.level = level;
1037         r.in.buffer = NULL;
1038         r.in.offered = 0;
1039         r.out.needed = &needed;
1040
1041         torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
1042
1043         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1044                 "GetPrinter failed");
1045
1046         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1047                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
1048                 r.in.buffer = &blob;
1049                 r.in.offered = needed;
1050
1051                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1052                         "GetPrinter failed");
1053         }
1054
1055         torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
1056
1057         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
1058
1059         if (info && r.out.info) {
1060                 *info = *r.out.info;
1061         }
1062
1063         return true;
1064 }
1065
1066
1067 static bool test_GetPrinter(struct torture_context *tctx,
1068                             struct dcerpc_binding_handle *b,
1069                             struct policy_handle *handle,
1070                             const char *environment)
1071 {
1072         uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1073         int i;
1074
1075         for (i=0;i<ARRAY_SIZE(levels);i++) {
1076
1077                 union spoolss_PrinterInfo info;
1078
1079                 ZERO_STRUCT(info);
1080
1081                 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
1082                         "failed to call GetPrinter");
1083
1084                 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
1085                         torture_assert(tctx,
1086                                 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
1087                                 "failed to call test_GetPrinterDriver2");
1088                 }
1089         }
1090
1091         return true;
1092 }
1093
1094 static bool test_SetPrinter(struct torture_context *tctx,
1095                             struct dcerpc_binding_handle *b,
1096                             struct policy_handle *handle,
1097                             struct spoolss_SetPrinterInfoCtr *info_ctr,
1098                             struct spoolss_DevmodeContainer *devmode_ctr,
1099                             struct sec_desc_buf *secdesc_ctr,
1100                             enum spoolss_PrinterControl command)
1101 {
1102         struct spoolss_SetPrinter r;
1103
1104         r.in.handle = handle;
1105         r.in.info_ctr = info_ctr;
1106         r.in.devmode_ctr = devmode_ctr;
1107         r.in.secdesc_ctr = secdesc_ctr;
1108         r.in.command = command;
1109
1110         torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1111
1112         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1113                 "failed to call SetPrinter");
1114         torture_assert_werr_ok(tctx, r.out.result,
1115                 "failed to call SetPrinter");
1116
1117         return true;
1118 }
1119
1120 static bool test_SetPrinter_errors(struct torture_context *tctx,
1121                                    struct dcerpc_binding_handle *b,
1122                                    struct policy_handle *handle)
1123 {
1124         struct spoolss_SetPrinter r;
1125         uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1126         int i;
1127
1128         struct spoolss_SetPrinterInfoCtr info_ctr;
1129         struct spoolss_DevmodeContainer devmode_ctr;
1130         struct sec_desc_buf secdesc_ctr;
1131
1132         info_ctr.level = 0;
1133         info_ctr.info.info0 = NULL;
1134
1135         ZERO_STRUCT(devmode_ctr);
1136         ZERO_STRUCT(secdesc_ctr);
1137
1138         r.in.handle = handle;
1139         r.in.info_ctr = &info_ctr;
1140         r.in.devmode_ctr = &devmode_ctr;
1141         r.in.secdesc_ctr = &secdesc_ctr;
1142         r.in.command = 0;
1143
1144         torture_comment(tctx, "Testing SetPrinter all zero\n");
1145
1146         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1147                 "failed to call SetPrinter");
1148         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1149                 "failed to call SetPrinter");
1150
1151  again:
1152         for (i=0; i < ARRAY_SIZE(levels); i++) {
1153
1154                 struct spoolss_SetPrinterInfo0 info0;
1155                 struct spoolss_SetPrinterInfo1 info1;
1156                 struct spoolss_SetPrinterInfo2 info2;
1157                 struct spoolss_SetPrinterInfo3 info3;
1158                 struct spoolss_SetPrinterInfo4 info4;
1159                 struct spoolss_SetPrinterInfo5 info5;
1160                 struct spoolss_SetPrinterInfo6 info6;
1161                 struct spoolss_SetPrinterInfo7 info7;
1162                 struct spoolss_SetPrinterInfo8 info8;
1163                 struct spoolss_SetPrinterInfo9 info9;
1164
1165
1166                 info_ctr.level = levels[i];
1167                 switch (levels[i]) {
1168                 case 0:
1169                         ZERO_STRUCT(info0);
1170                         info_ctr.info.info0 = &info0;
1171                         break;
1172                 case 1:
1173                         ZERO_STRUCT(info1);
1174                         info_ctr.info.info1 = &info1;
1175                         break;
1176                 case 2:
1177                         ZERO_STRUCT(info2);
1178                         info_ctr.info.info2 = &info2;
1179                         break;
1180                 case 3:
1181                         ZERO_STRUCT(info3);
1182                         info_ctr.info.info3 = &info3;
1183                         break;
1184                 case 4:
1185                         ZERO_STRUCT(info4);
1186                         info_ctr.info.info4 = &info4;
1187                         break;
1188                 case 5:
1189                         ZERO_STRUCT(info5);
1190                         info_ctr.info.info5 = &info5;
1191                         break;
1192                 case 6:
1193                         ZERO_STRUCT(info6);
1194                         info_ctr.info.info6 = &info6;
1195                         break;
1196                 case 7:
1197                         ZERO_STRUCT(info7);
1198                         info_ctr.info.info7 = &info7;
1199                         break;
1200                 case 8:
1201                         ZERO_STRUCT(info8);
1202                         info_ctr.info.info8 = &info8;
1203                         break;
1204                 case 9:
1205                         ZERO_STRUCT(info9);
1206                         info_ctr.info.info9 = &info9;
1207                         break;
1208                 }
1209
1210                 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1211                         info_ctr.level, r.in.command);
1212
1213                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1214                         "failed to call SetPrinter");
1215
1216                 switch (r.in.command) {
1217                 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1218                         /* is ignored for all levels other then 0 */
1219                         if (info_ctr.level > 0) {
1220                                 /* ignored then */
1221                                 break;
1222                         }
1223                 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1224                 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1225                 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1226                         if (info_ctr.level > 0) {
1227                                 /* is invalid for all levels other then 0 */
1228                                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1229                                         "unexpected error code returned");
1230                                 continue;
1231                         } else {
1232                                 torture_assert_werr_ok(tctx, r.out.result,
1233                                         "failed to call SetPrinter with non 0 command");
1234                                 continue;
1235                         }
1236                         break;
1237
1238                 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1239                         /* FIXME: gd needs further investigation */
1240                 default:
1241                         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1242                                 "unexpected error code returned");
1243                         continue;
1244                 }
1245
1246                 switch (info_ctr.level) {
1247                 case 1:
1248                         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1249                                 "unexpected error code returned");
1250                         break;
1251                 case 2:
1252                         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1253                                 "unexpected error code returned");
1254                         break;
1255                 case 3:
1256                 case 4:
1257                 case 5:
1258                 case 7:
1259                         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1260                                 "unexpected error code returned");
1261                         break;
1262                 case 9:
1263                         torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1264                                 "unexpected error code returned");
1265                         break;
1266                 default:
1267                         torture_assert_werr_ok(tctx, r.out.result,
1268                                 "failed to call SetPrinter");
1269                         break;
1270                 }
1271         }
1272
1273         if (r.in.command < 5) {
1274                 r.in.command++;
1275                 goto again;
1276         }
1277
1278         return true;
1279 }
1280
1281 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1282 {
1283         if ((r->level == 2) && (r->info.info2)) {
1284                 r->info.info2->secdesc_ptr = 0;
1285                 r->info.info2->devmode_ptr = 0;
1286         }
1287 }
1288
1289 static bool test_PrinterInfo(struct torture_context *tctx,
1290                              struct dcerpc_binding_handle *b,
1291                              struct policy_handle *handle)
1292 {
1293         NTSTATUS status;
1294         struct spoolss_SetPrinter s;
1295         struct spoolss_GetPrinter q;
1296         struct spoolss_GetPrinter q0;
1297         struct spoolss_SetPrinterInfoCtr info_ctr;
1298         union spoolss_PrinterInfo info;
1299         struct spoolss_DevmodeContainer devmode_ctr;
1300         struct sec_desc_buf secdesc_ctr;
1301         uint32_t needed;
1302         bool ret = true;
1303         int i;
1304
1305         uint32_t status_list[] = {
1306                 /* these do not stick
1307                 PRINTER_STATUS_PAUSED,
1308                 PRINTER_STATUS_ERROR,
1309                 PRINTER_STATUS_PENDING_DELETION, */
1310                 PRINTER_STATUS_PAPER_JAM,
1311                 PRINTER_STATUS_PAPER_OUT,
1312                 PRINTER_STATUS_MANUAL_FEED,
1313                 PRINTER_STATUS_PAPER_PROBLEM,
1314                 PRINTER_STATUS_OFFLINE,
1315                 PRINTER_STATUS_IO_ACTIVE,
1316                 PRINTER_STATUS_BUSY,
1317                 PRINTER_STATUS_PRINTING,
1318                 PRINTER_STATUS_OUTPUT_BIN_FULL,
1319                 PRINTER_STATUS_NOT_AVAILABLE,
1320                 PRINTER_STATUS_WAITING,
1321                 PRINTER_STATUS_PROCESSING,
1322                 PRINTER_STATUS_INITIALIZING,
1323                 PRINTER_STATUS_WARMING_UP,
1324                 PRINTER_STATUS_TONER_LOW,
1325                 PRINTER_STATUS_NO_TONER,
1326                 PRINTER_STATUS_PAGE_PUNT,
1327                 PRINTER_STATUS_USER_INTERVENTION,
1328                 PRINTER_STATUS_OUT_OF_MEMORY,
1329                 PRINTER_STATUS_DOOR_OPEN,
1330                 PRINTER_STATUS_SERVER_UNKNOWN,
1331                 PRINTER_STATUS_POWER_SAVE,
1332                 /* these do not stick
1333                 0x02000000,
1334                 0x04000000,
1335                 0x08000000,
1336                 0x10000000,
1337                 0x20000000,
1338                 0x40000000,
1339                 0x80000000 */
1340         };
1341         uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1342         uint32_t attribute_list[] = {
1343                 PRINTER_ATTRIBUTE_QUEUED,
1344                 /* fails with WERR_INVALID_DATATYPE:
1345                 PRINTER_ATTRIBUTE_DIRECT, */
1346                 /* does not stick
1347                 PRINTER_ATTRIBUTE_DEFAULT, */
1348                 PRINTER_ATTRIBUTE_SHARED,
1349                 /* does not stick
1350                 PRINTER_ATTRIBUTE_NETWORK, */
1351                 PRINTER_ATTRIBUTE_HIDDEN,
1352                 PRINTER_ATTRIBUTE_LOCAL,
1353                 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1354                 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1355                 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1356                 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1357                 /* does not stick
1358                 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1359                 /* fails with WERR_INVALID_DATATYPE:
1360                 PRINTER_ATTRIBUTE_RAW_ONLY, */
1361                 /* these do not stick
1362                 PRINTER_ATTRIBUTE_PUBLISHED,
1363                 PRINTER_ATTRIBUTE_FAX,
1364                 PRINTER_ATTRIBUTE_TS,
1365                 0x00010000,
1366                 0x00020000,
1367                 0x00040000,
1368                 0x00080000,
1369                 0x00100000,
1370                 0x00200000,
1371                 0x00400000,
1372                 0x00800000,
1373                 0x01000000,
1374                 0x02000000,
1375                 0x04000000,
1376                 0x08000000,
1377                 0x10000000,
1378                 0x20000000,
1379                 0x40000000,
1380                 0x80000000 */
1381         };
1382
1383         ZERO_STRUCT(devmode_ctr);
1384         ZERO_STRUCT(secdesc_ctr);
1385
1386         s.in.handle = handle;
1387         s.in.command = 0;
1388         s.in.info_ctr = &info_ctr;
1389         s.in.devmode_ctr = &devmode_ctr;
1390         s.in.secdesc_ctr = &secdesc_ctr;
1391
1392         q.in.handle = handle;
1393         q.out.info = &info;
1394         q0 = q;
1395
1396 #define TESTGETCALL(call, r) \
1397                 r.in.buffer = NULL; \
1398                 r.in.offered = 0;\
1399                 r.out.needed = &needed; \
1400                 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1401                 if (!NT_STATUS_IS_OK(status)) { \
1402                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1403                                r.in.level, nt_errstr(status), __location__); \
1404                         ret = false; \
1405                         break; \
1406                 }\
1407                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1408                         DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1409                         r.in.buffer = &blob; \
1410                         r.in.offered = needed; \
1411                 }\
1412                 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1413                 if (!NT_STATUS_IS_OK(status)) { \
1414                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1415                                r.in.level, nt_errstr(status), __location__); \
1416                         ret = false; \
1417                         break; \
1418                 } \
1419                 if (!W_ERROR_IS_OK(r.out.result)) { \
1420                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1421                                r.in.level, win_errstr(r.out.result), __location__); \
1422                         ret = false; \
1423                         break; \
1424                 }
1425
1426
1427 #define TESTSETCALL_EXP(call, r, err) \
1428                 clear_info2(&info_ctr);\
1429                 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1430                 if (!NT_STATUS_IS_OK(status)) { \
1431                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1432                                r.in.info_ctr->level, nt_errstr(status), __location__); \
1433                         ret = false; \
1434                         break; \
1435                 } \
1436                 if (!W_ERROR_IS_OK(err)) { \
1437                         if (!W_ERROR_EQUAL(err, r.out.result)) { \
1438                                 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1439                                        r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1440                                 ret = false; \
1441                         } \
1442                         break; \
1443                 } \
1444                 if (!W_ERROR_IS_OK(r.out.result)) { \
1445                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1446                                r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1447                         ret = false; \
1448                         break; \
1449                 }
1450
1451 #define TESTSETCALL(call, r) \
1452         TESTSETCALL_EXP(call, r, WERR_OK)
1453
1454 #define STRING_EQUAL(s1, s2, field) \
1455                 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1456                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1457                                #field, s2, __location__); \
1458                         ret = false; \
1459                         break; \
1460                 }
1461
1462 #define MEM_EQUAL(s1, s2, length, field) \
1463                 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1464                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1465                                #field, (const char *)s2, __location__); \
1466                         ret = false; \
1467                         break; \
1468                 }
1469
1470 #define INT_EQUAL(i1, i2, field) \
1471                 if (i1 != i2) { \
1472                         torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1473                                #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1474                         ret = false; \
1475                         break; \
1476                 }
1477
1478 #define SD_EQUAL(sd1, sd2, field) \
1479                 if (!security_descriptor_equal(sd1, sd2)) { \
1480                         torture_comment(tctx, "Failed to set %s (%s)\n", \
1481                                #field, __location__); \
1482                         ret = false; \
1483                         break; \
1484                 }
1485
1486 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1487                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1488                 q.in.level = lvl1; \
1489                 TESTGETCALL(GetPrinter, q) \
1490                 info_ctr.level = lvl1; \
1491                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1492                 info_ctr.info.info ## lvl1->field1 = value;\
1493                 TESTSETCALL_EXP(SetPrinter, s, err) \
1494                 info_ctr.info.info ## lvl1->field1 = ""; \
1495                 TESTGETCALL(GetPrinter, q) \
1496                 info_ctr.info.info ## lvl1->field1 = value; \
1497                 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1498                 q.in.level = lvl2; \
1499                 TESTGETCALL(GetPrinter, q) \
1500                 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1501                 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1502         } while (0)
1503
1504 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1505         TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1506         } while (0);
1507
1508 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1509                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1510                 q.in.level = lvl1; \
1511                 TESTGETCALL(GetPrinter, q) \
1512                 info_ctr.level = lvl1; \
1513                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1514                 info_ctr.info.info ## lvl1->field1 = value; \
1515                 TESTSETCALL(SetPrinter, s) \
1516                 info_ctr.info.info ## lvl1->field1 = 0; \
1517                 TESTGETCALL(GetPrinter, q) \
1518                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1519                 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1520                 q.in.level = lvl2; \
1521                 TESTGETCALL(GetPrinter, q) \
1522                 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1523                 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1524         } while (0)
1525
1526 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1527         TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1528         } while (0)
1529
1530         q0.in.level = 0;
1531         do { TESTGETCALL(GetPrinter, q0) } while (0);
1532
1533         TEST_PRINTERINFO_STRING(2, comment,  1, comment, "xx2-1 comment");
1534         TEST_PRINTERINFO_STRING(2, comment,  2, comment, "xx2-2 comment");
1535
1536         /* level 0 printername does not stick */
1537 /*      TEST_PRINTERINFO_STRING(2, printername,  0, printername, "xx2-0 printer"); */
1538         TEST_PRINTERINFO_STRING(2, printername,  1, name,        "xx2-1 printer");
1539         TEST_PRINTERINFO_STRING(2, printername,  2, printername, "xx2-2 printer");
1540         TEST_PRINTERINFO_STRING(2, printername,  4, printername, "xx2-4 printer");
1541         TEST_PRINTERINFO_STRING(2, printername,  5, printername, "xx2-5 printer");
1542 /*      TEST_PRINTERINFO_STRING(4, printername,  0, printername, "xx4-0 printer"); */
1543         TEST_PRINTERINFO_STRING(4, printername,  1, name,        "xx4-1 printer");
1544         TEST_PRINTERINFO_STRING(4, printername,  2, printername, "xx4-2 printer");
1545         TEST_PRINTERINFO_STRING(4, printername,  4, printername, "xx4-4 printer");
1546         TEST_PRINTERINFO_STRING(4, printername,  5, printername, "xx4-5 printer");
1547 /*      TEST_PRINTERINFO_STRING(5, printername,  0, printername, "xx5-0 printer"); */
1548         TEST_PRINTERINFO_STRING(5, printername,  1, name,        "xx5-1 printer");
1549         TEST_PRINTERINFO_STRING(5, printername,  2, printername, "xx5-2 printer");
1550         TEST_PRINTERINFO_STRING(5, printername,  4, printername, "xx5-4 printer");
1551         TEST_PRINTERINFO_STRING(5, printername,  5, printername, "xx5-5 printer");
1552
1553         /* servername can be set but does not stick
1554         TEST_PRINTERINFO_STRING(2, servername,  0, servername, "xx2-0 servername");
1555         TEST_PRINTERINFO_STRING(2, servername,  2, servername, "xx2-2 servername");
1556         TEST_PRINTERINFO_STRING(2, servername,  4, servername, "xx2-4 servername");
1557         */
1558
1559         /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1560         TEST_PRINTERINFO_STRING_EXP_ERR(2, portname,  2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1561         TEST_PRINTERINFO_STRING_EXP_ERR(2, portname,  5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1562         TEST_PRINTERINFO_STRING_EXP_ERR(5, portname,  2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1563         TEST_PRINTERINFO_STRING_EXP_ERR(5, portname,  5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1564
1565         TEST_PRINTERINFO_STRING(2, sharename,   2, sharename,   "xx2-2 sharename");
1566         /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1567         TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername,  2, drivername,  "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1568         TEST_PRINTERINFO_STRING(2, location,    2, location,    "xx2-2 location");
1569         /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1570         TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile,     2, sepfile,     "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1571         /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1572         TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1573         TEST_PRINTERINFO_STRING(2, datatype,    2, datatype,    "xx2-2 datatype");
1574         TEST_PRINTERINFO_STRING(2, parameters,  2, parameters,  "xx2-2 parameters");
1575
1576         for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1577 /*              TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1578                         attribute_list[i],
1579                         (attribute_list[i] | default_attribute)
1580                         ); */
1581                 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1582                         attribute_list[i],
1583                         (attribute_list[i] | default_attribute)
1584                         );
1585                 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1586                         attribute_list[i],
1587                         (attribute_list[i] | default_attribute)
1588                         );
1589                 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1590                         attribute_list[i],
1591                         (attribute_list[i] | default_attribute)
1592                         );
1593 /*              TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1594                         attribute_list[i],
1595                         (attribute_list[i] | default_attribute)
1596                         ); */
1597                 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1598                         attribute_list[i],
1599                         (attribute_list[i] | default_attribute)
1600                         );
1601                 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1602                         attribute_list[i],
1603                         (attribute_list[i] | default_attribute)
1604                         );
1605                 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1606                         attribute_list[i],
1607                         (attribute_list[i] | default_attribute)
1608                         );
1609 /*              TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1610                         attribute_list[i],
1611                         (attribute_list[i] | default_attribute)
1612                         ); */
1613                 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1614                         attribute_list[i],
1615                         (attribute_list[i] | default_attribute)
1616                         );
1617                 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1618                         attribute_list[i],
1619                         (attribute_list[i] | default_attribute)
1620                         );
1621                 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1622                         attribute_list[i],
1623                         (attribute_list[i] | default_attribute)
1624                         );
1625         }
1626
1627         for (i=0; i < ARRAY_SIZE(status_list); i++) {
1628                 /* level 2 sets do not stick
1629                 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1630                 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1631                 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1632                 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1633                 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1634                 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1635         }
1636
1637         /* priorities need to be between 0 and 99
1638            passing an invalid priority will result in WERR_INVALID_PRIORITY */
1639         TEST_PRINTERINFO_INT(2, priority,       2, priority, 0);
1640         TEST_PRINTERINFO_INT(2, priority,       2, priority, 1);
1641         TEST_PRINTERINFO_INT(2, priority,       2, priority, 99);
1642         /* TEST_PRINTERINFO_INT(2, priority,    2, priority, 100); */
1643         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1644         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1645         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1646         /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1647
1648         TEST_PRINTERINFO_INT(2, starttime,      2, starttime, __LINE__);
1649         TEST_PRINTERINFO_INT(2, untiltime,      2, untiltime, __LINE__);
1650
1651         /* does not stick
1652         TEST_PRINTERINFO_INT(2, cjobs,          2, cjobs, __LINE__);
1653         TEST_PRINTERINFO_INT(2, averageppm,     2, averageppm, __LINE__); */
1654
1655         /* does not stick
1656         TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1657         TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1658
1659         /* FIXME: gd also test devmode and secdesc behavior */
1660
1661         {
1662                 /* verify composition of level 1 description field */
1663                 const char *description;
1664                 const char *tmp;
1665
1666                 q0.in.level = 1;
1667                 do { TESTGETCALL(GetPrinter, q0) } while (0);
1668
1669                 description = talloc_strdup(tctx, q0.out.info->info1.description);
1670
1671                 q0.in.level = 2;
1672                 do { TESTGETCALL(GetPrinter, q0) } while (0);
1673
1674                 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1675                         q0.out.info->info2.printername,
1676                         q0.out.info->info2.drivername,
1677                         q0.out.info->info2.location);
1678
1679                 do { STRING_EQUAL(description, tmp, "description")} while (0);
1680         }
1681
1682         return ret;
1683 }
1684
1685 #define torture_assert_sid_equal(torture_ctx,got,expected,cmt)\
1686         do { struct dom_sid *__got = (got), *__expected = (expected); \
1687         if (!dom_sid_equal(__got, __expected)) { \
1688                 torture_result(torture_ctx, TORTURE_FAIL, \
1689                                            __location__": "#got" was %s, expected %s: %s", \
1690                                            dom_sid_string(torture_ctx, __got), dom_sid_string(torture_ctx, __expected), cmt); \
1691                 return false; \
1692         } \
1693         } while(0)
1694
1695 static bool test_security_descriptor_equal(struct torture_context *tctx,
1696                                            const struct security_descriptor *sd1,
1697                                            const struct security_descriptor *sd2)
1698 {
1699         if (sd1 == sd2) {
1700                 return true;
1701         }
1702
1703         if (!sd1 || !sd2) {
1704                 torture_comment(tctx, "%s\n", __location__);
1705                 return false;
1706         }
1707
1708         torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1709         torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1710
1711         torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1712         torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1713
1714         if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1715                 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1716                 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1717                 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1718                 return false;
1719         }
1720         if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1721                 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1722                 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1723                 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1724                 return false;
1725         }
1726
1727         return true;
1728 }
1729
1730 static bool test_sd_set_level(struct torture_context *tctx,
1731                               struct dcerpc_binding_handle *b,
1732                               struct policy_handle *handle,
1733                               uint32_t level,
1734                               struct security_descriptor *sd)
1735 {
1736         struct spoolss_SetPrinterInfoCtr info_ctr;
1737         struct spoolss_DevmodeContainer devmode_ctr;
1738         struct sec_desc_buf secdesc_ctr;
1739         union spoolss_SetPrinterInfo sinfo;
1740
1741         ZERO_STRUCT(devmode_ctr);
1742         ZERO_STRUCT(secdesc_ctr);
1743
1744         switch (level) {
1745         case 2: {
1746                 union spoolss_PrinterInfo info;
1747                 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1748                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1749
1750                 info_ctr.level = 2;
1751                 info_ctr.info = sinfo;
1752
1753                 break;
1754         }
1755         case 3: {
1756                 struct spoolss_SetPrinterInfo3 info3;
1757
1758                 info3.sec_desc_ptr = 0;
1759
1760                 info_ctr.level = 3;
1761                 info_ctr.info.info3 = &info3;
1762
1763                 break;
1764         }
1765         default:
1766                 return false;
1767         }
1768
1769         secdesc_ctr.sd = sd;
1770
1771         torture_assert(tctx,
1772                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1773
1774         return true;
1775 }
1776
1777 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1778                                  struct dcerpc_binding_handle *b,
1779                                  struct policy_handle *handle)
1780 {
1781         union spoolss_PrinterInfo info;
1782         struct security_descriptor *sd1, *sd2;
1783         int i;
1784
1785         /* just compare level 2 and level 3 */
1786
1787         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1788
1789         sd1 = info.info2.secdesc;
1790
1791         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1792
1793         sd2 = info.info3.secdesc;
1794
1795         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1796                 "SD level 2 != SD level 3");
1797
1798
1799         /* query level 2, set level 2, query level 2 */
1800
1801         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1802
1803         sd1 = info.info2.secdesc;
1804
1805         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1806
1807         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1808
1809         sd2 = info.info2.secdesc;
1810         if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1811                 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1812                 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1813         }
1814
1815         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1816                 "SD level 2 != SD level 2 after SD has been set via level 2");
1817
1818
1819         /* query level 2, set level 3, query level 2 */
1820
1821         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1822
1823         sd1 = info.info2.secdesc;
1824
1825         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1826
1827         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1828
1829         sd2 = info.info2.secdesc;
1830
1831         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1832                 "SD level 2 != SD level 2 after SD has been set via level 3");
1833
1834         /* set modified sd level 3, query level 2 */
1835
1836         for (i=0; i < 93; i++) {
1837                 struct security_ace a;
1838                 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1839                 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1840                 a.flags = 0;
1841                 a.size = 0; /* autogenerated */
1842                 a.access_mask = 0;
1843                 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1844                 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1845         }
1846
1847         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1848
1849         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1850         sd2 = info.info2.secdesc;
1851
1852         if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1853                 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1854                 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1855         }
1856
1857         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1858                 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1859
1860
1861         return true;
1862 }
1863
1864 /*
1865  * wrapper call that saves original sd, runs tests, and restores sd
1866  */
1867
1868 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1869                                 struct dcerpc_binding_handle *b,
1870                                 struct policy_handle *handle)
1871 {
1872         union spoolss_PrinterInfo info;
1873         struct security_descriptor *sd;
1874         bool ret = true;
1875
1876         torture_comment(tctx, "Testing Printer Security Descriptors\n");
1877
1878         /* save original sd */
1879
1880         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
1881                 "failed to get initial security descriptor");
1882
1883         sd = security_descriptor_copy(tctx, info.info2.secdesc);
1884
1885         /* run tests */
1886
1887         ret = test_PrinterInfo_SDs(tctx, b, handle);
1888
1889         /* restore original sd */
1890
1891         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
1892                 "failed to restore initial security descriptor");
1893
1894         torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
1895                 ret ? "succeeded" : "failed");
1896
1897
1898         return ret;
1899 }
1900
1901 static bool test_devmode_set_level(struct torture_context *tctx,
1902                                    struct dcerpc_binding_handle *b,
1903                                    struct policy_handle *handle,
1904                                    uint32_t level,
1905                                    struct spoolss_DeviceMode *devmode)
1906 {
1907         struct spoolss_SetPrinterInfoCtr info_ctr;
1908         struct spoolss_DevmodeContainer devmode_ctr;
1909         struct sec_desc_buf secdesc_ctr;
1910         union spoolss_SetPrinterInfo sinfo;
1911
1912         ZERO_STRUCT(devmode_ctr);
1913         ZERO_STRUCT(secdesc_ctr);
1914
1915         switch (level) {
1916         case 2: {
1917                 union spoolss_PrinterInfo info;
1918                 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1919                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1920
1921                 info_ctr.level = 2;
1922                 info_ctr.info = sinfo;
1923
1924                 break;
1925         }
1926         case 8: {
1927                 struct spoolss_SetPrinterInfo8 info8;
1928
1929                 info8.devmode_ptr = 0;
1930
1931                 info_ctr.level = 8;
1932                 info_ctr.info.info8 = &info8;
1933
1934                 break;
1935         }
1936         default:
1937                 return false;
1938         }
1939
1940         devmode_ctr.devmode = devmode;
1941
1942         torture_assert(tctx,
1943                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1944
1945         return true;
1946 }
1947
1948
1949 static bool test_devicemode_equal(struct torture_context *tctx,
1950                                   const struct spoolss_DeviceMode *d1,
1951                                   const struct spoolss_DeviceMode *d2)
1952 {
1953         if (d1 == d2) {
1954                 return true;
1955         }
1956
1957         if (!d1 || !d2) {
1958                 torture_comment(tctx, "%s\n", __location__);
1959                 return false;
1960         }
1961         torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
1962         torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
1963         torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
1964         torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
1965         torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
1966         torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
1967         torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
1968         torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
1969         torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
1970         torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
1971         torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
1972         torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
1973         torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
1974         torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
1975         torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
1976         torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
1977         torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
1978         torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
1979         torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
1980         torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
1981         torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
1982         torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
1983         torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
1984         torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
1985         torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
1986         torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
1987         torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
1988         torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
1989         torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
1990         torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
1991         torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
1992         torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
1993         torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
1994         torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
1995         torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
1996
1997         return true;
1998 }
1999
2000 static bool test_devicemode_full(struct torture_context *tctx,
2001                                  struct dcerpc_binding_handle *b,
2002                                  struct policy_handle *handle)
2003 {
2004         struct spoolss_SetPrinter s;
2005         struct spoolss_GetPrinter q;
2006         struct spoolss_GetPrinter q0;
2007         struct spoolss_SetPrinterInfoCtr info_ctr;
2008         struct spoolss_SetPrinterInfo8 info8;
2009         union spoolss_PrinterInfo info;
2010         struct spoolss_DevmodeContainer devmode_ctr;
2011         struct sec_desc_buf secdesc_ctr;
2012         uint32_t needed;
2013         bool ret = true;
2014         NTSTATUS status;
2015
2016 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
2017                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2018                 q.in.level = lvl1; \
2019                 TESTGETCALL(GetPrinter, q) \
2020                 info_ctr.level = lvl1; \
2021                 if (lvl1 == 2) {\
2022                         info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
2023                 } else if (lvl1 == 8) {\
2024                         info_ctr.info.info ## lvl1 = &info8; \
2025                 }\
2026                 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2027                 devmode_ctr.devmode->field1 = value; \
2028                 TESTSETCALL(SetPrinter, s) \
2029                 TESTGETCALL(GetPrinter, q) \
2030                 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2031                 q.in.level = lvl2; \
2032                 TESTGETCALL(GetPrinter, q) \
2033                 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2034         } while (0)
2035
2036 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2037         TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
2038         } while (0)
2039
2040         ZERO_STRUCT(devmode_ctr);
2041         ZERO_STRUCT(secdesc_ctr);
2042         ZERO_STRUCT(info8);
2043
2044         s.in.handle = handle;
2045         s.in.command = 0;
2046         s.in.info_ctr = &info_ctr;
2047         s.in.devmode_ctr = &devmode_ctr;
2048         s.in.secdesc_ctr = &secdesc_ctr;
2049
2050         q.in.handle = handle;
2051         q.out.info = &info;
2052         q0 = q;
2053
2054 #if 0
2055         const char *devicename;/* [charset(UTF16)] */
2056         enum spoolss_DeviceModeSpecVersion specversion;
2057         uint16_t driverversion;
2058         uint16_t size;
2059         uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2060         uint32_t fields;
2061 #endif
2062
2063         TEST_DEVMODE_INT(8, orientation,        8, orientation, __LINE__);
2064         TEST_DEVMODE_INT(8, papersize,          8, papersize, __LINE__);
2065         TEST_DEVMODE_INT(8, paperlength,        8, paperlength, __LINE__);
2066         TEST_DEVMODE_INT(8, paperwidth,         8, paperwidth, __LINE__);
2067         TEST_DEVMODE_INT(8, scale,              8, scale, __LINE__);
2068         TEST_DEVMODE_INT(8, copies,             8, copies, __LINE__);
2069         TEST_DEVMODE_INT(8, defaultsource,      8, defaultsource, __LINE__);
2070         TEST_DEVMODE_INT(8, printquality,       8, printquality, __LINE__);
2071         TEST_DEVMODE_INT(8, color,              8, color, __LINE__);
2072         TEST_DEVMODE_INT(8, duplex,             8, duplex, __LINE__);
2073         TEST_DEVMODE_INT(8, yresolution,        8, yresolution, __LINE__);
2074         TEST_DEVMODE_INT(8, ttoption,           8, ttoption, __LINE__);
2075         TEST_DEVMODE_INT(8, collate,            8, collate, __LINE__);
2076 #if 0
2077         const char *formname;/* [charset(UTF16)] */
2078 #endif
2079         TEST_DEVMODE_INT(8, logpixels,          8, logpixels, __LINE__);
2080         TEST_DEVMODE_INT(8, bitsperpel,         8, bitsperpel, __LINE__);
2081         TEST_DEVMODE_INT(8, pelswidth,          8, pelswidth, __LINE__);
2082         TEST_DEVMODE_INT(8, pelsheight,         8, pelsheight, __LINE__);
2083         TEST_DEVMODE_INT(8, displayflags,       8, displayflags, __LINE__);
2084         TEST_DEVMODE_INT(8, displayfrequency,   8, displayfrequency, __LINE__);
2085         TEST_DEVMODE_INT(8, icmmethod,          8, icmmethod, __LINE__);
2086         TEST_DEVMODE_INT(8, icmintent,          8, icmintent, __LINE__);
2087         TEST_DEVMODE_INT(8, mediatype,          8, mediatype, __LINE__);
2088         TEST_DEVMODE_INT(8, dithertype,         8, dithertype, __LINE__);
2089         TEST_DEVMODE_INT(8, reserved1,          8, reserved1, __LINE__);
2090         TEST_DEVMODE_INT(8, reserved2,          8, reserved2, __LINE__);
2091         TEST_DEVMODE_INT(8, panningwidth,       8, panningwidth, __LINE__);
2092         TEST_DEVMODE_INT(8, panningheight,      8, panningheight, __LINE__);
2093
2094         return ret;
2095 }
2096
2097 static bool call_OpenPrinterEx(struct torture_context *tctx,
2098                                struct dcerpc_pipe *p,
2099                                const char *name,
2100                                struct spoolss_DeviceMode *devmode,
2101                                struct policy_handle *handle);
2102
2103 static bool test_ClosePrinter(struct torture_context *tctx,
2104                               struct dcerpc_binding_handle *b,
2105                               struct policy_handle *handle);
2106
2107 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2108                                       struct dcerpc_pipe *p,
2109                                       struct policy_handle *handle,
2110                                       const char *name)
2111 {
2112         union spoolss_PrinterInfo info;
2113         struct spoolss_DeviceMode *devmode;
2114         struct spoolss_DeviceMode *devmode2;
2115         struct policy_handle handle_devmode;
2116         struct dcerpc_binding_handle *b = p->binding_handle;
2117
2118         /* simply compare level8 and level2 devmode */
2119
2120         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2121
2122         devmode = info.info8.devmode;
2123
2124         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2125
2126         devmode2 = info.info2.devmode;
2127
2128         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2129                 "DM level 8 != DM level 2");
2130
2131
2132         /* set devicemode level 8 and see if it persists */
2133
2134         devmode->copies = 93;
2135         devmode->formname = talloc_strdup(tctx, "Legal");
2136
2137         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2138
2139         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2140
2141         devmode2 = info.info8.devmode;
2142
2143         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2144                 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2145
2146         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2147
2148         devmode2 = info.info2.devmode;
2149
2150         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2151                 "modified DM level 8 != DM level 2");
2152
2153
2154         /* set devicemode level 2 and see if it persists */
2155
2156         devmode->copies = 39;
2157         devmode->formname = talloc_strdup(tctx, "Executive");
2158
2159         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2160
2161         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2162
2163         devmode2 = info.info8.devmode;
2164
2165         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2166                 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2167
2168         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2169
2170         devmode2 = info.info2.devmode;
2171
2172         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2173                 "modified DM level 8 != DM level 2");
2174
2175
2176         /* check every single bit in public part of devicemode */
2177
2178         torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2179                 "failed to set every single devicemode component");
2180
2181
2182         /* change formname upon open and see if it persists in getprinter calls */
2183
2184         devmode->formname = talloc_strdup(tctx, "A4");
2185         devmode->copies = 42;
2186
2187         torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2188                 "failed to open printer handle");
2189
2190         torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2191
2192         devmode2 = info.info8.devmode;
2193
2194         if (strequal(devmode->devicename, devmode2->devicename)) {
2195                 torture_warning(tctx, "devicenames are the same\n");
2196         } else {
2197                 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2198                 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2199         }
2200
2201         if (strequal(devmode->formname, devmode2->formname)) {
2202                 torture_warning(tctx, "formname are the same\n");
2203         } else {
2204                 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2205                 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2206         }
2207
2208         if (devmode->copies == devmode2->copies) {
2209                 torture_warning(tctx, "copies are the same\n");
2210         } else {
2211                 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2212                 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2213         }
2214
2215         torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2216
2217         devmode2 = info.info2.devmode;
2218
2219         if (strequal(devmode->devicename, devmode2->devicename)) {
2220                 torture_warning(tctx, "devicenames are the same\n");
2221         } else {
2222                 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2223                 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2224         }
2225
2226         if (strequal(devmode->formname, devmode2->formname)) {
2227                 torture_warning(tctx, "formname is the same\n");
2228         } else {
2229                 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2230                 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2231         }
2232
2233         if (devmode->copies == devmode2->copies) {
2234                 torture_warning(tctx, "copies are the same\n");
2235         } else {
2236                 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2237                 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2238         }
2239
2240         test_ClosePrinter(tctx, b, &handle_devmode);
2241
2242         return true;
2243 }
2244
2245 /*
2246  * wrapper call that saves original devmode, runs tests, and restores devmode
2247  */
2248
2249 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2250                                      struct dcerpc_pipe *p,
2251                                      struct policy_handle *handle,
2252                                      const char *name)
2253 {
2254         union spoolss_PrinterInfo info;
2255         struct spoolss_DeviceMode *devmode;
2256         bool ret = true;
2257         struct dcerpc_binding_handle *b = p->binding_handle;
2258
2259         torture_comment(tctx, "Testing Printer Devicemodes\n");
2260
2261         /* save original devmode */
2262
2263         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2264                 "failed to get initial global devicemode");
2265
2266         devmode = info.info8.devmode;
2267
2268         /* run tests */
2269
2270         ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2271
2272         /* restore original devmode */
2273
2274         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2275                 "failed to restore initial global device mode");
2276
2277         torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2278                 ret ? "succeeded" : "failed");
2279
2280
2281         return ret;
2282 }
2283
2284 static bool test_ClosePrinter(struct torture_context *tctx,
2285                               struct dcerpc_binding_handle *b,
2286                               struct policy_handle *handle)
2287 {
2288         NTSTATUS status;
2289         struct spoolss_ClosePrinter r;
2290
2291         r.in.handle = handle;
2292         r.out.handle = handle;
2293
2294         torture_comment(tctx, "Testing ClosePrinter\n");
2295
2296         status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2297         torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2298         torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2299
2300         return true;
2301 }
2302
2303 static bool test_GetForm_args(struct torture_context *tctx,
2304                               struct dcerpc_binding_handle *b,
2305                               struct policy_handle *handle,
2306                               const char *form_name,
2307                               uint32_t level,
2308                               union spoolss_FormInfo *info_p)
2309 {
2310         NTSTATUS status;
2311         struct spoolss_GetForm r;
2312         uint32_t needed;
2313
2314         r.in.handle = handle;
2315         r.in.form_name = form_name;
2316         r.in.level = level;
2317         r.in.buffer = NULL;
2318         r.in.offered = 0;
2319         r.out.needed = &needed;
2320
2321         torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2322
2323         status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2324         torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2325
2326         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2327                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2328                 r.in.buffer = &blob;
2329                 r.in.offered = needed;
2330                 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2331                 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2332
2333                 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2334
2335                 torture_assert(tctx, r.out.info, "No form info returned");
2336         }
2337
2338         torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2339
2340         CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2341
2342         if (info_p) {
2343                 *info_p = *r.out.info;
2344         }
2345
2346         return true;
2347 }
2348
2349 static bool test_GetForm(struct torture_context *tctx,
2350                          struct dcerpc_binding_handle *b,
2351                          struct policy_handle *handle,
2352                          const char *form_name,
2353                          uint32_t level)
2354 {
2355         return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2356 }
2357
2358 static bool test_EnumForms(struct torture_context *tctx,
2359                            struct dcerpc_binding_handle *b,
2360                            struct policy_handle *handle,
2361                            bool print_server,
2362                            uint32_t level,
2363                            uint32_t *count_p,
2364                            union spoolss_FormInfo **info_p)
2365 {
2366         struct spoolss_EnumForms r;
2367         uint32_t needed;
2368         uint32_t count;
2369         union spoolss_FormInfo *info;
2370
2371         r.in.handle = handle;
2372         r.in.level = level;
2373         r.in.buffer = NULL;
2374         r.in.offered = 0;
2375         r.out.needed = &needed;
2376         r.out.count = &count;
2377         r.out.info = &info;
2378
2379         torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2380
2381         torture_assert_ntstatus_ok(tctx,
2382                 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2383                 "EnumForms failed");
2384
2385         if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2386                 torture_skip(tctx, "EnumForms level 2 not supported");
2387         }
2388
2389         if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2390                 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2391         }
2392
2393         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2394                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2395                 r.in.buffer = &blob;
2396                 r.in.offered = needed;
2397
2398                 torture_assert_ntstatus_ok(tctx,
2399                         dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2400                         "EnumForms failed");
2401
2402                 torture_assert(tctx, info, "No forms returned");
2403         }
2404
2405         torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2406
2407         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2408
2409         if (info_p) {
2410                 *info_p = info;
2411         }
2412         if (count_p) {
2413                 *count_p = count;
2414         }
2415
2416         return true;
2417 }
2418
2419 static bool test_EnumForms_all(struct torture_context *tctx,
2420                                struct dcerpc_binding_handle *b,
2421                                struct policy_handle *handle,
2422                                bool print_server)
2423 {
2424         uint32_t levels[] = { 1, 2 };
2425         int i, j;
2426
2427         for (i=0; i<ARRAY_SIZE(levels); i++) {
2428
2429                 uint32_t count = 0;
2430                 union spoolss_FormInfo *info = NULL;
2431
2432                 torture_assert(tctx,
2433                         test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2434                         "failed to enum forms");
2435
2436                 for (j = 0; j < count; j++) {
2437                         if (!print_server) {
2438                                 torture_assert(tctx,
2439                                         test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2440                                         "failed to get form");
2441                         }
2442                 }
2443         }
2444
2445         return true;
2446 }
2447
2448 static bool test_EnumForms_find_one(struct torture_context *tctx,
2449                                     struct dcerpc_binding_handle *b,
2450                                     struct policy_handle *handle,
2451                                     bool print_server,
2452                                     const char *form_name)
2453 {
2454         union spoolss_FormInfo *info;
2455         uint32_t count;
2456         bool found = false;
2457         int i;
2458
2459         torture_assert(tctx,
2460                 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2461                 "failed to enumerate forms");
2462
2463         for (i=0; i<count; i++) {
2464                 if (strequal(form_name, info[i].info1.form_name)) {
2465                         found = true;
2466                         break;
2467                 }
2468         }
2469
2470         return found;
2471 }
2472
2473 static bool test_DeleteForm(struct torture_context *tctx,
2474                             struct dcerpc_binding_handle *b,
2475                             struct policy_handle *handle,
2476                             const char *form_name,
2477                             WERROR expected_result)
2478 {
2479         struct spoolss_DeleteForm r;
2480
2481         r.in.handle = handle;
2482         r.in.form_name = form_name;
2483
2484         torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2485
2486         torture_assert_ntstatus_ok(tctx,
2487                 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2488                 "DeleteForm failed");
2489         torture_assert_werr_equal(tctx, r.out.result, expected_result,
2490                 "DeleteForm gave unexpected result");
2491         if (W_ERROR_IS_OK(r.out.result)) {
2492                 torture_assert_ntstatus_ok(tctx,
2493                         dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2494                         "2nd DeleteForm failed");
2495                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2496                         "2nd DeleteForm failed");
2497         }
2498
2499         return true;
2500 }
2501
2502 static bool test_AddForm(struct torture_context *tctx,
2503                          struct dcerpc_binding_handle *b,
2504                          struct policy_handle *handle,
2505                          uint32_t level,
2506                          union spoolss_AddFormInfo *info,
2507                          WERROR expected_result)
2508 {
2509         struct spoolss_AddForm r;
2510
2511         if (level != 1) {
2512                 torture_skip(tctx, "only level 1 supported");
2513         }
2514
2515         r.in.handle     = handle;
2516         r.in.level      = level;
2517         r.in.info       = *info;
2518
2519         torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2520                 r.in.info.info1->form_name, r.in.level,
2521                 r.in.info.info1->flags);
2522
2523         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2524                 "AddForm failed");
2525         torture_assert_werr_equal(tctx, r.out.result, expected_result,
2526                 "AddForm gave unexpected result");
2527
2528         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2529                 "2nd AddForm failed");
2530         if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2531                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2532                         "2nd AddForm gave unexpected result");
2533         } else {
2534                 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2535                         "2nd AddForm gave unexpected result");
2536         }
2537
2538         return true;
2539 }
2540
2541 static bool test_SetForm(struct torture_context *tctx,
2542                          struct dcerpc_binding_handle *b,
2543                          struct policy_handle *handle,
2544                          const char *form_name,
2545                          uint32_t level,
2546                          union spoolss_AddFormInfo *info)
2547 {
2548         struct spoolss_SetForm r;
2549
2550         r.in.handle     = handle;
2551         r.in.form_name  = form_name;
2552         r.in.level      = level;
2553         r.in.info       = *info;
2554
2555         torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2556                 form_name, r.in.level);
2557
2558         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2559                 "SetForm failed");
2560
2561         torture_assert_werr_ok(tctx, r.out.result,
2562                 "SetForm failed");
2563
2564         return true;
2565 }
2566
2567 static bool test_GetForm_winreg(struct torture_context *tctx,
2568                                 struct dcerpc_binding_handle *b,
2569                                 struct policy_handle *handle,
2570                                 const char *key_name,
2571                                 const char *form_name,
2572                                 enum winreg_Type *w_type,
2573                                 uint32_t *w_size,
2574                                 uint32_t *w_length,
2575                                 uint8_t **w_data);
2576
2577 static bool test_Forms_args(struct torture_context *tctx,
2578                             struct dcerpc_binding_handle *b,
2579                             struct policy_handle *handle,
2580                             bool print_server,
2581                             const char *printer_name,
2582                             struct dcerpc_binding_handle *winreg_handle,
2583                             struct policy_handle *hive_handle,
2584                             const char *form_name,
2585                             struct spoolss_AddFormInfo1 *info1,
2586                             WERROR expected_add_result,
2587                             WERROR expected_delete_result)
2588 {
2589         union spoolss_FormInfo info;
2590         union spoolss_AddFormInfo add_info;
2591
2592         enum winreg_Type w_type;
2593         uint32_t w_size;
2594         uint32_t w_length;
2595         uint8_t *w_data;
2596
2597         add_info.info1 = info1;
2598
2599         torture_assert(tctx,
2600                 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2601                 "failed to add form");
2602
2603         if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2604
2605                 torture_assert(tctx,
2606                         test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2607                         "failed to get form via winreg");
2608
2609                 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2610                 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2611                 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2612                 torture_assert_mem_equal(tctx, &w_data[0], &add_info.info1->size.width, 4, "width mismatch");
2613                 torture_assert_mem_equal(tctx, &w_data[4], &add_info.info1->size.height, 4, "height mismatch");
2614                 torture_assert_mem_equal(tctx, &w_data[8], &add_info.info1->area.left, 4, "left mismatch");
2615                 torture_assert_mem_equal(tctx, &w_data[12], &add_info.info1->area.top, 4, "top mismatch");
2616                 torture_assert_mem_equal(tctx, &w_data[16], &add_info.info1->area.right, 4, "right mismatch");
2617                 torture_assert_mem_equal(tctx, &w_data[20], &add_info.info1->area.bottom, 4, "bottom mismatch");
2618                 /* skip index here */
2619                 torture_assert_mem_equal(tctx, &w_data[28], &add_info.info1->flags, 4, "flags mismatch");
2620         }
2621
2622         if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2623                 torture_assert(tctx,
2624                         test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2625                         "failed to get added form");
2626
2627                 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2628                 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2629                 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2630                 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2631                 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2632                 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2633                 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2634
2635                 if (winreg_handle && hive_handle) {
2636                         torture_assert_mem_equal(tctx, &w_data[0], &info.info1.size.width, 4, "width mismatch");
2637                         torture_assert_mem_equal(tctx, &w_data[4], &info.info1.size.height, 4, "height mismatch");
2638                         torture_assert_mem_equal(tctx, &w_data[8], &info.info1.area.left, 4, "left mismatch");
2639                         torture_assert_mem_equal(tctx, &w_data[12], &info.info1.area.top, 4, "top mismatch");
2640                         torture_assert_mem_equal(tctx, &w_data[16], &info.info1.area.right, 4, "right mismatch");
2641                         torture_assert_mem_equal(tctx, &w_data[20], &info.info1.area.bottom, 4, "bottom mismatch");
2642                         /* skip index here */
2643                         torture_assert_mem_equal(tctx, &w_data[28], &info.info1.flags, 4, "flags mismatch");
2644                 }
2645
2646                 add_info.info1->size.width = 1234;
2647
2648                 torture_assert(tctx,
2649                         test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2650                         "failed to set form");
2651                 torture_assert(tctx,
2652                         test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2653                         "failed to get setted form");
2654
2655                 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2656         }
2657
2658         if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2659                 torture_assert(tctx,
2660                         test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2661                         "Newly added form not found in enum call");
2662         }
2663
2664         torture_assert(tctx,
2665                 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2666                 "failed to delete form");
2667
2668         return true;
2669 }
2670
2671 static bool test_Forms(struct torture_context *tctx,
2672                        struct dcerpc_binding_handle *b,
2673                        struct policy_handle *handle,
2674                        bool print_server,
2675                        const char *printer_name,
2676                        struct dcerpc_binding_handle *winreg_handle,
2677                        struct policy_handle *hive_handle)
2678 {
2679         const struct spoolss_FormSize size = {
2680                 .width  = 50,
2681                 .height = 25
2682         };
2683         const struct spoolss_FormArea area = {
2684                 .left   = 5,
2685                 .top    = 10,
2686                 .right  = 45,
2687                 .bottom = 15
2688         };
2689         int i;
2690
2691         struct {
2692                 struct spoolss_AddFormInfo1 info1;
2693                 WERROR expected_add_result;
2694                 WERROR expected_delete_result;
2695         } forms[] = {
2696                 {
2697                         .info1 = {
2698                                 .flags          = SPOOLSS_FORM_USER,
2699                                 .form_name      = "testform_user",
2700                                 .size           = size,
2701                                 .area           = area,
2702                         },
2703                         .expected_add_result    = WERR_OK,
2704                         .expected_delete_result = WERR_OK
2705                 },
2706 /*
2707                 weird, we can add a builtin form but we can never remove it
2708                 again - gd
2709
2710                 {
2711                         .info1 = {
2712                                 .flags          = SPOOLSS_FORM_BUILTIN,
2713                                 .form_name      = "testform_builtin",
2714                                 .size           = size,
2715                                 .area           = area,
2716                         },
2717                         .expected_add_result    = WERR_OK,
2718                         .expected_delete_result = WERR_INVALID_PARAM,
2719                 },
2720 */
2721                 {
2722                         .info1 = {
2723                                 .flags          = SPOOLSS_FORM_PRINTER,
2724                                 .form_name      = "testform_printer",
2725                                 .size           = size,
2726                                 .area           = area,
2727                         },
2728                         .expected_add_result    = WERR_OK,
2729                         .expected_delete_result = WERR_OK
2730                 },
2731                 {
2732                         .info1 = {
2733                                 .flags          = SPOOLSS_FORM_USER,
2734                                 .form_name      = "Letter",
2735                                 .size           = size,
2736                                 .area           = area,
2737                         },
2738                         .expected_add_result    = WERR_FILE_EXISTS,
2739                         .expected_delete_result = WERR_INVALID_PARAM
2740                 },
2741                 {
2742                         .info1 = {
2743                                 .flags          = SPOOLSS_FORM_BUILTIN,
2744                                 .form_name      = "Letter",
2745                                 .size           = size,
2746                                 .area           = area,
2747                         },
2748                         .expected_add_result    = WERR_FILE_EXISTS,
2749                         .expected_delete_result = WERR_INVALID_PARAM
2750                 },
2751                 {
2752                         .info1 = {
2753                                 .flags          = SPOOLSS_FORM_PRINTER,
2754                                 .form_name      = "Letter",
2755                                 .size           = size,
2756                                 .area           = area,
2757                         },
2758                         .expected_add_result    = WERR_FILE_EXISTS,
2759                         .expected_delete_result = WERR_INVALID_PARAM
2760                 },
2761                 {
2762                         .info1 = {
2763                                 .flags          = 12345,
2764                                 .form_name      = "invalid_flags",
2765                                 .size           = size,
2766                                 .area           = area,
2767                         },
2768                         .expected_add_result    = WERR_INVALID_PARAM,
2769                         .expected_delete_result = WERR_INVALID_FORM_NAME
2770                 }
2771
2772         };
2773
2774         for (i=0; i < ARRAY_SIZE(forms); i++) {
2775                 torture_assert(tctx,
2776                         test_Forms_args(tctx, b, handle, print_server, printer_name,
2777                                         winreg_handle, hive_handle,
2778                                         forms[i].info1.form_name,
2779                                         &forms[i].info1,
2780                                         forms[i].expected_add_result,
2781                                         forms[i].expected_delete_result),
2782                         talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2783         }
2784
2785         return true;
2786 }
2787
2788 static bool test_EnumPorts_old(struct torture_context *tctx,
2789                                struct dcerpc_pipe *p)
2790 {
2791         NTSTATUS status;
2792         struct spoolss_EnumPorts r;
2793         uint32_t needed;
2794         uint32_t count;
2795         union spoolss_PortInfo *info;
2796         struct dcerpc_binding_handle *b = p->binding_handle;
2797
2798         r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2799                                           dcerpc_server_name(p));
2800         r.in.level = 2;
2801         r.in.buffer = NULL;
2802         r.in.offered = 0;
2803         r.out.needed = &needed;
2804         r.out.count = &count;
2805         r.out.info = &info;
2806
2807         torture_comment(tctx, "Testing EnumPorts\n");
2808
2809         status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2810
2811         torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2812
2813         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2814                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2815                 r.in.buffer = &blob;
2816                 r.in.offered = needed;
2817
2818                 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2819                 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2820                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2821
2822                 torture_assert(tctx, info, "No ports returned");
2823         }
2824
2825         torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2826
2827         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2828
2829         return true;
2830 }
2831
2832 static bool test_AddPort(struct torture_context *tctx,
2833                          struct dcerpc_pipe *p)
2834 {
2835         NTSTATUS status;
2836         struct spoolss_AddPort r;
2837         struct dcerpc_binding_handle *b = p->binding_handle;
2838
2839         r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
2840                                            dcerpc_server_name(p));
2841         r.in.unknown = 0;
2842         r.in.monitor_name = "foo";
2843
2844         torture_comment(tctx, "Testing AddPort\n");
2845
2846         status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
2847
2848         torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
2849
2850         /* win2k3 returns WERR_NOT_SUPPORTED */
2851
2852 #if 0
2853
2854         if (!W_ERROR_IS_OK(r.out.result)) {
2855                 printf("AddPort failed - %s\n", win_errstr(r.out.result));
2856                 return false;
2857         }
2858
2859 #endif
2860
2861         return true;
2862 }
2863
2864 static bool test_GetJob_args(struct torture_context *tctx,
2865                              struct dcerpc_binding_handle *b,
2866                              struct policy_handle *handle,
2867                              uint32_t job_id,
2868                              uint32_t level,
2869                              union spoolss_JobInfo *info_p)
2870 {
2871         NTSTATUS status;
2872         struct spoolss_GetJob r;
2873         union spoolss_JobInfo info;
2874         uint32_t needed;
2875
2876         r.in.handle = handle;
2877         r.in.job_id = job_id;
2878         r.in.level = level;
2879         r.in.buffer = NULL;
2880         r.in.offered = 0;
2881         r.out.needed = &needed;
2882         r.out.info = &info;
2883
2884         torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
2885
2886         status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
2887         torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2888         if (level == 0) {
2889                 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
2890         }
2891
2892         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2893                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2894                 r.in.buffer = &blob;
2895                 r.in.offered = needed;
2896
2897                 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
2898                 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2899         }
2900
2901         torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
2902         torture_assert(tctx, r.out.info, "No job info returned");
2903
2904         CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2905
2906         if (info_p) {
2907                 *info_p = *r.out.info;
2908         }
2909
2910         return true;
2911 }
2912
2913 static bool test_GetJob(struct torture_context *tctx,
2914                         struct dcerpc_binding_handle *b,
2915                         struct policy_handle *handle,
2916                         uint32_t job_id)
2917 {
2918         uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
2919         uint32_t i;
2920
2921         for (i=0; i < ARRAY_SIZE(levels); i++) {
2922                 torture_assert(tctx,
2923                         test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
2924                         "GetJob failed");
2925         }
2926
2927         return true;
2928 }
2929
2930 static bool test_SetJob(struct torture_context *tctx,
2931                         struct dcerpc_binding_handle *b,
2932                         struct policy_handle *handle, uint32_t job_id,
2933                         enum spoolss_JobControl command)
2934 {
2935         NTSTATUS status;
2936         struct spoolss_SetJob r;
2937
2938         r.in.handle     = handle;
2939         r.in.job_id     = job_id;
2940         r.in.ctr        = NULL;
2941         r.in.command    = command;
2942
2943         switch (command) {
2944         case SPOOLSS_JOB_CONTROL_PAUSE:
2945                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
2946                 break;
2947         case SPOOLSS_JOB_CONTROL_RESUME:
2948                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
2949                 break;
2950         case SPOOLSS_JOB_CONTROL_CANCEL:
2951                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
2952                 break;
2953         case SPOOLSS_JOB_CONTROL_RESTART:
2954                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
2955                 break;
2956         case SPOOLSS_JOB_CONTROL_DELETE:
2957                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
2958                 break;
2959         case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
2960                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
2961                 break;
2962         case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
2963                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
2964                 break;
2965         case SPOOLSS_JOB_CONTROL_RETAIN:
2966                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
2967                 break;
2968         case SPOOLSS_JOB_CONTROL_RELEASE:
2969                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
2970                 break;
2971         default:
2972                 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
2973                 break;
2974         }
2975
2976         status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
2977         torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
2978         torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
2979
2980         return true;
2981 }
2982
2983 static bool test_AddJob(struct torture_context *tctx,
2984                         struct dcerpc_binding_handle *b,
2985                         struct policy_handle *handle)
2986 {
2987         NTSTATUS status;
2988         struct spoolss_AddJob r;
2989         uint32_t needed;
2990
2991         r.in.level = 0;
2992         r.in.handle = handle;
2993         r.in.offered = 0;
2994         r.out.needed = &needed;
2995         r.in.buffer = r.out.buffer = NULL;
2996
2997         torture_comment(tctx, "Testing AddJob\n");
2998
2999         status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3000         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3001
3002         r.in.level = 1;
3003
3004         status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3005         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3006
3007         return true;
3008 }
3009
3010
3011 static bool test_EnumJobs_args(struct torture_context *tctx,
3012                                struct dcerpc_binding_handle *b,
3013                                struct policy_handle *handle,
3014                                uint32_t level,
3015                                uint32_t *count_p,
3016                                union spoolss_JobInfo **info_p)
3017 {
3018         NTSTATUS status;
3019         struct spoolss_EnumJobs r;
3020         uint32_t needed;
3021         uint32_t count;
3022         union spoolss_JobInfo *info;
3023
3024         r.in.handle = handle;
3025         r.in.firstjob = 0;
3026         r.in.numjobs = 0xffffffff;
3027         r.in.level = level;
3028         r.in.buffer = NULL;
3029         r.in.offered = 0;
3030         r.out.needed = &needed;
3031         r.out.count = &count;
3032         r.out.info = &info;
3033
3034         torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3035
3036         status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3037
3038         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3039
3040         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3041                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3042                 r.in.buffer = &blob;
3043                 r.in.offered = needed;
3044
3045                 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3046
3047                 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3048                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3049                 torture_assert(tctx, info, "No jobs returned");
3050
3051                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3052
3053         } else {
3054                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3055         }
3056
3057         if (count_p) {
3058                 *count_p = count;
3059         }
3060         if (info_p) {
3061                 *info_p = info;
3062         }
3063
3064         return true;
3065 }
3066
3067 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3068                                          struct dcerpc_binding_handle *b,
3069                                          struct policy_handle *handle,
3070                                          uint32_t *job_id)
3071 {
3072         NTSTATUS status;
3073         struct spoolss_StartDocPrinter s;
3074         struct spoolss_DocumentInfo1 info1;
3075         struct spoolss_StartPagePrinter sp;
3076         struct spoolss_WritePrinter w;
3077         struct spoolss_EndPagePrinter ep;
3078         struct spoolss_EndDocPrinter e;
3079         int i;
3080         uint32_t num_written;
3081
3082         torture_comment(tctx, "Testing StartDocPrinter\n");
3083
3084         s.in.handle             = handle;
3085         s.in.level              = 1;
3086         s.in.info.info1         = &info1;
3087         s.out.job_id            = job_id;
3088         info1.document_name     = "TorturePrintJob";
3089         info1.output_file       = NULL;
3090         info1.datatype          = "RAW";
3091
3092         status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3093         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3094         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3095
3096         for (i=1; i < 4; i++) {
3097                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3098
3099                 sp.in.handle            = handle;
3100
3101                 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3102                 torture_assert_ntstatus_ok(tctx, status,
3103                                            "dcerpc_spoolss_StartPagePrinter failed");
3104                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3105
3106                 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3107
3108                 w.in.handle             = handle;
3109                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3110                 w.out.num_written       = &num_written;
3111
3112                 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3113                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3114                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3115
3116                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3117
3118                 ep.in.handle            = handle;
3119
3120                 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3121                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3122                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3123         }
3124
3125         torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3126
3127         e.in.handle = handle;
3128
3129         status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3130         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3131         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3132
3133         return true;
3134 }
3135
3136 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3137                                         struct dcerpc_binding_handle *b,
3138                                         struct policy_handle *handle,
3139                                         uint32_t num_jobs,
3140                                         uint32_t *job_ids)
3141 {
3142         uint32_t count;
3143         union spoolss_JobInfo *info = NULL;
3144         int i;
3145
3146         torture_assert(tctx,
3147                 test_AddJob(tctx, b, handle),
3148                 "AddJob failed");
3149
3150         torture_assert(tctx,
3151                 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3152                 "EnumJobs level 1 failed");
3153
3154         torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3155
3156         for (i=0; i < num_jobs; i++) {
3157                 union spoolss_JobInfo ginfo;
3158
3159                 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3160
3161                 torture_assert(tctx,
3162                         test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3163                         "failed to call test_GetJob");
3164
3165                 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3166         }
3167
3168         for (i=0; i < num_jobs; i++) {
3169                 torture_assert(tctx,
3170                         test_SetJob(tctx, b, handle, info[i].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE),
3171                         "failed to pause printjob");
3172                 torture_assert(tctx,
3173                         test_SetJob(tctx, b, handle, info[i].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME),
3174                         "failed to resume printjob");
3175         }
3176
3177         return true;
3178 }
3179
3180 static bool test_DoPrintTest(struct torture_context *tctx,
3181                              struct dcerpc_binding_handle *b,
3182                              struct policy_handle *handle)
3183 {
3184         bool ret = true;
3185         uint32_t num_jobs = 8;
3186         uint32_t *job_ids;
3187         int i;
3188
3189         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3190
3191         for (i=0; i < num_jobs; i++) {
3192                 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
3193         }
3194
3195         ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3196
3197         for (i=0; i < num_jobs; i++) {
3198                 ret &= test_SetJob(tctx, b, handle, job_ids[i], SPOOLSS_JOB_CONTROL_DELETE);
3199         }
3200
3201         return ret;
3202 }
3203
3204 static bool test_PausePrinter(struct torture_context *tctx,
3205                               struct dcerpc_binding_handle *b,
3206                               struct policy_handle *handle)
3207 {
3208         NTSTATUS status;
3209         struct spoolss_SetPrinter r;
3210         struct spoolss_SetPrinterInfoCtr info_ctr;
3211         struct spoolss_DevmodeContainer devmode_ctr;
3212         struct sec_desc_buf secdesc_ctr;
3213
3214         info_ctr.level = 0;
3215         info_ctr.info.info0 = NULL;
3216
3217         ZERO_STRUCT(devmode_ctr);
3218         ZERO_STRUCT(secdesc_ctr);
3219
3220         r.in.handle             = handle;
3221         r.in.info_ctr           = &info_ctr;
3222         r.in.devmode_ctr        = &devmode_ctr;
3223         r.in.secdesc_ctr        = &secdesc_ctr;
3224         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
3225
3226         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3227
3228         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3229
3230         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3231
3232         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3233
3234         return true;
3235 }
3236
3237 static bool test_ResumePrinter(struct torture_context *tctx,
3238                                struct dcerpc_binding_handle *b,
3239                                struct policy_handle *handle)
3240 {
3241         NTSTATUS status;
3242         struct spoolss_SetPrinter r;
3243         struct spoolss_SetPrinterInfoCtr info_ctr;
3244         struct spoolss_DevmodeContainer devmode_ctr;
3245         struct sec_desc_buf secdesc_ctr;
3246
3247         info_ctr.level = 0;
3248         info_ctr.info.info0 = NULL;
3249
3250         ZERO_STRUCT(devmode_ctr);
3251         ZERO_STRUCT(secdesc_ctr);
3252
3253         r.in.handle             = handle;
3254         r.in.info_ctr           = &info_ctr;
3255         r.in.devmode_ctr        = &devmode_ctr;
3256         r.in.secdesc_ctr        = &secdesc_ctr;
3257         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
3258
3259         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3260
3261         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3262
3263         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3264
3265         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3266
3267         return true;
3268 }
3269
3270 static bool test_GetPrinterData(struct torture_context *tctx,
3271                                 struct dcerpc_binding_handle *b,
3272                                 struct policy_handle *handle,
3273                                 const char *value_name,
3274                                 enum winreg_Type *type_p,
3275                                 uint8_t **data_p,
3276                                 uint32_t *needed_p)
3277 {
3278         NTSTATUS status;
3279         struct spoolss_GetPrinterData r;
3280         uint32_t needed;
3281         enum winreg_Type type;
3282         union spoolss_PrinterData data;
3283
3284         r.in.handle = handle;
3285         r.in.value_name = value_name;
3286         r.in.offered = 0;
3287         r.out.needed = &needed;
3288         r.out.type = &type;
3289         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3290
3291         torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3292
3293         status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3294         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3295
3296         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3297                 r.in.offered = needed;
3298                 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3299                 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3300                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3301         }
3302
3303         torture_assert_werr_ok(tctx, r.out.result,
3304                 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3305
3306         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3307
3308         if (type_p) {
3309                 *type_p = type;
3310         }
3311
3312         if (data_p) {
3313                 *data_p = r.out.data;
3314         }
3315
3316         if (needed_p) {
3317                 *needed_p = needed;
3318         }
3319
3320         return true;
3321 }
3322
3323 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3324                                   struct dcerpc_pipe *p,
3325                                   struct policy_handle *handle,
3326                                   const char *key_name,
3327                                   const char *value_name,
3328                                   enum winreg_Type *type_p,
3329                                   uint8_t **data_p,
3330                                   uint32_t *needed_p)
3331 {
3332         NTSTATUS status;
3333         struct spoolss_GetPrinterDataEx r;
3334         enum winreg_Type type;
3335         uint32_t needed;
3336         union spoolss_PrinterData data;
3337         struct dcerpc_binding_handle *b = p->binding_handle;
3338
3339         r.in.handle = handle;
3340         r.in.key_name = key_name;
3341         r.in.value_name = value_name;
3342         r.in.offered = 0;
3343         r.out.type = &type;
3344         r.out.needed = &needed;
3345         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3346
3347         torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3348                 r.in.key_name, r.in.value_name);
3349
3350         status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3351         if (!NT_STATUS_IS_OK(status)) {
3352                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3353                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3354                 }
3355                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3356         }
3357
3358         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3359                 r.in.offered = needed;
3360                 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3361                 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3362                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3363         }
3364
3365         torture_assert_werr_ok(tctx, r.out.result,
3366                 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3367
3368         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3369
3370         if (type_p) {
3371                 *type_p = type;
3372         }
3373
3374         if (data_p) {
3375                 *data_p = r.out.data;
3376         }
3377
3378         if (needed_p) {
3379                 *needed_p = needed;
3380         }
3381
3382         return true;
3383 }
3384
3385 static bool test_get_environment(struct torture_context *tctx,
3386                                  struct dcerpc_binding_handle *b,
3387                                  struct policy_handle *handle,
3388                                  const char **architecture)
3389 {
3390         DATA_BLOB blob;
3391         enum winreg_Type type;
3392         uint8_t *data;
3393         uint32_t needed;
3394
3395         torture_assert(tctx,
3396                 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3397                 "failed to get Architecture");
3398
3399         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3400
3401         blob = data_blob_const(data, needed);
3402         *architecture = reg_val_data_string(tctx, lp_iconv_convenience(tctx->lp_ctx), REG_SZ, blob);
3403
3404         return true;
3405 }
3406
3407 static bool test_GetPrinterData_list(struct torture_context *tctx,
3408                                      struct dcerpc_pipe *p,
3409                                      struct policy_handle *handle,
3410                                      const char **architecture)
3411 {
3412         struct dcerpc_binding_handle *b = p->binding_handle;
3413         const char *list[] = {
3414                 "W3SvcInstalled",
3415                 "BeepEnabled",
3416                 "EventLog",
3417                 /* "NetPopup", not on w2k8 */
3418                 /* "NetPopupToComputer", not on w2k8 */
3419                 "MajorVersion",
3420                 "MinorVersion",
3421                 "DefaultSpoolDirectory",
3422                 "Architecture",
3423                 "DsPresent",
3424                 "OSVersion",
3425                 /* "OSVersionEx", not on s3 */
3426                 "DNSMachineName"
3427         };
3428         int i;
3429
3430         for (i=0; i < ARRAY_SIZE(list); i++) {
3431                 enum winreg_Type type, type_ex;
3432                 uint8_t *data, *data_ex;
3433                 uint32_t needed, needed_ex;
3434
3435                 torture_assert(tctx, test_GetPrinterData(tctx, b, handle, list[i], &type, &data, &needed),
3436                         talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
3437                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
3438                         talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
3439                 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
3440                 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
3441                 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3442
3443                 if (strequal(list[i], "Architecture")) {
3444                         if (architecture) {
3445                                 DATA_BLOB blob = data_blob_const(data, needed);
3446                                 *architecture = reg_val_data_string(tctx, lp_iconv_convenience(tctx->lp_ctx), REG_SZ, blob);
3447                         }
3448                 }
3449         }
3450
3451         return true;
3452 }
3453
3454 static bool test_EnumPrinterData(struct torture_context *tctx,
3455                                  struct dcerpc_pipe *p,
3456                                  struct policy_handle *handle,
3457                                  uint32_t enum_index,
3458                                  uint32_t value_offered,
3459                                  uint32_t data_offered,
3460                                  enum winreg_Type *type_p,
3461                                  uint32_t *value_needed_p,
3462                                  uint32_t *data_needed_p,
3463                                  const char **value_name_p,
3464                                  uint8_t **data_p,
3465                                  WERROR *result_p)
3466 {
3467         struct spoolss_EnumPrinterData r;
3468         uint32_t data_needed;
3469         uint32_t value_needed;
3470         enum winreg_Type type;
3471         struct dcerpc_binding_handle *b = p->binding_handle;
3472
3473         r.in.handle = handle;
3474         r.in.enum_index = enum_index;
3475         r.in.value_offered = value_offered;
3476         r.in.data_offered = data_offered;
3477         r.out.data_needed = &data_needed;
3478         r.out.value_needed = &value_needed;
3479         r.out.type = &type;
3480         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3481         r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3482
3483         torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3484
3485         torture_assert_ntstatus_ok(tctx,
3486                 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
3487                 "EnumPrinterData failed");
3488
3489         if (type_p) {
3490                 *type_p = type;
3491         }
3492         if (value_needed_p) {
3493                 *value_needed_p = value_needed;
3494         }
3495         if (data_needed_p) {
3496                 *data_needed_p = data_needed;
3497         }
3498         if (value_name_p) {
3499                 *value_name_p = r.out.value_name;
3500         }
3501         if (data_p) {
3502                 *data_p = r.out.data;
3503         }
3504         if (result_p) {
3505                 *result_p = r.out.result;
3506         }
3507
3508         return true;
3509 }
3510
3511
3512 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3513                                      struct dcerpc_pipe *p,
3514                                      struct policy_handle *handle)
3515 {
3516         uint32_t enum_index = 0;
3517         enum winreg_Type type;
3518         uint32_t value_needed;
3519         uint32_t data_needed;
3520         uint8_t *data;
3521         const char *value_name;
3522         WERROR result;
3523
3524         torture_comment(tctx, "Testing EnumPrinterData\n");
3525
3526         do {
3527                 torture_assert(tctx,
3528                         test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3529                                              &type, &value_needed, &data_needed,
3530                                              &value_name, &data, &result),
3531                         "EnumPrinterData failed");
3532
3533                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3534                         break;
3535                 }
3536
3537                 torture_assert(tctx,
3538                         test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3539                                              &type, &value_needed, &data_needed,
3540                                              &value_name, &data, &result),
3541                         "EnumPrinterData failed");
3542
3543                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3544                         break;
3545                 }
3546
3547                 enum_index++;
3548
3549         } while (W_ERROR_IS_OK(result));
3550
3551         torture_comment(tctx, "EnumPrinterData test succeeded\n");
3552
3553         return true;
3554 }
3555
3556 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3557                                    struct dcerpc_binding_handle *b,
3558                                    struct policy_handle *handle,
3559                                    const char *key_name,
3560                                    uint32_t *count_p,
3561                                    struct spoolss_PrinterEnumValues **info_p)
3562 {
3563         struct spoolss_EnumPrinterDataEx r;
3564         struct spoolss_PrinterEnumValues *info;
3565         uint32_t needed;
3566         uint32_t count;
3567
3568         r.in.handle = handle;
3569         r.in.key_name = key_name;
3570         r.in.offered = 0;
3571         r.out.needed = &needed;
3572         r.out.count = &count;
3573         r.out.info = &info;
3574
3575         torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3576
3577         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3578                 "EnumPrinterDataEx failed");
3579         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3580                 r.in.offered = needed;
3581                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3582                         "EnumPrinterDataEx failed");
3583         }
3584
3585         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3586
3587         CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3588
3589         if (count_p) {
3590                 *count_p = count;
3591         }
3592         if (info_p) {
3593                 *info_p = info;
3594         }
3595
3596         return true;
3597 }
3598
3599 static bool test_SetPrinterData(struct torture_context *tctx,
3600                                 struct dcerpc_binding_handle *b,
3601                                 struct policy_handle *handle,
3602                                 const char *value_name,
3603                                 enum winreg_Type type,
3604                                 uint8_t *data,
3605                                 uint32_t offered);
3606 static bool test_DeletePrinterData(struct torture_context *tctx,
3607                                    struct dcerpc_binding_handle *b,
3608                                    struct policy_handle *handle,
3609                                    const char *value_name);
3610
3611 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3612                                              struct dcerpc_pipe *p,
3613                                              struct policy_handle *handle)
3614 {
3615         uint32_t count;
3616         struct spoolss_PrinterEnumValues *info;
3617         int i;
3618         uint32_t value_needed, data_needed;
3619         uint32_t value_offered, data_offered;
3620         WERROR result;
3621         struct dcerpc_binding_handle *b = p->binding_handle;
3622
3623         enum winreg_Type type;
3624         DATA_BLOB blob;
3625
3626         torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3627
3628         torture_assert(tctx,
3629                 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3630                                   "REG_SZ", "torture_data1", &type, &blob), "");
3631
3632         torture_assert(tctx,
3633                 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
3634                 "SetPrinterData failed");
3635
3636         blob = data_blob_string_const("torture_data2");
3637
3638         torture_assert(tctx,
3639                 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3640                 "SetPrinterData failed");
3641
3642         blob = data_blob_talloc(tctx, NULL, 4);
3643         SIVAL(blob.data, 0, 0x11223344);
3644
3645         torture_assert(tctx,
3646                 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
3647                 "SetPrinterData failed");
3648
3649         torture_assert(tctx,
3650                 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
3651                 "failed to call EnumPrinterDataEx");
3652
3653         /* get the max sizes for value and data */
3654
3655         torture_assert(tctx,
3656                 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3657                                      NULL, &value_needed, &data_needed,
3658                                      NULL, NULL, &result),
3659                 "EnumPrinterData failed");
3660         torture_assert_werr_ok(tctx, result, "unexpected result");
3661
3662         /* check if the reply from the EnumPrinterData really matches max values */
3663
3664         for (i=0; i < count; i++) {
3665                 if (info[i].value_name_len > value_needed) {
3666                         torture_fail(tctx,
3667                                 talloc_asprintf(tctx,
3668                                 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3669                                 info[i].value_name_len, value_needed));
3670                 }
3671                 if (info[i].data_length > data_needed) {
3672                         torture_fail(tctx,
3673                                 talloc_asprintf(tctx,
3674                                 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3675                                 info[i].data_length, data_needed));
3676                 }
3677         }
3678
3679         /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3680          * sort or not sort the replies by value name, we should be able to do
3681          * the following entry comparison */
3682
3683         data_offered = data_needed;
3684         value_offered = value_needed;
3685
3686         for (i=0; i < count; i++) {
3687
3688                 const char *value_name;
3689                 uint8_t *data;
3690
3691                 torture_assert(tctx,
3692                         test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3693                                              &type, &value_needed, &data_needed,
3694                                              &value_name, &data, &result),
3695                         "EnumPrinterData failed");
3696
3697                 if (i -1 == count) {
3698                         torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3699                                 "unexpected result");
3700                         break;
3701                 } else {
3702                         torture_assert_werr_ok(tctx, result, "unexpected result");
3703                 }
3704
3705                 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3706                 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3707                 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
3708                 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
3709                 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
3710         }
3711
3712         torture_assert(tctx,
3713                 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
3714                 "DeletePrinterData failed");
3715         torture_assert(tctx,
3716                 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
3717                 "DeletePrinterData failed");
3718         torture_assert(tctx,
3719                 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
3720                 "DeletePrinterData failed");
3721
3722         torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
3723
3724         return true;
3725 }
3726
3727 static bool test_DeletePrinterData(struct torture_context *tctx,
3728                                    struct dcerpc_binding_handle *b,
3729                                    struct policy_handle *handle,
3730                                    const char *value_name)
3731 {
3732         NTSTATUS status;
3733         struct spoolss_DeletePrinterData r;
3734
3735         r.in.handle = handle;
3736         r.in.value_name = value_name;
3737
3738         torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
3739                 r.in.value_name);
3740
3741         status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
3742
3743         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
3744         torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
3745
3746         return true;
3747 }
3748
3749 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
3750                                      struct dcerpc_binding_handle *b,
3751                                      struct policy_handle *handle,
3752                                      const char *key_name,
3753                                      const char *value_name)
3754 {
3755         struct spoolss_DeletePrinterDataEx r;
3756
3757         r.in.handle = handle;
3758         r.in.key_name = key_name;
3759         r.in.value_name = value_name;
3760
3761         torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
3762                 r.in.key_name, r.in.value_name);
3763
3764         torture_assert_ntstatus_ok(tctx,
3765                 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
3766                 "DeletePrinterDataEx failed");
3767         torture_assert_werr_ok(tctx, r.out.result,
3768                 "DeletePrinterDataEx failed");
3769
3770         return true;
3771 }
3772
3773 static bool test_DeletePrinterKey(struct torture_context *tctx,
3774                                   struct dcerpc_binding_handle *b,
3775                                   struct policy_handle *handle,
3776                                   const char *key_name)
3777 {
3778         struct spoolss_DeletePrinterKey r;
3779
3780         r.in.handle = handle;
3781         r.in.key_name = key_name;
3782
3783         torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
3784
3785         if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
3786                 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
3787                 return true;
3788         }
3789
3790         torture_assert_ntstatus_ok(tctx,
3791                 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
3792                 "DeletePrinterKey failed");
3793         torture_assert_werr_ok(tctx, r.out.result,
3794                 "DeletePrinterKey failed");
3795
3796         return true;
3797 }
3798
3799 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
3800                                  struct dcerpc_binding_handle *b,
3801                                  struct policy_handle *handle)
3802 {
3803         struct winreg_OpenHKLM r;
3804
3805         r.in.system_name = NULL;
3806         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3807         r.out.handle = handle;
3808
3809         torture_comment(tctx, "Testing winreg_OpenHKLM\n");
3810
3811         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
3812         torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
3813
3814         return true;
3815 }
3816
3817 static void init_winreg_String(struct winreg_String *name, const char *s)
3818 {
3819         name->name = s;
3820         if (s) {
3821                 name->name_len = 2 * (strlen_m(s) + 1);
3822                 name->name_size = name->name_len;
3823         } else {
3824                 name->name_len = 0;
3825                 name->name_size = 0;
3826         }
3827 }
3828
3829 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
3830                                      struct dcerpc_binding_handle *b,
3831                                      struct policy_handle *hive_handle,
3832                                      const char *keyname,
3833                                      uint32_t options,
3834                                      struct policy_handle *key_handle)
3835 {
3836         struct winreg_OpenKey r;
3837
3838         r.in.parent_handle = hive_handle;
3839         init_winreg_String(&r.in.keyname, keyname);
3840         r.in.options = options;
3841         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3842         r.out.handle = key_handle;
3843
3844         torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
3845
3846         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
3847         torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
3848
3849         return true;
3850 }
3851
3852 static bool test_winreg_OpenKey(struct torture_context *tctx,
3853                                 struct dcerpc_binding_handle *b,
3854                                 struct policy_handle *hive_handle,
3855                                 const char *keyname,
3856                                 struct policy_handle *key_handle)
3857 {
3858         return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
3859                                         REG_OPTION_NON_VOLATILE, key_handle);
3860 }
3861
3862 static bool test_winreg_CloseKey(struct torture_context *tctx,
3863                                  struct dcerpc_binding_handle *b,
3864                                  struct policy_handle *handle)
3865 {
3866         struct winreg_CloseKey r;
3867
3868         r.in.handle = handle;
3869         r.out.handle = handle;
3870
3871         torture_comment(tctx, "Testing winreg_CloseKey\n");
3872
3873         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
3874         torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
3875
3876         return true;
3877 }
3878
3879 bool test_winreg_QueryValue(struct torture_context *tctx,
3880                             struct dcerpc_binding_handle *b,
3881                             struct policy_handle *handle,
3882                             const char *value_name,
3883                             enum winreg_Type *type_p,
3884                             uint32_t *data_size_p,
3885                             uint32_t *data_length_p,
3886                             uint8_t **data_p)
3887 {
3888         struct winreg_QueryValue r;
3889         enum winreg_Type type = REG_NONE;
3890         uint32_t data_size = 0;
3891         uint32_t data_length = 0;
3892         struct winreg_String valuename;
3893         uint8_t *data = NULL;
3894
3895         init_winreg_String(&valuename, value_name);
3896
3897         data = talloc_zero_array(tctx, uint8_t, 0);
3898
3899         r.in.handle = handle;
3900         r.in.value_name = &valuename;
3901         r.in.type = &type;
3902         r.in.data_size = &data_size;
3903         r.in.data_length = &data_length;
3904         r.in.data = data;
3905         r.out.type = &type;
3906         r.out.data = data;
3907         r.out.data_size = &data_size;
3908         r.out.data_length = &data_length;
3909
3910         torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
3911
3912         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
3913         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3914                 *r.in.data_size = *r.out.data_size;
3915                 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
3916                 r.in.data = data;
3917                 r.out.data = data;
3918                 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
3919         }
3920         torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
3921
3922         if (type_p) {
3923                 *type_p = *r.out.type;
3924         }
3925         if (data_size_p) {
3926                 *data_size_p = *r.out.data_size;
3927         }
3928         if (data_length_p) {
3929                 *data_length_p = *r.out.data_length;
3930         }
3931         if (data_p) {
3932                 *data_p = r.out.data;
3933         }
3934
3935         return true;
3936 }
3937
3938 static bool test_winreg_query_printerdata(struct torture_context *tctx,
3939                                           struct dcerpc_binding_handle *b,
3940                                           struct policy_handle *handle,
3941                                           const char *printer_name,
3942                                           const char *key_name,
3943                                           const char *value_name,
3944                                           enum winreg_Type *w_type,
3945                                           uint32_t *w_size,
3946                                           uint32_t *w_length,
3947                                           uint8_t **w_data)
3948 {
3949         const char *printer_key;
3950         struct policy_handle key_handle;
3951
3952         printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
3953                 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
3954
3955         torture_assert(tctx,
3956                 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
3957
3958         torture_assert(tctx,
3959                 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
3960
3961         torture_assert(tctx,
3962                 test_winreg_CloseKey(tctx, b, &key_handle), "");
3963
3964         return true;
3965 }
3966
3967 static bool test_GetForm_winreg(struct torture_context *tctx,
3968                                 struct dcerpc_binding_handle *b,
3969                                 struct policy_handle *handle,
3970                                 const char *key_name,
3971                                 const char *form_name,
3972                                 enum winreg_Type *w_type,
3973                                 uint32_t *w_size,
3974                                 uint32_t *w_length,
3975                                 uint8_t **w_data)
3976 {
3977         struct policy_handle key_handle;
3978
3979         torture_assert(tctx,
3980                 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
3981
3982         torture_assert(tctx,
3983                 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
3984
3985         torture_assert(tctx,
3986                 test_winreg_CloseKey(tctx, b, &key_handle), "");
3987
3988         return true;
3989 }
3990
3991 static bool test_winreg_symbolic_link(struct torture_context *tctx,
3992                                       struct dcerpc_binding_handle *b,
3993                                       struct policy_handle *handle,
3994                                       const char *symlink_keyname,
3995                                       const char *symlink_destination)
3996 {
3997         /* check if the first key is a symlink to the second key */
3998
3999         enum winreg_Type w_type;
4000         uint32_t w_size;
4001         uint32_t w_length;
4002         uint8_t *w_data;
4003         struct policy_handle key_handle;
4004         DATA_BLOB blob;
4005         const char *str;
4006
4007         if (torture_setting_bool(tctx, "samba3", false)) {
4008                 torture_skip(tctx, "skip winreg symlink test against samba");
4009         }
4010
4011         torture_assert(tctx,
4012                 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4013                         "failed to open key link");
4014
4015         torture_assert(tctx,
4016                 test_winreg_QueryValue(tctx, b, &key_handle,
4017                                        "SymbolicLinkValue",
4018                                        &w_type, &w_size, &w_length, &w_data),
4019                 "failed to query for 'SymbolicLinkValue' attribute");
4020
4021         torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4022
4023         blob = data_blob(w_data, w_size);
4024         str = reg_val_data_string(tctx, lp_iconv_convenience(tctx->lp_ctx), REG_SZ, blob);
4025
4026         torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4027
4028         torture_assert(tctx,
4029                 test_winreg_CloseKey(tctx, b, &key_handle),
4030                 "failed to close key link");
4031
4032         return true;
4033 }
4034
4035 static const char *strip_unc(const char *unc)
4036 {
4037         char *name;
4038
4039         if (!unc) {
4040                 return NULL;
4041         }
4042
4043         if (unc[0] == '\\' && unc[1] == '\\') {
4044                 unc +=2;
4045         }
4046
4047         name = strchr(unc, '\\');
4048         if (name) {
4049                 return name+1;
4050         }
4051
4052         return unc;
4053 }
4054
4055 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4056                                        struct dcerpc_binding_handle *b,
4057                                        struct policy_handle *handle,
4058                                        const char *printer_name,
4059                                        struct dcerpc_binding_handle *winreg_handle,
4060                                        struct policy_handle *hive_handle)
4061 {
4062         union spoolss_PrinterInfo info;
4063         const char *keys[] = {
4064                 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4065                 TOP_LEVEL_PRINT_PRINTERS_KEY
4066         };
4067         int i;
4068         const char *printername, *sharename;
4069
4070         torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4071
4072         torture_assert(tctx,
4073                 test_GetPrinter_level(tctx, b, handle, 2, &info),
4074                 "failed to get printer info level 2");
4075
4076         printername = strip_unc(info.info2.printername);
4077         sharename = strip_unc(info.info2.sharename);
4078
4079 #define test_sz(wname, iname) \
4080 do {\
4081         DATA_BLOB blob;\
4082         const char *str;\
4083         enum winreg_Type w_type;\
4084         uint32_t w_size;\
4085         uint32_t w_length;\
4086         uint8_t *w_data;\
4087         torture_assert(tctx,\
4088                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4089                                        &w_type, &w_size, &w_length, &w_data),\
4090                 "failed to query winreg");\
4091         torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4092         blob = data_blob(w_data, w_size);\
4093         str = reg_val_data_string(tctx, lp_iconv_convenience(tctx->lp_ctx), REG_SZ, blob);\
4094         if (w_size == 2 && iname == NULL) {\
4095                 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4096         } else {\
4097                 torture_assert_str_equal(tctx, str, iname,\
4098                         talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4099         }\
4100 } while(0);
4101
4102 #define test_dword(wname, iname) \
4103 do {\
4104         uint32_t value;\
4105         enum winreg_Type w_type;\
4106         uint32_t w_size;\
4107         uint32_t w_length;\
4108         uint8_t *w_data;\
4109         torture_assert(tctx,\
4110                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4111                                        &w_type, &w_size, &w_length, &w_data),\
4112                 "failed to query winreg");\
4113         torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4114         torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4115         torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4116         value = IVAL(w_data, 0);\
4117         torture_assert_int_equal(tctx, value, iname,\
4118                 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4119 } while(0);
4120
4121 #define test_dm(wname, iname) \
4122 do {\
4123         DATA_BLOB blob;\
4124         struct spoolss_DeviceMode dm;\
4125         enum ndr_err_code ndr_err;\
4126         enum winreg_Type w_type;\
4127         uint32_t w_size;\
4128         uint32_t w_length;\
4129         uint8_t *w_data;\
4130         torture_assert(tctx,\
4131                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4132                                        &w_type, &w_size, &w_length, &w_data),\
4133                 "failed to query winreg");\
4134         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4135         blob = data_blob(w_data, w_size);\
4136         ndr_err = ndr_pull_struct_blob(&blob, tctx, lp_iconv_convenience(tctx->lp_ctx), &dm,\
4137                 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4138         torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4139         torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4140                 "dm unequal");\
4141 } while(0);
4142
4143 #define test_sd(wname, iname) \
4144 do {\
4145         DATA_BLOB blob;\
4146         struct security_descriptor sd;\
4147         enum ndr_err_code ndr_err;\
4148         enum winreg_Type w_type;\
4149         uint32_t w_size;\
4150         uint32_t w_length;\
4151         uint8_t *w_data;\
4152         torture_assert(tctx,\
4153                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4154                                        &w_type, &w_size, &w_length, &w_data),\
4155                 "failed to query winreg");\
4156         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4157         blob = data_blob(w_data, w_size);\
4158         ndr_err = ndr_pull_struct_blob(&blob, tctx, lp_iconv_convenience(tctx->lp_ctx), &sd,\
4159                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4160         torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4161         torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4162                 "sd unequal");\
4163 } while(0);
4164
4165 #define test_multi_sz(wname, iname) \
4166 do {\
4167         DATA_BLOB blob;\
4168         const char **array;\
4169         enum winreg_Type w_type;\
4170         uint32_t w_size;\
4171         uint32_t w_length;\
4172         uint8_t *w_data;\
4173         int i;\
4174         torture_assert(tctx,\
4175                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4176                                        &w_type, &w_size, &w_length, &w_data),\
4177                 "failed to query winreg");\
4178         torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4179         blob = data_blob(w_data, w_size);\
4180         torture_assert(tctx, \
4181                 pull_reg_multi_sz(tctx, lp_iconv_convenience(tctx->lp_ctx), &blob, &array),\
4182                 "failed to pull multi sz");\
4183         for (i=0; array[i] != NULL; i++) {\
4184                 torture_assert_str_equal(tctx, array[i], iname[i],\
4185                         talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4186         }\
4187 } while(0);
4188
4189
4190         if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4191                                        TOP_LEVEL_CONTROL_PRINTERS_KEY,
4192                                        "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4193         {
4194                 torture_warning(tctx, "failed to check for winreg symlink");
4195         }
4196
4197
4198         for (i=0; i < ARRAY_SIZE(keys); i++) {
4199
4200                 const char *printer_key;
4201                 struct policy_handle key_handle;
4202
4203                 printer_key = talloc_asprintf(tctx, "%s\\%s",
4204                         keys[i], printer_name);
4205
4206                 torture_assert(tctx,
4207                         test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4208
4209                 test_sz("Name", printername);
4210                 test_sz("Share Name", sharename);
4211                 test_sz("Port", info.info2.portname);
4212                 test_sz("Printer Driver", info.info2.drivername);
4213                 test_sz("Description", info.info2.comment);
4214                 test_sz("Location", info.info2.location);
4215                 test_sz("Separator File", info.info2.sepfile);
4216                 test_sz("Print Processor", info.info2.printprocessor);
4217                 test_sz("Datatype", info.info2.datatype);
4218                 test_sz("Parameters", info.info2.parameters);
4219                 /* winreg: 0, spoolss not */
4220 /*              test_dword("Attributes", info.info2.attributes); */
4221                 test_dword("Priority", info.info2.priority);
4222                 test_dword("Default Priority", info.info2.defaultpriority);
4223                 /* winreg: 60, spoolss: 0 */
4224 /*              test_dword("StartTime", info.info2.starttime); */
4225 /*              test_dword("UntilTime", info.info2.untiltime); */
4226                 /* winreg != spoolss */
4227 /*              test_dword("Status", info.info2.status); */
4228                 test_dm("Default DevMode", info.info2.devmode);
4229                 test_sd("Security", info.info2.secdesc);
4230
4231                 torture_assert(tctx,
4232                         test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4233         }
4234
4235 #undef test_dm
4236 #undef test_sd
4237
4238         torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4239
4240         return true;
4241 }
4242
4243 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4244                                          struct dcerpc_binding_handle *b,
4245                                          struct policy_handle *handle,
4246                                          const char *driver_name,
4247                                          const char *architecture,
4248                                          uint32_t level,
4249                                          uint32_t client_major_version,
4250                                          uint32_t client_minor_version,
4251                                          union spoolss_DriverInfo *info_p,
4252                                          WERROR *result);
4253
4254 static const char *strip_path(const char *path)
4255 {
4256         char *p;
4257
4258         if (path == NULL) {
4259                 return NULL;
4260         }
4261
4262         p = strrchr(path, '\\');
4263         if (p) {
4264                 return p+1;
4265         }
4266
4267         return path;
4268 }
4269
4270 static const char **strip_paths(const char **path_array)
4271 {
4272         int i;
4273
4274         if (path_array == NULL) {
4275                 return NULL;
4276         }
4277
4278         for (i=0; path_array[i] != NULL; i++) {
4279                 path_array[i] = strip_path(path_array[i]);
4280         }
4281
4282         return path_array;
4283 }
4284
4285 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4286 {
4287         time_t t;
4288         struct tm *tm;
4289         t = nt_time_to_unix(nt);
4290         tm = localtime(&t);
4291
4292         return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4293                 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4294 }
4295
4296 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4297 {
4298         return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4299                 (unsigned)((v >> 48) & 0xFFFF),
4300                 (unsigned)((v >> 32) & 0xFFFF),
4301                 (unsigned)((v >> 16) & 0xFFFF),
4302                 (unsigned)(v & 0xFFFF));
4303 }
4304
4305 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4306                                       struct dcerpc_binding_handle *b,
4307                                       struct policy_handle *handle,
4308                                       const char *printer_name,
4309                                       const char *driver_name,
4310                                       const char *environment,
4311                                       struct dcerpc_binding_handle *winreg_handle,
4312                                       struct policy_handle *hive_handle)
4313 {
4314         WERROR result;
4315         union spoolss_DriverInfo info;
4316         const char *driver_key;
4317         struct policy_handle key_handle;
4318
4319         const char *driver_path;
4320         const char *data_file;
4321         const char *config_file;
4322         const char *help_file;
4323         const char **dependent_files;
4324
4325         const char *driver_date;
4326         const char *inbox_driver_date;
4327
4328         const char *driver_version;
4329         const char *inbox_driver_version;
4330
4331         torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4332
4333         driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4334                                      TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4335                                      environment,
4336                                      3,
4337                                      driver_name);
4338
4339         torture_assert(tctx,
4340                 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4341                 "failed to open driver key");
4342
4343         torture_assert(tctx,
4344                 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, 3, 0, &info, &result),
4345                 "failed to get driver info level 8");
4346
4347         if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4348                 goto try_level6;
4349         }
4350
4351         driver_path     = strip_path(info.info8.driver_path);
4352         data_file       = strip_path(info.info8.data_file);
4353         config_file     = strip_path(info.info8.config_file);
4354         help_file       = strip_path(info.info8.help_file);
4355         dependent_files = strip_paths(info.info8.dependent_files);
4356
4357         driver_date             = driver_winreg_date(tctx, info.info8.driver_date);
4358         inbox_driver_date       = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
4359
4360         driver_version          = driver_winreg_version(tctx, info.info8.driver_version);
4361         inbox_driver_version    = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
4362
4363         test_sz("Configuration File",           config_file);
4364         test_sz("Data File",                    data_file);
4365         test_sz("Datatype",                     info.info8.default_datatype);
4366         test_sz("Driver",                       driver_path);
4367         test_sz("DriverDate",                   driver_date);
4368         test_sz("DriverVersion",                driver_version);
4369         test_sz("HardwareID",                   info.info8.hardware_id);
4370         test_sz("Help File",                    help_file);
4371         test_sz("InfPath",                      info.info8.inf_path);
4372         test_sz("Manufacturer",                 info.info8.manufacturer_name);
4373         test_sz("MinInboxDriverVerDate",        inbox_driver_date);
4374         test_sz("MinInboxDriverVerVersion",     inbox_driver_version);
4375         test_sz("Monitor",                      info.info8.monitor_name);
4376         test_sz("OEM URL",                      info.info8.manufacturer_url);
4377         test_sz("Print Processor",              info.info8.print_processor);
4378         test_sz("Provider",                     info.info8.provider);
4379         test_sz("VendorSetup",                  info.info8.vendor_setup);
4380         test_multi_sz("ColorProfiles",          info.info8.color_profiles);
4381         test_multi_sz("Dependent Files",        dependent_files);
4382         test_multi_sz("CoreDependencies",       info.info8.core_driver_dependencies);
4383         test_multi_sz("Previous Names",         info.info8.previous_names);
4384 /*      test_dword("Attributes",                ?); */
4385         test_dword("PrinterDriverAttributes",   info.info8.printer_driver_attributes);
4386         test_dword("Version",                   info.info8.version);
4387 /*      test_dword("TempDir",                   ?); */
4388
4389  try_level6:
4390
4391         torture_assert(tctx,
4392                 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, 3, 0, &info, &result),
4393                 "failed to get driver info level 6");
4394
4395         driver_path     = strip_path(info.info6.driver_path);
4396         data_file       = strip_path(info.info6.data_file);
4397         config_file     = strip_path(info.info6.config_file);
4398         help_file       = strip_path(info.info6.help_file);
4399         dependent_files = strip_paths(info.info6.dependent_files);
4400
4401         driver_date             = driver_winreg_date(tctx, info.info6.driver_date);
4402
4403         driver_version          = driver_winreg_version(tctx, info.info6.driver_version);
4404
4405         test_sz("Configuration File",           config_file);
4406         test_sz("Data File",                    data_file);
4407         test_sz("Datatype",                     info.info6.default_datatype);
4408         test_sz("Driver",                       driver_path);
4409         test_sz("DriverDate",                   driver_date);
4410         test_sz("DriverVersion",                driver_version);
4411         test_sz("HardwareID",                   info.info6.hardware_id);
4412         test_sz("Help File",                    help_file);
4413         test_sz("Manufacturer",                 info.info6.manufacturer_name);
4414         test_sz("Monitor",                      info.info6.monitor_name);
4415         test_sz("OEM URL",                      info.info6.manufacturer_url);
4416         test_sz("Provider",                     info.info6.provider);
4417         test_multi_sz("Dependent Files",        dependent_files);
4418         test_multi_sz("Previous Names",         info.info6.previous_names);
4419 /*      test_dword("Attributes",                ?); */
4420         test_dword("Version",                   info.info6.version);
4421 /*      test_dword("TempDir",                   ?); */
4422
4423         torture_assert(tctx,
4424                 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4425
4426         torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
4427
4428         return true;
4429 }
4430
4431 #undef test_sz
4432 #undef test_dword
4433
4434 static bool test_SetPrinterData(struct torture_context *tctx,
4435                                 struct dcerpc_binding_handle *b,
4436                                 struct policy_handle *handle,
4437                                 const char *value_name,
4438                                 enum winreg_Type type,
4439                                 uint8_t *data,
4440                                 uint32_t offered)
4441 {
4442         struct spoolss_SetPrinterData r;
4443
4444         r.in.handle = handle;
4445         r.in.value_name = value_name;
4446         r.in.type = type;
4447         r.in.data = data;
4448         r.in.offered = offered;
4449
4450         torture_comment(tctx, "Testing SetPrinterData(%s)\n",
4451                 r.in.value_name);
4452
4453         torture_assert_ntstatus_ok(tctx,
4454                 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
4455                 "SetPrinterData failed");
4456         torture_assert_werr_ok(tctx, r.out.result,
4457                 "SetPrinterData failed");
4458
4459         return true;
4460 }
4461
4462 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
4463                                        struct dcerpc_binding_handle *b,
4464                                        struct policy_handle *handle,
4465                                        const char *printer_name,
4466                                        struct dcerpc_binding_handle *winreg_handle,
4467                                        struct policy_handle *hive_handle)
4468 {
4469         const char *values[] = {
4470                 "spootyfoot",
4471                 "spooty\\foot",
4472 #if 0
4473         /* FIXME: not working with s3 atm. */
4474                 "spooty,foot",
4475                 "spooty,fo,ot",
4476 #endif
4477                 "spooty foot",
4478 #if 0
4479         /* FIXME: not working with s3 atm. */
4480                 "spooty\\fo,ot",
4481                 "spooty,fo\\ot"
4482 #endif
4483         };
4484         int i;
4485
4486         for (i=0; i < ARRAY_SIZE(values); i++) {
4487
4488                 enum winreg_Type type;
4489                 DATA_BLOB blob;
4490                 uint8_t *data;
4491                 uint32_t needed;
4492
4493                 torture_assert(tctx,
4494                         reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
4495                                           "REG_SZ", "dog", &type, &blob), "");
4496
4497                 torture_assert(tctx,
4498                         test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
4499                         "SetPrinterData failed");
4500
4501                 torture_assert(tctx,
4502                         test_GetPrinterData(tctx, b, handle, values[i], &type, &data, &needed),
4503                         "GetPrinterData failed");
4504
4505                 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
4506                 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
4507                 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
4508
4509                 if (winreg_handle && hive_handle) {
4510
4511                         enum winreg_Type w_type;
4512                         uint32_t w_size;
4513                         uint32_t w_length;
4514                         uint8_t *w_data;
4515
4516                         torture_assert(tctx,
4517                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4518                                         printer_name, "PrinterDriverData", values[i],
4519                                         &w_type, &w_size, &w_length, &w_data), "");
4520
4521                         torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
4522                         torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
4523                         torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
4524                         torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
4525                 }
4526
4527                 torture_assert(tctx,
4528                         test_DeletePrinterData(tctx, b, handle, values[i]),
4529                         "DeletePrinterData failed");
4530         }
4531
4532         return true;
4533 }
4534
4535
4536 static bool test_EnumPrinterKey(struct torture_context *tctx,
4537                                 struct dcerpc_binding_handle *b,
4538                                 struct policy_handle *handle,
4539                                 const char *key_name,
4540                                 const char ***array);
4541
4542 static bool test_SetPrinterDataEx(struct torture_context *tctx,
4543                                   struct dcerpc_binding_handle *b,
4544                                   struct policy_handle *handle,
4545                                   const char *key_name,
4546                                   const char *value_name,
4547                                   enum winreg_Type type,
4548                                   uint8_t *data,
4549                                   uint32_t offered)
4550 {
4551         NTSTATUS status;
4552         struct spoolss_SetPrinterDataEx r;
4553
4554         r.in.handle = handle;
4555         r.in.key_name = key_name;
4556         r.in.value_name = value_name;
4557         r.in.type = type;
4558         r.in.data = data;
4559         r.in.offered = offered;
4560
4561         torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
4562                 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
4563
4564         status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
4565
4566         torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
4567         torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
4568
4569         return true;
4570 }
4571
4572 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
4573                                          struct dcerpc_pipe *p,
4574                                          struct policy_handle *handle,
4575                                          const char *printername,
4576                                          struct dcerpc_binding_handle *winreg_handle,
4577                                          struct policy_handle *hive_handle)
4578 {
4579         struct dcerpc_binding_handle *b = p->binding_handle;
4580         const char *value_name = "dog";
4581         const char *keys[] = {
4582                 "torturedataex",
4583                 "torture data ex",
4584 #if 0
4585         /* FIXME: not working with s3 atm. */
4586                 "torturedataex_with_subkey\\subkey",
4587                 "torturedataex_with_subkey\\subkey:0",
4588                 "torturedataex_with_subkey\\subkey:1",
4589                 "torturedataex_with_subkey\\subkey\\subsubkey",
4590                 "torturedataex_with_subkey\\subkey\\subsubkey:0",
4591                 "torturedataex_with_subkey\\subkey\\subsubkey:1",
4592 #endif
4593                 "torture,data",
4594 #if 0
4595         /* FIXME: not working with s3 atm. */
4596
4597                 "torture,data,ex",
4598                 "torture,data\\ex",
4599                 "torture\\data,ex"
4600 #endif
4601         };
4602         enum winreg_Type types[] = {
4603                 REG_SZ,
4604                 REG_MULTI_SZ,
4605                 REG_DWORD,
4606                 REG_BINARY
4607         };
4608         const char *str = "abcdefghijklmnopqrstuvwxzy";
4609         int i, t, s;
4610
4611
4612         for (i=0; i < ARRAY_SIZE(keys); i++) {
4613         for (t=0; t < ARRAY_SIZE(types); t++) {
4614         for (s=0; s < strlen(str); s++) {
4615
4616                 char *c;
4617                 const char *key;
4618                 enum winreg_Type type;
4619                 const char *string = talloc_strndup(tctx, str, s);
4620                 DATA_BLOB blob = data_blob_string_const(string);
4621                 const char **subkeys;
4622                 DATA_BLOB data;
4623                 uint8_t *data_out;
4624                 uint32_t needed, offered = 0;
4625                 uint32_t ecount;
4626                 struct spoolss_PrinterEnumValues *einfo;
4627
4628                 if (types[t] == REG_DWORD) {
4629                         s = 0xffff;
4630                 }
4631
4632                 if (torture_setting_bool(tctx, "samba3", false)) {
4633                         if ((types[t] == REG_MULTI_SZ) && s == 0) {
4634                                 torture_warning(tctx, "samba3 does not handle 4 byte emtpy REG_MULTI_SZ buffers");
4635                                 continue;
4636                         }
4637                 }
4638
4639                 switch (types[t]) {
4640                 case REG_BINARY:
4641                         data = blob;
4642                         offered = blob.length;
4643                         break;
4644                 case REG_DWORD:
4645                         data = data_blob_talloc(tctx, NULL, 4);
4646                         SIVAL(data.data, 0, 0x12345678);
4647                         offered = 4;
4648                         break;
4649                 case REG_SZ:
4650                         torture_assert(tctx,
4651                                 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
4652                                                   "REG_SZ", string, &type, &data), "");
4653                         offered = data.length;
4654                         /*strlen_m_term(data.string)*2;*/
4655                         break;
4656                 case REG_MULTI_SZ:
4657                         torture_assert(tctx,
4658                                 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
4659                                                   "REG_SZ", string, &type, &data), "");
4660                         torture_assert(tctx, data_blob_realloc(tctx, &data, data.length + 2), "");
4661                         memset(&data.data[data.length - 2], '\0', 2);
4662                         offered = data.length;
4663                         break;
4664                 default:
4665                         torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
4666                 }
4667
4668                 torture_assert(tctx,
4669                         test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, types[t], data.data, offered),
4670                         "failed to call SetPrinterDataEx");
4671
4672                 torture_assert(tctx,
4673                         test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &data_out, &needed),
4674                         "failed to call GetPrinterDataEx");
4675
4676                 torture_assert(tctx,
4677                         test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
4678                         "failed to call EnumPrinterDataEx");
4679
4680                 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
4681                 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
4682                 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
4683
4684                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
4685                 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
4686                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
4687                 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
4688                 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
4689                 if (einfo[0].data_length > 0) {
4690                         torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
4691                 }
4692
4693                 if (winreg_handle && hive_handle) {
4694                         enum winreg_Type w_type;
4695                         uint32_t w_size;
4696                         uint32_t w_length;
4697                         uint8_t *w_data;
4698
4699                         torture_assert(tctx,
4700                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4701                                         printername, keys[i], value_name,
4702                                         &w_type, &w_size, &w_length, &w_data), "");
4703
4704                         torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
4705                         torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
4706                         torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
4707                         torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
4708                 }
4709
4710                 key = talloc_strdup(tctx, keys[i]);
4711
4712                 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
4713                         return false;
4714                 }
4715
4716                 c = strchr(key, '\\');
4717                 if (c) {
4718                         int k;
4719
4720                         /* we have subkeys */
4721
4722                         *c = 0;
4723
4724                         if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
4725                                 return false;
4726                         }
4727
4728                         for (k=0; subkeys && subkeys[k]; k++) {
4729
4730                                 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
4731
4732                                 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
4733                                         return false;
4734                                 }
4735                         }
4736
4737                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4738                                 return false;
4739                         }
4740
4741                 } else {
4742                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4743                                 return false;
4744                         }
4745                 }
4746         }
4747         }
4748         }
4749
4750         return true;
4751 }
4752
4753 static bool test_PrinterData_winreg(struct torture_context *tctx,
4754                                     struct dcerpc_pipe *p,
4755                                     struct policy_handle *handle,
4756                                     const char *printer_name)
4757 {
4758         struct dcerpc_binding_handle *b = p->binding_handle;
4759         struct dcerpc_pipe *p2;
4760         bool ret = true;
4761         struct policy_handle hive_handle;
4762         struct dcerpc_binding_handle *b2;
4763
4764         torture_assert_ntstatus_ok(tctx,
4765                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4766                 "could not open winreg pipe");
4767         b2 = p2->binding_handle;
4768
4769         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4770
4771         ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
4772         ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
4773
4774         test_winreg_CloseKey(tctx, b2, &hive_handle);
4775
4776         talloc_free(p2);
4777
4778         return ret;
4779 }
4780
4781 static bool test_Forms_winreg(struct torture_context *tctx,
4782                               struct dcerpc_binding_handle *b,
4783                               struct policy_handle *handle,
4784                               bool print_server,
4785                               const char *printer_name)
4786 {
4787         struct dcerpc_pipe *p2;
4788         bool ret = true;
4789         struct policy_handle hive_handle;
4790         struct dcerpc_binding_handle *b2;
4791
4792         torture_assert_ntstatus_ok(tctx,
4793                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4794                 "could not open winreg pipe");
4795         b2 = p2->binding_handle;
4796
4797         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4798
4799         ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
4800
4801         test_winreg_CloseKey(tctx, b2, &hive_handle);
4802
4803         talloc_free(p2);
4804
4805         return ret;
4806 }
4807
4808 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
4809                                     struct dcerpc_pipe *p,
4810                                     struct policy_handle *handle,
4811                                     const char *printer_name)
4812 {
4813         struct dcerpc_binding_handle *b = p->binding_handle;
4814         struct dcerpc_pipe *p2;
4815         bool ret = true;
4816         struct policy_handle hive_handle;
4817         struct dcerpc_binding_handle *b2;
4818
4819         torture_assert_ntstatus_ok(tctx,
4820                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4821                 "could not open winreg pipe");
4822         b2 = p2->binding_handle;
4823
4824         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4825
4826         ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
4827
4828         test_winreg_CloseKey(tctx, b2, &hive_handle);
4829
4830         talloc_free(p2);
4831
4832         return ret;
4833 }
4834
4835 static bool test_DriverInfo_winreg(struct torture_context *tctx,
4836                                    struct dcerpc_pipe *p,
4837                                    struct policy_handle *handle,
4838                                    const char *printer_name,
4839                                    const char *driver_name,
4840                                    const char *environment)
4841 {
4842         struct dcerpc_binding_handle *b = p->binding_handle;
4843         struct dcerpc_pipe *p2;
4844         bool ret = true;
4845         struct policy_handle hive_handle;
4846         struct dcerpc_binding_handle *b2;
4847
4848         torture_assert_ntstatus_ok(tctx,
4849                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4850                 "could not open winreg pipe");
4851         b2 = p2->binding_handle;
4852
4853         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4854
4855         ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, b2, &hive_handle);
4856
4857         test_winreg_CloseKey(tctx, b2, &hive_handle);
4858
4859         talloc_free(p2);
4860
4861         return ret;
4862 }
4863
4864 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
4865                                          struct dcerpc_binding_handle *b,
4866                                          struct policy_handle *handle,
4867                                          uint32_t *change_id)
4868 {
4869         enum winreg_Type type;
4870         uint8_t *data;
4871         uint32_t needed;
4872
4873         torture_assert(tctx,
4874                 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
4875                 "failed to call GetPrinterData");
4876
4877         torture_assert(tctx, type == REG_DWORD, "unexpected type");
4878         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
4879
4880         *change_id = IVAL(data, 0);
4881
4882         return true;
4883 }
4884
4885 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
4886                                            struct dcerpc_pipe *p,
4887                                            struct policy_handle *handle,
4888                                            uint32_t *change_id)
4889 {
4890         enum winreg_Type type;
4891         uint8_t *data;
4892         uint32_t needed;
4893
4894         torture_assert(tctx,
4895                 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
4896                 "failed to call GetPrinterData");
4897
4898         torture_assert(tctx, type == REG_DWORD, "unexpected type");
4899         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
4900
4901         *change_id = IVAL(data, 0);
4902
4903         return true;
4904 }
4905
4906 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
4907                                          struct dcerpc_binding_handle *b,
4908                                          struct policy_handle *handle,
4909                                          uint32_t *change_id)
4910 {
4911         union spoolss_PrinterInfo info;
4912
4913         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
4914                 "failed to query Printer level 0");
4915
4916         *change_id = info.info0.change_id;
4917
4918         return true;
4919 }
4920
4921 static bool test_ChangeID(struct torture_context *tctx,
4922                           struct dcerpc_pipe *p,
4923                           struct policy_handle *handle)
4924 {
4925         uint32_t change_id, change_id_ex, change_id_info;
4926         uint32_t change_id2, change_id_ex2, change_id_info2;
4927         union spoolss_PrinterInfo info;
4928         const char *comment;
4929         struct dcerpc_binding_handle *b = p->binding_handle;
4930
4931         torture_comment(tctx, "Testing ChangeID: id change test #1\n");
4932
4933         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
4934                 "failed to query for ChangeID");
4935         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
4936                 "failed to query for ChangeID");
4937         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
4938                 "failed to query for ChangeID");
4939
4940         torture_assert_int_equal(tctx, change_id, change_id_ex,
4941                 "change_ids should all be equal");
4942         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
4943                 "change_ids should all be equal");
4944
4945
4946         torture_comment(tctx, "Testing ChangeID: id change test #2\n");
4947
4948         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
4949                 "failed to query for ChangeID");
4950         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
4951                 "failed to query Printer level 2");
4952         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
4953                 "failed to query for ChangeID");
4954         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
4955                 "failed to query for ChangeID");
4956         torture_assert_int_equal(tctx, change_id, change_id_ex,
4957                 "change_id should not have changed");
4958         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
4959                 "change_id should not have changed");
4960
4961
4962         torture_comment(tctx, "Testing ChangeID: id change test #3\n");
4963
4964         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
4965                 "failed to query for ChangeID");
4966         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
4967                 "failed to query for ChangeID");
4968         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
4969                 "failed to query for ChangeID");
4970         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
4971                 "failed to query Printer level 2");
4972         comment = talloc_strdup(tctx, info.info2.comment);
4973
4974         {
4975                 struct spoolss_SetPrinterInfoCtr info_ctr;
4976                 struct spoolss_DevmodeContainer devmode_ctr;
4977                 struct sec_desc_buf secdesc_ctr;
4978                 union spoolss_SetPrinterInfo sinfo;
4979
4980                 ZERO_STRUCT(info_ctr);
4981                 ZERO_STRUCT(devmode_ctr);
4982                 ZERO_STRUCT(secdesc_ctr);
4983
4984
4985                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
4986                 sinfo.info2->comment    = "torture_comment";
4987
4988                 info_ctr.level = 2;
4989                 info_ctr.info = sinfo;
4990
4991                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
4992                         "failed to call SetPrinter");
4993
4994                 sinfo.info2->comment    = comment;
4995
4996                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
4997                         "failed to call SetPrinter");
4998
4999         }
5000
5001         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5002                 "failed to query for ChangeID");
5003         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5004                 "failed to query for ChangeID");
5005         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5006                 "failed to query for ChangeID");
5007
5008         torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5009                 "change_ids should all be equal");
5010         torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5011                 "change_ids should all be equal");
5012
5013         torture_assert(tctx, (change_id < change_id2),
5014                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5015                 change_id2, change_id));
5016         torture_assert(tctx, (change_id_ex < change_id_ex2),
5017                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5018                 change_id_ex2, change_id_ex));
5019         torture_assert(tctx, (change_id_info < change_id_info2),
5020                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5021                 change_id_info2, change_id_info));
5022
5023         torture_comment(tctx, "ChangeID tests succeeded\n\n");
5024
5025         return true;
5026 }
5027
5028 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5029                                        struct dcerpc_pipe *p,
5030                                        struct policy_handle *handle)
5031 {
5032         NTSTATUS status;
5033         struct dcerpc_binding *b;
5034         struct dcerpc_pipe *p2;
5035         struct spoolss_ClosePrinter cp;
5036
5037         /* only makes sense on SMB */
5038         if (p->conn->transport.transport != NCACN_NP) {
5039                 return true;
5040         }
5041
5042         torture_comment(tctx, "Testing close on secondary pipe\n");
5043
5044         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
5045         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
5046
5047         status = dcerpc_secondary_connection(p, &p2, b);
5048         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
5049
5050         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
5051         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
5052
5053         cp.in.handle = handle;
5054         cp.out.handle = handle;
5055
5056         status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
5057         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
5058                         "ERROR: Allowed close on secondary connection");
5059
5060         talloc_free(p2);
5061
5062         return true;
5063 }
5064
5065 static bool test_OpenPrinter_badname(struct torture_context *tctx,
5066                                      struct dcerpc_binding_handle *b, const char *name)
5067 {
5068         NTSTATUS status;
5069         struct spoolss_OpenPrinter op;
5070         struct spoolss_OpenPrinterEx opEx;
5071         struct policy_handle handle;
5072         bool ret = true;
5073
5074         op.in.printername       = name;
5075         op.in.datatype          = NULL;
5076         op.in.devmode_ctr.devmode= NULL;
5077         op.in.access_mask       = 0;
5078         op.out.handle           = &handle;
5079
5080         torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
5081
5082         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
5083         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5084         torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
5085                 "unexpected result");
5086
5087         if (W_ERROR_IS_OK(op.out.result)) {
5088                 ret &=test_ClosePrinter(tctx, b, &handle);
5089         }
5090
5091         opEx.in.printername             = name;
5092         opEx.in.datatype                = NULL;
5093         opEx.in.devmode_ctr.devmode     = NULL;
5094         opEx.in.access_mask             = 0;
5095         opEx.in.level                   = 1;
5096         opEx.in.userlevel.level1        = NULL;
5097         opEx.out.handle                 = &handle;
5098
5099         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
5100
5101         status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
5102         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5103         torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
5104                 "unexpected result");
5105
5106         if (W_ERROR_IS_OK(opEx.out.result)) {
5107                 ret &=test_ClosePrinter(tctx, b, &handle);
5108         }
5109
5110         return ret;
5111 }
5112
5113 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
5114                                           struct dcerpc_binding_handle *b,
5115                                           const char *server_name)
5116 {
5117         const char *badnames[] = {
5118                 "__INVALID_PRINTER__",
5119                 "\\\\__INVALID_HOST__",
5120                 "",
5121                 "\\\\\\",
5122                 "\\\\\\__INVALID_PRINTER__"
5123         };
5124         const char *badname;
5125         int i;
5126
5127         for (i=0; i < ARRAY_SIZE(badnames); i++) {
5128                 torture_assert(tctx,
5129                         test_OpenPrinter_badname(tctx, b, badnames[i]),
5130                         "");
5131         }
5132
5133         badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
5134         torture_assert(tctx,
5135                 test_OpenPrinter_badname(tctx, b, badname),
5136                 "");
5137
5138         badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
5139         torture_assert(tctx,
5140                 test_OpenPrinter_badname(tctx, b, badname),
5141                 "");
5142
5143         return true;
5144 }
5145
5146 static bool test_OpenPrinter(struct torture_context *tctx,
5147                              struct dcerpc_pipe *p,
5148                              const char *name,
5149                              const char *environment)
5150 {
5151         NTSTATUS status;
5152         struct spoolss_OpenPrinter r;
5153         struct policy_handle handle;
5154         bool ret = true;
5155         struct dcerpc_binding_handle *b = p->binding_handle;
5156
5157         r.in.printername        = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
5158         r.in.datatype           = NULL;
5159         r.in.devmode_ctr.devmode= NULL;
5160         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
5161         r.out.handle            = &handle;
5162
5163         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5164
5165         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5166
5167         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5168
5169         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5170
5171         if (!test_GetPrinter(tctx, b, &handle, environment)) {
5172                 ret = false;
5173         }
5174
5175         if (!torture_setting_bool(tctx, "samba3", false)) {
5176                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5177                         ret = false;
5178                 }
5179         }
5180
5181         if (!test_ClosePrinter(tctx, b, &handle)) {
5182                 ret = false;
5183         }
5184
5185         return ret;
5186 }
5187
5188 static bool call_OpenPrinterEx(struct torture_context *tctx,
5189                                struct dcerpc_pipe *p,
5190                                const char *name,
5191                                struct spoolss_DeviceMode *devmode,
5192                                struct policy_handle *handle)
5193 {
5194         struct spoolss_OpenPrinterEx r;
5195         struct spoolss_UserLevel1 userlevel1;
5196         NTSTATUS status;
5197         struct dcerpc_binding_handle *b = p->binding_handle;
5198
5199         if (name && name[0]) {
5200                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
5201                                                    dcerpc_server_name(p), name);
5202         } else {
5203                 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
5204                                                    dcerpc_server_name(p));
5205         }
5206
5207         r.in.datatype           = NULL;
5208         r.in.devmode_ctr.devmode= devmode;
5209         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
5210         r.in.level              = 1;
5211         r.in.userlevel.level1   = &userlevel1;
5212         r.out.handle = handle;
5213
5214         userlevel1.size = 1234;
5215         userlevel1.client = "hello";
5216         userlevel1.user = "spottyfoot!";
5217         userlevel1.build = 1;
5218         userlevel1.major = 2;
5219         userlevel1.minor = 3;
5220         userlevel1.processor = 4;
5221
5222         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5223
5224         status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r);
5225
5226         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5227
5228         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
5229
5230         return true;
5231 }
5232
5233 static bool test_printer_rename(struct torture_context *tctx,
5234                                 struct dcerpc_pipe *p,
5235                                 struct policy_handle *handle,
5236                                 const char *name)
5237 {
5238         bool ret = true;
5239         union spoolss_PrinterInfo info;
5240         union spoolss_SetPrinterInfo sinfo;
5241         struct spoolss_SetPrinterInfoCtr info_ctr;
5242         struct spoolss_DevmodeContainer devmode_ctr;
5243         struct sec_desc_buf secdesc_ctr;
5244         const char *printer_name;
5245         const char *printer_name_orig;
5246         const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5247         struct policy_handle new_handle;
5248         const char *q;
5249         struct dcerpc_binding_handle *b = p->binding_handle;
5250
5251         ZERO_STRUCT(devmode_ctr);
5252         ZERO_STRUCT(secdesc_ctr);
5253
5254         torture_comment(tctx, "Testing Printer rename operations\n");
5255
5256         torture_assert(tctx,
5257                 test_GetPrinter_level(tctx, b, handle, 2, &info),
5258                 "failed to call GetPrinter level 2");
5259
5260         printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5261
5262         q = strrchr(info.info2.printername, '\\');
5263         if (q) {
5264                 torture_warning(tctx,
5265                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5266         }
5267
5268         torture_assert(tctx,
5269                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5270
5271         sinfo.info2->printername = printer_name_new;
5272
5273         info_ctr.level = 2;
5274         info_ctr.info = sinfo;
5275
5276         torture_assert(tctx,
5277                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5278                 "failed to call SetPrinter level 2");
5279
5280         torture_assert(tctx,
5281                 test_GetPrinter_level(tctx, b, handle, 2, &info),
5282                 "failed to call GetPrinter level 2");
5283
5284         printer_name = talloc_strdup(tctx, info.info2.printername);
5285
5286         q = strrchr(info.info2.printername, '\\');
5287         if (q) {
5288                 torture_warning(tctx,
5289                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5290                 q++;
5291                 printer_name = q;
5292         }
5293
5294         torture_assert_str_equal(tctx, printer_name, printer_name_new,
5295                 "new printer name was not set");
5296
5297         /* samba currently cannot fully rename printers */
5298         if (!torture_setting_bool(tctx, "samba3", false)) {
5299                 torture_assert(tctx,
5300                         test_OpenPrinter_badname(tctx, b, printer_name_orig),
5301                         "still can open printer with oldname after rename");
5302         } else {
5303                 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
5304         }
5305
5306         torture_assert(tctx,
5307                 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
5308                 "failed to open printer with new name");
5309
5310         torture_assert(tctx,
5311                 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
5312                 "failed to call GetPrinter level 2");
5313
5314         /* FIXME: we openend with servername! */
5315         printer_name = talloc_asprintf(tctx, "\\\\%s\\%s",
5316                 dcerpc_server_name(p), printer_name_new);
5317
5318         torture_assert_str_equal(tctx, info.info2.printername, printer_name,
5319                 "new printer name was not set");
5320
5321         torture_assert(tctx,
5322                 test_ClosePrinter(tctx, b, &new_handle),
5323                 "failed to close printer");
5324
5325         torture_comment(tctx, "Printer rename operations test succeeded\n\n");
5326
5327         return ret;
5328 }
5329
5330
5331 static bool test_OpenPrinterEx(struct torture_context *tctx,
5332                                struct dcerpc_pipe *p,
5333                                const char *name,
5334                                const char *environment)
5335 {
5336         struct policy_handle handle;
5337         bool ret = true;
5338         struct dcerpc_binding_handle *b = p->binding_handle;
5339
5340         if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
5341                 return false;
5342         }
5343
5344         if (!test_PrinterInfo_SD(tctx, b, &handle)) {
5345                 ret = false;
5346         }
5347
5348         if (!test_GetPrinter(tctx, b, &handle, environment)) {
5349                 ret = false;
5350         }
5351
5352         if (!test_EnumForms_all(tctx, b, &handle, false)) {
5353                 ret = false;
5354         }
5355
5356         if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
5357                 ret = false;
5358         }
5359
5360         if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
5361                 ret = false;
5362         }
5363
5364         if (!test_EnumPrinterData_all(tctx, p, &handle)) {
5365                 ret = false;
5366         }
5367
5368         if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
5369                 ret = false;
5370         }
5371
5372         if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
5373                 ret = false;
5374         }
5375
5376         if (!test_printer_keys(tctx, b, &handle)) {
5377                 ret = false;
5378         }
5379
5380         if (!test_PausePrinter(tctx, b, &handle)) {
5381                 ret = false;
5382         }
5383
5384         if (!test_DoPrintTest(tctx, b, &handle)) {
5385                 ret = false;
5386         }
5387
5388         if (!test_ResumePrinter(tctx, b, &handle)) {
5389                 ret = false;
5390         }
5391
5392         if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
5393                 ret = false;
5394         }
5395
5396         if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
5397                 ret = false;
5398         }
5399
5400         if (!torture_setting_bool(tctx, "samba3", false)) {
5401                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5402                         ret = false;
5403                 }
5404         }
5405
5406         if (!test_ClosePrinter(tctx, b, &handle)) {
5407                 ret = false;
5408         }
5409
5410         return ret;
5411 }
5412
5413 static bool test_EnumPrinters_old(struct torture_context *tctx,
5414                                   struct dcerpc_pipe *p,
5415                                   const char *environment)
5416 {
5417         struct spoolss_EnumPrinters r;
5418         NTSTATUS status;
5419         uint16_t levels[] = {1, 2, 4, 5};
5420         int i;
5421         bool ret = true;
5422         struct dcerpc_binding_handle *b = p->binding_handle;
5423
5424         for (i=0;i<ARRAY_SIZE(levels);i++) {
5425                 union spoolss_PrinterInfo *info;
5426                 int j;
5427                 uint32_t needed;
5428                 uint32_t count;
5429
5430                 r.in.flags      = PRINTER_ENUM_LOCAL;
5431                 r.in.server     = "";
5432                 r.in.level      = levels[i];
5433                 r.in.buffer     = NULL;
5434                 r.in.offered    = 0;
5435                 r.out.needed    = &needed;
5436                 r.out.count     = &count;
5437                 r.out.info      = &info;
5438
5439                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
5440
5441                 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
5442                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
5443
5444                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5445                         DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5446                         r.in.buffer = &blob;
5447                         r.in.offered = needed;
5448                         status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
5449                 }
5450
5451                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
5452
5453                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
5454
5455                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
5456
5457                 if (!info) {
5458                         torture_comment(tctx, "No printers returned\n");
5459                         return true;
5460                 }
5461
5462                 for (j=0;j<count;j++) {
5463                         if (r.in.level == 1) {
5464                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
5465                                 char *slash, *name;
5466                                 name = unc;
5467                                 if (unc[0] == '\\' && unc[1] == '\\') {
5468                                         unc +=2;
5469                                 }
5470                                 slash = strchr(unc, '\\');
5471                                 if (slash) {
5472                                         slash++;
5473                                         name = slash;
5474                                 }
5475                                 if (!test_OpenPrinter(tctx, p, name, environment)) {
5476                                         ret = false;
5477                                 }
5478                                 if (!test_OpenPrinterEx(tctx, p, name, environment)) {
5479                                         ret = false;
5480                                 }
5481                         }
5482                 }
5483         }
5484
5485         return ret;
5486 }
5487
5488 static bool test_GetPrinterDriver(struct torture_context *tctx,
5489                                   struct dcerpc_binding_handle *b,
5490                                   struct policy_handle *handle,
5491                                   const char *driver_name)
5492 {
5493         struct spoolss_GetPrinterDriver r;
5494         uint32_t needed;
5495
5496         r.in.handle = handle;
5497         r.in.architecture = "W32X86";
5498         r.in.level = 1;
5499         r.in.buffer = NULL;
5500         r.in.offered = 0;
5501         r.out.needed = &needed;
5502
5503         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
5504
5505         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
5506                 "failed to call GetPrinterDriver");
5507         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5508                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5509                 r.in.buffer = &blob;
5510                 r.in.offered = needed;
5511                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
5512                         "failed to call GetPrinterDriver");
5513         }
5514
5515         torture_assert_werr_ok(tctx, r.out.result,
5516                 "failed to call GetPrinterDriver");
5517
5518         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
5519
5520         return true;
5521 }
5522
5523 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
5524                                          struct dcerpc_binding_handle *b,
5525                                          struct policy_handle *handle,
5526                                          const char *driver_name,
5527                                          const char *architecture,
5528                                          uint32_t level,
5529                                          uint32_t client_major_version,
5530                                          uint32_t client_minor_version,
5531                                          union spoolss_DriverInfo *info_p,
5532                                          WERROR *result_p)
5533
5534 {
5535         struct spoolss_GetPrinterDriver2 r;
5536         uint32_t needed;
5537         uint32_t server_major_version;
5538         uint32_t server_minor_version;
5539
5540         r.in.handle = handle;
5541         r.in.architecture = architecture;
5542         r.in.client_major_version = client_major_version;
5543         r.in.client_minor_version = client_minor_version;
5544         r.in.buffer = NULL;
5545         r.in.offered = 0;
5546         r.in.level = level;
5547         r.out.needed = &needed;
5548         r.out.server_major_version = &server_major_version;
5549         r.out.server_minor_version = &server_minor_version;
5550
5551         torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
5552                 driver_name, r.in.level);
5553
5554         torture_assert_ntstatus_ok(tctx,
5555                 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
5556                 "failed to call GetPrinterDriver2");
5557         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5558                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5559                 r.in.buffer = &blob;
5560                 r.in.offered = needed;
5561                 torture_assert_ntstatus_ok(tctx,
5562                         dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
5563                         "failed to call GetPrinterDriver2");
5564         }
5565
5566         if (result_p) {
5567                 *result_p = r.out.result;
5568         }
5569
5570         if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
5571                 switch (r.in.level) {
5572                 case 101:
5573                 case 8:
5574                         torture_comment(tctx,
5575                                 "level %d not implemented, not considering as an error\n",
5576                                 r.in.level);
5577                         return true;
5578                 default:
5579                         break;
5580                 }
5581         }
5582
5583         torture_assert_werr_ok(tctx, r.out.result,
5584                 "failed to call GetPrinterDriver2");
5585
5586         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
5587
5588         if (info_p) {
5589                 *info_p = *r.out.info;
5590         }
5591
5592         return true;
5593 }
5594
5595 static bool test_GetPrinterDriver2(struct torture_context *tctx,
5596                                    struct dcerpc_binding_handle *b,
5597                                    struct policy_handle *handle,
5598                                    const char *driver_name,
5599                                    const char *architecture)
5600 {
5601         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
5602         int i;
5603
5604
5605         for (i=0;i<ARRAY_SIZE(levels);i++) {
5606
5607                 torture_assert(tctx,
5608                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
5609                         "");
5610         }
5611
5612         return true;
5613 }
5614
5615 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
5616                                         struct dcerpc_pipe *p,
5617                                         const char *environment)
5618 {
5619         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
5620         int i;
5621         struct dcerpc_binding_handle *b = p->binding_handle;
5622         const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
5623
5624         for (i=0;i<ARRAY_SIZE(levels);i++) {
5625
5626                 uint32_t count;
5627                 union spoolss_DriverInfo *info;
5628
5629                 torture_assert(tctx,
5630                         test_EnumPrinterDrivers_args(tctx, b, server_name, environment, levels[i], &count, &info),
5631                         "failed to enumerate drivers");
5632
5633                 if (!info) {
5634                         torture_comment(tctx, "No printer drivers returned\n");
5635                         break;
5636                 }
5637         }
5638
5639         return true;
5640 }
5641
5642 static bool test_DeletePrinter(struct torture_context *tctx,
5643                                struct dcerpc_binding_handle *b,
5644                                struct policy_handle *handle)
5645 {
5646         struct spoolss_DeletePrinter r;
5647
5648         torture_comment(tctx, "Testing DeletePrinter\n");
5649
5650         r.in.handle = handle;
5651
5652         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
5653                 "failed to delete printer");
5654         torture_assert_werr_ok(tctx, r.out.result,
5655                 "failed to delete printer");
5656
5657         return true;
5658 }
5659
5660 static bool test_EnumPrinters_findname(struct torture_context *tctx,
5661                                        struct dcerpc_binding_handle *b,
5662                                        uint32_t flags,
5663                                        uint32_t level,
5664                                        const char *name,
5665                                        bool *found)
5666 {
5667         struct spoolss_EnumPrinters e;
5668         uint32_t count;
5669         union spoolss_PrinterInfo *info;
5670         uint32_t needed;
5671         int i;
5672
5673         *found = false;
5674
5675         e.in.flags = flags;
5676         e.in.server = NULL;
5677         e.in.level = level;
5678         e.in.buffer = NULL;
5679         e.in.offered = 0;
5680         e.out.count = &count;
5681         e.out.info = &info;
5682         e.out.needed = &needed;
5683
5684         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
5685                 "failed to enum printers");
5686
5687         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
5688                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5689                 e.in.buffer = &blob;
5690                 e.in.offered = needed;
5691
5692                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
5693                         "failed to enum printers");
5694         }
5695
5696         torture_assert_werr_ok(tctx, e.out.result,
5697                 "failed to enum printers");
5698
5699         for (i=0; i < count; i++) {
5700
5701                 const char *current = NULL;
5702                 const char *q;
5703
5704                 switch (level) {
5705                 case 1:
5706                         current = info[i].info1.name;
5707                         break;
5708                 }
5709
5710                 if (strequal(current, name)) {
5711                         *found = true;
5712                         break;
5713                 }
5714
5715                 q = strrchr(current, '\\');
5716                 if (q) {
5717                         if (!e.in.server) {
5718                                 torture_warning(tctx,
5719                                         "server returns printername %s incl. servername although we did not set servername", current);
5720                         }
5721                         q++;
5722                         if (strequal(q, name)) {
5723                                 *found = true;
5724                                 break;
5725                         }
5726                 }
5727         }
5728
5729         return true;
5730 }
5731
5732 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
5733                                       struct dcerpc_pipe *p,
5734                                       const char *printername,
5735                                       bool ex)
5736 {
5737         WERROR result;
5738         struct spoolss_AddPrinter r;
5739         struct spoolss_AddPrinterEx rex;
5740         struct spoolss_SetPrinterInfoCtr info_ctr;
5741         struct spoolss_SetPrinterInfo1 info1;
5742         struct spoolss_DevmodeContainer devmode_ctr;
5743         struct sec_desc_buf secdesc_ctr;
5744         struct spoolss_UserLevelCtr userlevel_ctr;
5745         struct policy_handle handle;
5746         bool found = false;
5747         struct dcerpc_binding_handle *b = p->binding_handle;
5748
5749         ZERO_STRUCT(devmode_ctr);
5750         ZERO_STRUCT(secdesc_ctr);
5751         ZERO_STRUCT(userlevel_ctr);
5752         ZERO_STRUCT(info1);
5753
5754         torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
5755
5756         /* try to add printer to wellknown printer list (level 1) */
5757
5758         userlevel_ctr.level = 1;
5759
5760         info_ctr.info.info1 = &info1;
5761         info_ctr.level = 1;
5762
5763         rex.in.server = NULL;
5764         rex.in.info_ctr = &info_ctr;
5765         rex.in.devmode_ctr = &devmode_ctr;
5766         rex.in.secdesc_ctr = &secdesc_ctr;
5767         rex.in.userlevel_ctr = &userlevel_ctr;
5768         rex.out.handle = &handle;
5769
5770         r.in.server = NULL;
5771         r.in.info_ctr = &info_ctr;
5772         r.in.devmode_ctr = &devmode_ctr;
5773         r.in.secdesc_ctr = &secdesc_ctr;
5774         r.out.handle = &handle;
5775
5776         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5777                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5778                 "failed to add printer");
5779         result = ex ? rex.out.result : r.out.result;
5780         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
5781                 "unexpected result code");
5782
5783         info1.name = printername;
5784         info1.flags = PRINTER_ATTRIBUTE_SHARED;
5785
5786         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5787                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5788                 "failed to add printer");
5789         result = ex ? rex.out.result : r.out.result;
5790         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
5791                 "unexpected result code");
5792
5793         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
5794            better do a real check to see the printer is really there */
5795
5796         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
5797                                                         PRINTER_ENUM_NETWORK, 1,
5798                                                         printername,
5799                                                         &found),
5800                         "failed to enum printers");
5801
5802         torture_assert(tctx, found, "failed to find newly added printer");
5803
5804         info1.flags = 0;
5805
5806         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5807                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5808                 "failed to add printer");
5809         result = ex ? rex.out.result : r.out.result;
5810         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
5811                 "unexpected result code");
5812
5813         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
5814            better do a real check to see the printer has really been removed
5815            from the well known printer list */
5816
5817         found = false;
5818
5819         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
5820                                                         PRINTER_ENUM_NETWORK, 1,
5821                                                         printername,
5822                                                         &found),
5823                         "failed to enum printers");
5824 #if 0
5825         torture_assert(tctx, !found, "printer still in well known printer list");
5826 #endif
5827         return true;
5828 }
5829
5830 static bool test_AddPrinter_normal(struct torture_context *tctx,
5831                                    struct dcerpc_pipe *p,
5832                                    struct policy_handle *handle_p,
5833                                    const char *printername,
5834                                    const char *drivername,
5835                                    const char *portname,
5836                                    bool ex)
5837 {
5838         WERROR result;
5839         struct spoolss_AddPrinter r;
5840         struct spoolss_AddPrinterEx rex;
5841         struct spoolss_SetPrinterInfoCtr info_ctr;
5842         struct spoolss_SetPrinterInfo2 info2;
5843         struct spoolss_DevmodeContainer devmode_ctr;
5844         struct sec_desc_buf secdesc_ctr;
5845         struct spoolss_UserLevelCtr userlevel_ctr;
5846         struct policy_handle handle;
5847         bool found = false;
5848         bool existing_printer_deleted = false;
5849         struct dcerpc_binding_handle *b = p->binding_handle;
5850
5851         ZERO_STRUCT(devmode_ctr);
5852         ZERO_STRUCT(secdesc_ctr);
5853         ZERO_STRUCT(userlevel_ctr);
5854
5855         torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
5856
5857         userlevel_ctr.level = 1;
5858
5859         rex.in.server = NULL;
5860         rex.in.info_ctr = &info_ctr;
5861         rex.in.devmode_ctr = &devmode_ctr;
5862         rex.in.secdesc_ctr = &secdesc_ctr;
5863         rex.in.userlevel_ctr = &userlevel_ctr;
5864         rex.out.handle = &handle;
5865
5866         r.in.server = NULL;
5867         r.in.info_ctr = &info_ctr;
5868         r.in.devmode_ctr = &devmode_ctr;
5869         r.in.secdesc_ctr = &secdesc_ctr;
5870         r.out.handle = &handle;
5871
5872  again:
5873
5874         /* try to add printer to printer list (level 2) */
5875
5876         ZERO_STRUCT(info2);
5877
5878         info_ctr.info.info2 = &info2;
5879         info_ctr.level = 2;
5880
5881         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5882                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5883                 "failed to add printer");
5884         result = ex ? rex.out.result : r.out.result;
5885         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
5886                 "unexpected result code");
5887
5888         info2.printername = printername;
5889
5890         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5891                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5892                 "failed to add printer");
5893         result = ex ? rex.out.result : r.out.result;
5894
5895         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
5896                 struct policy_handle printer_handle;
5897
5898                 if (existing_printer_deleted) {
5899                         torture_fail(tctx, "already deleted printer still existing?");
5900                 }
5901
5902                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
5903                         "failed to open printer handle");
5904
5905                 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
5906                         "failed to delete printer");
5907
5908                 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
5909                         "failed to close server handle");
5910
5911                 existing_printer_deleted = true;
5912
5913                 goto again;
5914         }
5915
5916         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
5917                 "unexpected result code");
5918
5919         info2.portname = portname;
5920
5921         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5922                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5923                 "failed to add printer");
5924         result = ex ? rex.out.result : r.out.result;
5925         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
5926                 "unexpected result code");
5927
5928         info2.drivername = drivername;
5929
5930         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5931                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5932                 "failed to add printer");
5933         result = ex ? rex.out.result : r.out.result;
5934
5935         /* w2k8r2 allows to add printer w/o defining printprocessor */
5936
5937         if (!W_ERROR_IS_OK(result)) {
5938                 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
5939                         "unexpected result code");
5940
5941                 info2.printprocessor = "winprint";
5942
5943                 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5944                                                       dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5945                         "failed to add printer");
5946                 result = ex ? rex.out.result : r.out.result;
5947                 torture_assert_werr_ok(tctx, result,
5948                         "failed to add printer");
5949         }
5950
5951         *handle_p = handle;
5952
5953         /* we are paranoid, really check if the printer is there now */
5954
5955         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
5956                                                         PRINTER_ENUM_LOCAL, 1,
5957                                                         printername,
5958                                                         &found),
5959                         "failed to enum printers");
5960         torture_assert(tctx, found, "failed to find newly added printer");
5961
5962         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5963                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5964                 "failed to add printer");
5965         result = ex ? rex.out.result : r.out.result;
5966         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
5967                 "unexpected result code");
5968
5969         return true;
5970 }
5971
5972 static bool test_AddPrinterEx(struct torture_context *tctx,
5973                               struct dcerpc_pipe *p,
5974                               struct policy_handle *handle_p,
5975                               const char *printername,
5976                               const char *drivername,
5977                               const char *portname)
5978 {
5979         bool ret = true;
5980
5981         if (!torture_setting_bool(tctx, "samba3", false)) {
5982                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
5983                         torture_comment(tctx, "failed to add printer to well known list\n");
5984                         ret = false;
5985                 }
5986         }
5987
5988         if (!test_AddPrinter_normal(tctx, p, handle_p,
5989                                     printername, drivername, portname,
5990                                     true)) {
5991                 torture_comment(tctx, "failed to add printer to printer list\n");
5992                 ret = false;
5993         }
5994
5995         return ret;
5996 }
5997
5998 static bool test_AddPrinter(struct torture_context *tctx,
5999                             struct dcerpc_pipe *p,
6000                             struct policy_handle *handle_p,
6001                             const char *printername,
6002                             const char *drivername,
6003                             const char *portname)
6004 {
6005         bool ret = true;
6006
6007         if (!torture_setting_bool(tctx, "samba3", false)) {
6008                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
6009                         torture_comment(tctx, "failed to add printer to well known list\n");
6010                         ret = false;
6011                 }
6012         }
6013
6014         if (!test_AddPrinter_normal(tctx, p, handle_p,
6015                                     printername, drivername, portname,
6016                                     false)) {
6017                 torture_comment(tctx, "failed to add printer to printer list\n");
6018                 ret = false;
6019         }
6020
6021         return ret;
6022 }
6023
6024 static bool test_printer_info(struct torture_context *tctx,
6025                               struct dcerpc_binding_handle *b,
6026                               struct policy_handle *handle)
6027 {
6028         bool ret = true;
6029
6030         if (torture_setting_bool(tctx, "samba3", false)) {
6031                 torture_skip(tctx, "skipping printer info cross tests against samba 3");
6032         }
6033
6034         if (!test_PrinterInfo(tctx, b, handle)) {
6035                 ret = false;
6036         }
6037
6038         if (!test_SetPrinter_errors(tctx, b, handle)) {
6039                 ret = false;
6040         }
6041
6042         return ret;
6043 }
6044
6045 static bool test_EnumPrinterKey(struct torture_context *tctx,
6046                                 struct dcerpc_binding_handle *b,
6047                                 struct policy_handle *handle,
6048                                 const char *key_name,
6049                                 const char ***array)
6050 {
6051         struct spoolss_EnumPrinterKey r;
6052         uint32_t needed = 0;
6053         union spoolss_KeyNames key_buffer;
6054         int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
6055         uint32_t _ndr_size;
6056         int i;
6057
6058         r.in.handle = handle;
6059         r.in.key_name = key_name;
6060         r.out.key_buffer = &key_buffer;
6061         r.out.needed = &needed;
6062         r.out._ndr_size = &_ndr_size;
6063
6064         for (i=0; i < ARRAY_SIZE(offered); i++) {
6065
6066                 if (offered[i] < 0 && needed) {
6067                         if (needed <= 4) {
6068                                 continue;
6069                         }
6070                         r.in.offered = needed + offered[i];
6071                 } else {
6072                         r.in.offered = offered[i];
6073                 }
6074
6075                 ZERO_STRUCT(key_buffer);
6076
6077                 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
6078
6079                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
6080                         "failed to call EnumPrinterKey");
6081                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
6082
6083                         torture_assert(tctx, (_ndr_size == r.in.offered/2),
6084                                 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
6085                                         _ndr_size, r.in.offered/2));
6086
6087                         r.in.offered = needed;
6088                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
6089                                 "failed to call EnumPrinterKey");
6090                 }
6091
6092                 if (offered[i] > 0) {
6093                         torture_assert_werr_ok(tctx, r.out.result,
6094                                 "failed to call EnumPrinterKey");
6095                 }
6096
6097                 torture_assert(tctx, (_ndr_size == r.in.offered/2),
6098                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
6099                                 _ndr_size, r.in.offered/2));
6100
6101                 torture_assert(tctx, (*r.out.needed <= r.in.offered),
6102                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
6103
6104                 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
6105                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
6106
6107                 if (key_buffer.string_array) {
6108                         uint32_t calc_needed = 0;
6109                         int s;
6110                         for (s=0; key_buffer.string_array[s]; s++) {
6111                                 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
6112                         }
6113                         if (!key_buffer.string_array[0]) {
6114                                 calc_needed += 2;
6115                         }
6116                         calc_needed += 2;
6117
6118                         torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
6119                                 "EnumPrinterKey unexpected size");
6120                 }
6121         }
6122
6123         if (array) {
6124                 *array = key_buffer.string_array;
6125         }
6126
6127         return true;
6128 }
6129
6130 bool test_printer_keys(struct torture_context *tctx,
6131                        struct dcerpc_binding_handle *b,
6132                        struct policy_handle *handle)
6133 {
6134         const char **key_array = NULL;
6135         int i;
6136
6137         torture_comment(tctx, "Testing Printer Keys\n");
6138
6139         torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
6140                 "failed to call test_EnumPrinterKey");
6141
6142         for (i=0; key_array && key_array[i]; i++) {
6143                 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
6144                         "failed to call test_EnumPrinterKey");
6145         }
6146         for (i=0; key_array && key_array[i]; i++) {
6147                 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
6148                         "failed to call test_EnumPrinterDataEx");
6149         }
6150
6151         torture_comment(tctx, "Printer Keys test succeeded\n\n");
6152
6153         return true;
6154 }
6155
6156 static bool test_one_printer(struct torture_context *tctx,
6157                              struct dcerpc_pipe *p,
6158                              struct policy_handle *handle,
6159                              const char *name,
6160                              const char *drivername,
6161                              const char *environment)
6162 {
6163         bool ret = true;
6164         struct dcerpc_binding_handle *b = p->binding_handle;
6165
6166         if (!test_PausePrinter(tctx, b, handle)) {
6167                 ret = false;
6168         }
6169
6170         if (!test_DoPrintTest(tctx, b, handle)) {
6171                 ret = false;
6172         }
6173
6174         if (!test_ResumePrinter(tctx, b, handle)) {
6175                 ret = false;
6176         }
6177
6178         if (!test_printer_info(tctx, b, handle)) {
6179                 ret = false;
6180         }
6181
6182         if (!test_PrinterInfo_SD(tctx, b, handle)) {
6183                 ret = false;
6184         }
6185
6186         if (!test_PrinterInfo_DevMode(tctx, p, handle, name)) {
6187                 ret = false;
6188         }
6189
6190         if (!test_PrinterInfo_winreg(tctx, p, handle, name)) {
6191                 ret = false;
6192         }
6193
6194         if (!test_ChangeID(tctx, p, handle)) {
6195                 ret = false;
6196         }
6197
6198         if (!test_printer_keys(tctx, b, handle)) {
6199                 ret = false;
6200         }
6201
6202         if (!test_EnumPrinterData_consistency(tctx, p, handle)) {
6203                 ret = false;
6204         }
6205
6206         if (!test_SetPrinterDataEx_matrix(tctx, p, handle, name, NULL, NULL)) {
6207                 ret = false;
6208         }
6209
6210         if (!test_PrinterData_winreg(tctx, p, handle, name)) {
6211                 ret = false;
6212         }
6213
6214         if (!test_DriverInfo_winreg(tctx, p, handle, name, drivername, environment)) {
6215                 ret = false;
6216         }
6217
6218         if (!test_printer_rename(tctx, p, handle, name)) {
6219                 ret = false;
6220         }
6221
6222         return ret;
6223 }
6224
6225 static bool test_csetprinter(struct torture_context *tctx,
6226                              struct dcerpc_pipe *p,
6227                              struct policy_handle *handle,
6228                              const char *printername,
6229                              const char *drivername,
6230                              const char *portname)
6231 {
6232         union spoolss_PrinterInfo info;
6233         struct policy_handle new_handle, new_handle2;
6234         struct dcerpc_binding_handle *b = p->binding_handle;
6235
6236         torture_comment(tctx, "Testing c_setprinter\n");
6237
6238         torture_assert(tctx,
6239                 test_GetPrinter_level(tctx, b, handle, 0, &info),
6240                 "failed to get level 0 printer info");
6241         torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
6242                 info.info0.c_setprinter);
6243
6244         /* check if c_setprinter on 1st handle increases after a printer has
6245          * been added */
6246
6247         torture_assert(tctx,
6248                 test_AddPrinter(tctx, p, &new_handle, printername, drivername, portname),
6249                 "failed to add new printer");
6250         torture_assert(tctx,
6251                 test_GetPrinter_level(tctx, b, handle, 0, &info),
6252                 "failed to get level 0 printer info");
6253         torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
6254                 info.info0.c_setprinter);
6255
6256         /* check if c_setprinter on new handle increases after a printer has
6257          * been added */
6258
6259         torture_assert(tctx,
6260                 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
6261                 "failed to get level 0 printer info");
6262         torture_comment(tctx, "csetprinter on created handle: %d\n",
6263                 info.info0.c_setprinter);
6264
6265         /* open the new printer and check if c_setprinter increases */
6266
6267         torture_assert(tctx,
6268                 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
6269                 "failed to open created printer");
6270         torture_assert(tctx,
6271                 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
6272                 "failed to get level 0 printer info");
6273         torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
6274                 info.info0.c_setprinter);
6275
6276         /* cleanup */
6277
6278         torture_assert(tctx,
6279                 test_ClosePrinter(tctx, b, &new_handle2),
6280                 "failed to close printer");
6281         torture_assert(tctx,
6282                 test_DeletePrinter(tctx, b, &new_handle),
6283                 "failed to delete new printer");
6284
6285         return true;
6286 }
6287
6288 static bool test_printer(struct torture_context *tctx,
6289                          struct dcerpc_pipe *p)
6290 {
6291         bool ret = true;
6292         struct policy_handle handle[2];
6293         struct policy_handle printserver_handle;
6294         bool found = false;
6295         const char *drivername = "Microsoft XPS Document Writer";
6296         const char *portname = "LPT1:";
6297         struct dcerpc_binding_handle *b = p->binding_handle;
6298         const char *environment;
6299
6300         torture_assert(tctx,
6301                 test_OpenPrinter_server(tctx, p, &printserver_handle),
6302                 "failed to open printserver");
6303         torture_assert(tctx,
6304                 test_get_environment(tctx, b, &printserver_handle, &environment),
6305                 "failed to get environment");
6306         torture_assert(tctx,
6307                 test_ClosePrinter(tctx, b, &printserver_handle),
6308                 "failed to close printserver");
6309
6310         /* test printer created via AddPrinter */
6311
6312         if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
6313                 return false;
6314         }
6315
6316         if (!test_csetprinter(tctx, p, &handle[0], TORTURE_PRINTER "2", drivername, portname)) {
6317                 ret = false;
6318         }
6319
6320         if (!test_one_printer(tctx, p, &handle[0], TORTURE_PRINTER, drivername, environment)) {
6321                 ret = false;
6322         }
6323
6324         if (!test_DeletePrinter(tctx, b, &handle[0])) {
6325                 ret = false;
6326         }
6327
6328         if (!test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
6329                                         TORTURE_PRINTER, &found)) {
6330                 ret = false;
6331         }
6332
6333         torture_assert(tctx, !found, "deleted printer still there");
6334
6335         /* test printer created via AddPrinterEx */
6336
6337         if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
6338                 return false;
6339         }
6340
6341         if (!test_csetprinter(tctx, p, &handle[1], TORTURE_PRINTER_EX "2", drivername, portname)) {
6342                 ret = false;
6343         }
6344
6345         if (!test_one_printer(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, environment)) {
6346                 ret = false;
6347         }
6348
6349         if (!test_DeletePrinter(tctx, b, &handle[1])) {
6350                 ret = false;
6351         }
6352
6353         if (!test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
6354                                         TORTURE_PRINTER_EX, &found)) {
6355                 ret = false;
6356         }
6357
6358         torture_assert(tctx, !found, "deleted printer still there");
6359
6360         return ret;
6361 }
6362
6363 static bool test_architecture_buffer(struct torture_context *tctx,
6364                                      struct dcerpc_pipe *p)
6365 {
6366         struct spoolss_OpenPrinterEx r;
6367         struct spoolss_UserLevel1 u1;
6368         struct policy_handle handle;
6369         uint32_t architectures[] = {
6370                 PROCESSOR_ARCHITECTURE_INTEL,
6371                 PROCESSOR_ARCHITECTURE_IA64,
6372                 PROCESSOR_ARCHITECTURE_AMD64
6373         };
6374         uint32_t needed[3];
6375         int i;
6376         struct dcerpc_binding_handle *b = p->binding_handle;
6377
6378         for (i=0; i < ARRAY_SIZE(architectures); i++) {
6379
6380                 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
6381
6382                 u1.size = 0;
6383                 u1.client = NULL;
6384                 u1.user = NULL;
6385                 u1.build = 0;
6386                 u1.major = 3;
6387                 u1.minor = 0;
6388                 u1.processor = architectures[i];
6389
6390                 r.in.printername        = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6391                 r.in.datatype           = NULL;
6392                 r.in.devmode_ctr.devmode= NULL;
6393                 r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
6394                 r.in.level               = 1;
6395                 r.in.userlevel.level1   = &u1;
6396                 r.out.handle            = &handle;
6397
6398                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
6399                 torture_assert_werr_ok(tctx, r.out.result, "");
6400
6401                 {
6402                         struct spoolss_EnumPrinters e;
6403                         uint32_t count;
6404                         union spoolss_PrinterInfo *info;
6405
6406                         e.in.flags = PRINTER_ENUM_LOCAL;
6407                         e.in.server = NULL;
6408                         e.in.level = 2;
6409                         e.in.buffer = NULL;
6410                         e.in.offered = 0;
6411                         e.out.count = &count;
6412                         e.out.info = &info;
6413                         e.out.needed = &needed[i];
6414
6415                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
6416 #if 0
6417                         torture_comment(tctx, "needed was %d\n", needed[i]);
6418 #endif
6419                 }
6420
6421                 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
6422         }
6423
6424         for (i=1; i < ARRAY_SIZE(architectures); i++) {
6425                 if (needed[i-1] != needed[i]) {
6426                         torture_fail(tctx,
6427                                 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
6428                                                 needed[i-1], architectures[i-1], needed[i], architectures[i]));
6429                 }
6430         }
6431
6432         return true;
6433 }
6434
6435 bool torture_rpc_spoolss(struct torture_context *torture)
6436 {
6437         NTSTATUS status;
6438         struct dcerpc_pipe *p;
6439         struct dcerpc_binding_handle *b;
6440         bool ret = true;
6441         struct test_spoolss_context *ctx;
6442         const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
6443
6444         status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
6445         if (!NT_STATUS_IS_OK(status)) {
6446                 return false;
6447         }
6448         b = p->binding_handle;
6449
6450         ctx = talloc_zero(torture, struct test_spoolss_context);
6451
6452         ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
6453         ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle, &environment);
6454         ret &= test_EnumForms_all(torture, b, &ctx->server_handle, true);
6455         ret &= test_Forms(torture, b, &ctx->server_handle, true, NULL, NULL, NULL);
6456         ret &= test_Forms_winreg(torture, b, &ctx->server_handle, true, NULL);
6457         ret &= test_EnumPorts(torture, b, ctx);
6458         ret &= test_GetPrinterDriverDirectory(torture, p, environment);
6459         ret &= test_GetPrintProcessorDirectory(torture, p, environment);
6460         ret &= test_EnumPrinterDrivers(torture, p, ctx, environment);
6461         ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
6462         ret &= test_EnumMonitors(torture, b, ctx);
6463         ret &= test_EnumPrintProcessors(torture, b, ctx, environment);
6464         ret &= test_EnumPrintProcDataTypes(torture, b);
6465         ret &= test_EnumPrinters(torture, b, ctx);
6466         ret &= test_OpenPrinter_badname_list(torture, b, dcerpc_server_name(p));
6467
6468         ret &= test_AddPort(torture, p);
6469         ret &= test_EnumPorts_old(torture, p);
6470         ret &= test_EnumPrinters_old(torture, p, environment);
6471         ret &= test_EnumPrinterDrivers_old(torture, p, environment);
6472         ret &= test_architecture_buffer(torture, p);
6473
6474         return ret;
6475 }
6476
6477 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
6478 {
6479         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
6480
6481         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
6482                                                         "printer", &ndr_table_spoolss);
6483
6484         torture_rpc_tcase_add_test(tcase, "printer", test_printer);
6485
6486         return suite;
6487 }
6488
6489 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
6490                                                   struct dcerpc_binding_handle *b,
6491                                                   const char *server,
6492                                                   const char *environment,
6493                                                   const char **dir_p)
6494 {
6495         struct spoolss_GetPrinterDriverDirectory r;
6496         uint32_t needed;
6497
6498         r.in.server             = server;
6499         r.in.environment        = environment;
6500         r.in.level              = 1;
6501         r.in.buffer             = NULL;
6502         r.in.offered            = 0;
6503         r.out.needed            = &needed;
6504
6505         torture_assert_ntstatus_ok(tctx,
6506                 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
6507                 "failed to query driver directory");
6508
6509         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6510                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6511                 r.in.buffer = &blob;
6512                 r.in.offered = needed;
6513
6514                 torture_assert_ntstatus_ok(tctx,
6515                         dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
6516                         "failed to query driver directory");
6517         }
6518
6519         torture_assert_werr_ok(tctx, r.out.result,
6520                 "failed to query driver directory");
6521
6522         if (dir_p) {
6523                 *dir_p = r.out.info->info1.directory_name;
6524         }
6525
6526         return true;
6527 }
6528
6529 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
6530 {
6531         if (info_ctr == NULL) {
6532                 return NULL;
6533         }
6534
6535         switch (info_ctr->level) {
6536         case 1:
6537                 return info_ctr->info.info1->driver_name;
6538         case 2:
6539                 return info_ctr->info.info2->driver_name;
6540         case 3:
6541                 return info_ctr->info.info3->driver_name;
6542         case 4:
6543                 return info_ctr->info.info4->driver_name;
6544         case 6:
6545                 return info_ctr->info.info6->driver_name;
6546         case 8:
6547                 return info_ctr->info.info8->driver_name;
6548         default:
6549                 return NULL;
6550         }
6551 }
6552
6553 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
6554                                       struct dcerpc_binding_handle *b,
6555                                       const char *servername,
6556                                       struct spoolss_AddDriverInfoCtr *info_ctr,
6557                                       WERROR expected_result)
6558 {
6559         struct spoolss_AddPrinterDriver r;
6560         const char *drivername = get_driver_from_info(info_ctr);
6561
6562         r.in.servername = servername;
6563         r.in.info_ctr = info_ctr;
6564
6565         torture_comment(tctx, "Testing AddPrinterDriver(%s) level %d\n",
6566                 drivername, info_ctr->level);
6567
6568         torture_assert_ntstatus_ok(tctx,
6569                 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
6570                 "spoolss_AddPrinterDriver failed");
6571         torture_assert_werr_equal(tctx, r.out.result, expected_result,
6572                 "spoolss_AddPrinterDriver failed with unexpected result");
6573
6574         return true;
6575
6576 }
6577
6578 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
6579                                         struct dcerpc_binding_handle *b,
6580                                         const char *servername,
6581                                         struct spoolss_AddDriverInfoCtr *info_ctr,
6582                                         uint32_t flags,
6583                                         WERROR expected_result)
6584 {
6585         struct spoolss_AddPrinterDriverEx r;
6586         const char *drivername = get_driver_from_info(info_ctr);
6587
6588         r.in.servername = servername;
6589         r.in.info_ctr = info_ctr;
6590         r.in.flags = flags;
6591
6592         torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level %d\n",
6593                 drivername, info_ctr->level);
6594
6595         torture_assert_ntstatus_ok(tctx,
6596                 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
6597                 "AddPrinterDriverEx failed");
6598         torture_assert_werr_equal(tctx, r.out.result, expected_result,
6599                 "AddPrinterDriverEx failed with unexpected result");
6600
6601         return true;
6602 }
6603
6604 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
6605                                                struct dcerpc_binding_handle *b,
6606                                                const char *server_name,
6607                                                struct spoolss_AddDriverInfo8 *r,
6608                                                uint32_t flags,
6609                                                bool ex)
6610 {
6611         struct spoolss_AddDriverInfoCtr info_ctr;
6612         struct spoolss_AddDriverInfo1 info1;
6613
6614         ZERO_STRUCT(info1);
6615
6616         info_ctr.level = 1;
6617         info_ctr.info.info1 = &info1;
6618
6619         if (ex) {
6620                 torture_assert(tctx,
6621                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
6622                         "failed to test AddPrinterDriverEx level 1");
6623         } else {
6624                 torture_assert(tctx,
6625                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
6626                         "failed to test AddPrinterDriver level 1");
6627         }
6628
6629         info1.driver_name = r->driver_name;
6630
6631         if (ex) {
6632                 torture_assert(tctx,
6633                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
6634                         "failed to test AddPrinterDriverEx level 1");
6635         } else {
6636                 torture_assert(tctx,
6637                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
6638                         "failed to test AddPrinterDriver level 1");
6639         }
6640
6641         return true;
6642 }
6643
6644 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
6645                                                struct dcerpc_binding_handle *b,
6646                                                const char *server_name,
6647                                                struct spoolss_AddDriverInfo8 *r,
6648                                                uint32_t flags,
6649                                                bool ex)
6650 {
6651         struct spoolss_AddDriverInfoCtr info_ctr;
6652         struct spoolss_AddDriverInfo2 info2;
6653
6654         ZERO_STRUCT(info2);
6655
6656         info_ctr.level = 2;
6657         info_ctr.info.info2 = &info2;
6658
6659         if (ex) {
6660                 torture_assert(tctx,
6661                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
6662                         "failed to test AddPrinterDriverEx level 2");
6663         } else {
6664                 torture_assert(tctx,
6665                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
6666                         "failed to test AddPrinterDriver level 2");
6667         }
6668
6669         info2.driver_name = r->driver_name;
6670
6671         if (ex) {
6672                 torture_assert(tctx,
6673                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
6674                         "failed to test AddPrinterDriverEx level 2");
6675         } else {
6676                 torture_assert(tctx,
6677                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
6678                         "failed to test AddPrinterDriver level 2");
6679         }
6680
6681         info2.version = r->version;
6682
6683         if (ex) {
6684                 torture_assert(tctx,
6685                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
6686                         "failed to test AddPrinterDriverEx level 2");
6687         } else {
6688                 torture_assert(tctx,
6689                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
6690                         "failed to test AddPrinterDriver level 2");
6691         }
6692
6693         info2.architecture = r->architecture;
6694
6695         if (ex) {
6696                 torture_assert(tctx,
6697                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
6698                         "failed to test AddPrinterDriverEx level 2");
6699         } else {
6700                 torture_assert(tctx,
6701                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
6702                         "failed to test AddPrinterDriver level 2");
6703         }
6704
6705         info2.driver_path = r->driver_path;
6706
6707         if (ex) {
6708                 torture_assert(tctx,
6709                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
6710                         "failed to test AddPrinterDriverEx level 2");
6711         } else {
6712                 torture_assert(tctx,
6713                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
6714                         "failed to test AddPrinterDriver level 2");
6715         }
6716
6717         info2.data_file = r->data_file;
6718
6719         if (ex) {
6720                 torture_assert(tctx,
6721                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
6722                         "failed to test AddPrinterDriverEx level 2");
6723         } else {
6724                 torture_assert(tctx,
6725                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
6726                         "failed to test AddPrinterDriver level 2");
6727         }
6728
6729         info2.config_file = r->config_file;
6730
6731         if (ex) {
6732                 torture_assert(tctx,
6733                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
6734                         "failed to test AddPrinterDriverEx");
6735         }
6736
6737         if (ex) {
6738                 torture_assert(tctx,
6739                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
6740                         "failed to test AddPrinterDriverEx level 2");
6741         } else {
6742                 torture_assert(tctx,
6743                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
6744                         "failed to test AddPrinterDriver level 2");
6745         }
6746
6747         torture_assert(tctx,
6748                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name),
6749                 "failed to find added printer driver");
6750
6751         return true;
6752 }
6753
6754 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
6755                                                struct dcerpc_binding_handle *b,
6756                                                const char *server_name,
6757                                                struct spoolss_AddDriverInfo8 *r,
6758                                                uint32_t flags,
6759                                                bool ex)
6760 {
6761         struct spoolss_AddDriverInfoCtr info_ctr;
6762         struct spoolss_AddDriverInfo3 info3;
6763
6764         ZERO_STRUCT(info3);
6765
6766         info3.driver_name       = r->driver_name;
6767         info3.version           = r->version;
6768         info3.architecture      = r->architecture;
6769         info3.driver_path       = r->driver_path;
6770         info3.data_file         = r->data_file;
6771         info3.config_file       = r->config_file;
6772
6773         info_ctr.level = 3;
6774         info_ctr.info.info3 = &info3;
6775
6776         if (ex) {
6777                 torture_assert(tctx,
6778                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
6779                         "failed to test AddPrinterDriverEx level 3");
6780         } else {
6781                 torture_assert(tctx,
6782                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
6783                         "failed to test AddPrinterDriver level 3");
6784         }
6785
6786         torture_assert(tctx,
6787                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name),
6788                 "failed to find added printer driver");
6789
6790         return true;
6791 }
6792
6793 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
6794                                                struct dcerpc_binding_handle *b,
6795                                                const char *server_name,
6796                                                struct spoolss_AddDriverInfo8 *r,
6797                                                uint32_t flags,
6798                                                bool ex)
6799 {
6800         struct spoolss_AddDriverInfoCtr info_ctr;
6801         struct spoolss_AddDriverInfo4 info4;
6802
6803         ZERO_STRUCT(info4);
6804
6805         info4.driver_name       = r->driver_name;
6806         info4.version           = r->version;
6807         info4.architecture      = r->architecture;
6808         info4.driver_path       = r->driver_path;
6809         info4.data_file         = r->data_file;
6810         info4.config_file       = r->config_file;
6811
6812         info_ctr.level = 4;
6813         info_ctr.info.info4 = &info4;
6814
6815         if (ex) {
6816                 torture_assert(tctx,
6817                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
6818                         "failed to test AddPrinterDriverEx level 4");
6819         } else {
6820                 torture_assert(tctx,
6821                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
6822                         "failed to test AddPrinterDriver level 4");
6823         }
6824
6825         torture_assert(tctx,
6826                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name),
6827                 "failed to find added printer driver");
6828
6829         return true;
6830 }
6831
6832 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
6833                                                struct dcerpc_binding_handle *b,
6834                                                const char *server_name,
6835                                                struct spoolss_AddDriverInfo8 *r,
6836                                                uint32_t flags,
6837                                                bool ex)
6838 {
6839         struct spoolss_AddDriverInfoCtr info_ctr;
6840         struct spoolss_AddDriverInfo6 info6;
6841
6842         ZERO_STRUCT(info6);
6843
6844         info6.driver_name       = r->driver_name;
6845         info6.version           = r->version;
6846         info6.architecture      = r->architecture;
6847         info6.driver_path       = r->driver_path;
6848         info6.data_file         = r->data_file;
6849         info6.config_file       = r->config_file;
6850
6851         info_ctr.level = 6;
6852         info_ctr.info.info6 = &info6;
6853
6854         if (ex) {
6855                 torture_assert(tctx,
6856                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
6857                         "failed to test AddPrinterDriverEx level 6");
6858         } else {
6859                 torture_assert(tctx,
6860                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
6861                         "failed to test AddPrinterDriver level 6");
6862         }
6863
6864         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
6865
6866         if (!ex) {
6867                 return true;
6868         }
6869
6870         torture_assert(tctx,
6871                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name),
6872                 "failed to find added printer driver");
6873
6874         return true;
6875 }
6876
6877 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
6878                                                struct dcerpc_binding_handle *b,
6879                                                const char *server_name,
6880                                                struct spoolss_AddDriverInfo8 *r,
6881                                                uint32_t flags,
6882                                                bool ex)
6883 {
6884         struct spoolss_AddDriverInfoCtr info_ctr;
6885         struct spoolss_AddDriverInfo8 info8;
6886
6887         ZERO_STRUCT(info8);
6888
6889         info8.driver_name       = r->driver_name;
6890         info8.version           = r->version;
6891         info8.architecture      = r->architecture;
6892         info8.driver_path       = r->driver_path;
6893         info8.data_file         = r->data_file;
6894         info8.config_file       = r->config_file;
6895
6896         info_ctr.level = 8;
6897         info_ctr.info.info8 = &info8;
6898
6899         if (ex) {
6900                 torture_assert(tctx,
6901                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
6902                         "failed to test AddPrinterDriverEx level 8");
6903         } else {
6904                 torture_assert(tctx,
6905                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
6906                         "failed to test AddPrinterDriver level 8");
6907         }
6908
6909         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
6910
6911         if (!ex) {
6912                 return true;
6913         }
6914
6915         torture_assert(tctx,
6916                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name),
6917                 "failed to find added printer driver");
6918
6919         return true;
6920 }
6921
6922 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
6923                                          struct dcerpc_binding_handle *b,
6924                                          const char *server,
6925                                          const char *driver,
6926                                          const char *environment,
6927                                          WERROR expected_result)
6928 {
6929         struct spoolss_DeletePrinterDriver r;
6930
6931         r.in.server = server;
6932         r.in.architecture = environment;
6933         r.in.driver = driver;
6934
6935         torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
6936
6937         torture_assert_ntstatus_ok(tctx,
6938                 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
6939                 "DeletePrinterDriver failed");
6940         torture_assert_werr_equal(tctx, r.out.result, expected_result,
6941                 "DeletePrinterDriver failed with unexpected result");
6942
6943         return true;
6944 }
6945
6946 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
6947                                            struct dcerpc_binding_handle *b,
6948                                            const char *server,
6949                                            const char *driver,
6950                                            const char *environment,
6951                                            uint32_t delete_flags,
6952                                            uint32_t version,
6953                                            WERROR expected_result)
6954 {
6955         struct spoolss_DeletePrinterDriverEx r;
6956
6957         r.in.server = server;
6958         r.in.architecture = environment;
6959         r.in.driver = driver;
6960         r.in.delete_flags = delete_flags;
6961         r.in.version = version;
6962
6963         torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
6964
6965         torture_assert_ntstatus_ok(tctx,
6966                 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
6967                 "DeletePrinterDriverEx failed");
6968         torture_assert_werr_equal(tctx, r.out.result, expected_result,
6969                 "DeletePrinterDriverEx failed with unexpected result");
6970
6971         return true;
6972 }
6973
6974 static bool test_DeletePrinterDriver(struct torture_context *tctx,
6975                                      struct dcerpc_binding_handle *b,
6976                                      const char *server_name,
6977                                      const char *driver,
6978                                      const char *environment)
6979 {
6980         torture_assert(tctx,
6981                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
6982                 "failed to delete driver");
6983
6984         torture_assert(tctx,
6985                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
6986                 "failed to delete driver");
6987
6988         if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
6989                 torture_fail(tctx, "deleted driver still enumerated");
6990         }
6991
6992         torture_assert(tctx,
6993                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
6994                 "2nd delete failed");
6995
6996         return true;
6997 }
6998
6999 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
7000                                        struct dcerpc_binding_handle *b,
7001                                        const char *server_name,
7002                                        const char *driver,
7003                                        const char *environment,
7004                                        uint32_t delete_flags,
7005                                        uint32_t version)
7006 {
7007         torture_assert(tctx,
7008                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
7009                 "failed to delete driver");
7010
7011         torture_assert(tctx,
7012                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
7013                 "failed to delete driver");
7014
7015         if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
7016                 torture_fail(tctx, "deleted driver still enumerated");
7017         }
7018
7019         torture_assert(tctx,
7020                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
7021                 "2nd delete failed");
7022
7023         return true;
7024 }
7025
7026 static bool test_PrinterDriver_args(struct torture_context *tctx,
7027                                     struct dcerpc_binding_handle *b,
7028                                     const char *server_name,
7029                                     uint32_t level,
7030                                     struct spoolss_AddDriverInfo8 *r,
7031                                     uint32_t add_flags,
7032                                     uint32_t delete_flags,
7033                                     uint32_t delete_version,
7034                                     bool ex)
7035 {
7036         bool ret = true;
7037
7038         switch (level) {
7039         case 1:
7040                 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex);
7041                 break;
7042         case 2:
7043                 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex);
7044                 break;
7045         case 3:
7046                 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex);
7047                 break;
7048         case 4:
7049                 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex);
7050                 break;
7051         case 6:
7052                 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex);
7053                 break;
7054         case 8:
7055                 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex);
7056                 break;
7057         default:
7058                 return false;
7059         }
7060
7061         if (ret == false) {
7062                 return ret;
7063         }
7064
7065         if (level == 1) {
7066                 return ret;
7067         }
7068
7069         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
7070
7071         if (!ex && (level == 6 || level == 8)) {
7072                 return ret;
7073         }
7074
7075         if (ex) {
7076                 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
7077         } else {
7078                 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
7079         }
7080 }
7081
7082 static bool fillup_printserver_info(struct torture_context *tctx,
7083                                     struct dcerpc_pipe *p,
7084                                     struct torture_driver_context *d)
7085 {
7086         struct policy_handle server_handle;
7087         struct dcerpc_binding_handle *b = p->binding_handle;
7088         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7089
7090         torture_assert(tctx,
7091                 test_OpenPrinter_server(tctx, p, &server_handle),
7092                 "failed to open printserver");
7093         torture_assert(tctx,
7094                 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
7095                 "failed to get environment");
7096         torture_assert(tctx,
7097                 test_ClosePrinter(tctx, b, &server_handle),
7098                 "failed to close printserver");
7099
7100         torture_assert(tctx,
7101                 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
7102                         d->local.environment ? d->local.environment : d->remote.environment,
7103                         &d->remote.driver_directory),
7104                 "failed to get driver directory");
7105
7106         return true;
7107 }
7108
7109 static const char *driver_directory_dir(const char *driver_directory)
7110 {
7111         char *p;
7112
7113         p = strrchr(driver_directory, '\\');
7114         if (p) {
7115                 return p+1;
7116         }
7117
7118         return NULL;
7119 }
7120
7121 static const char *driver_directory_share(struct torture_context *tctx,
7122                                           const char *driver_directory)
7123 {
7124         const char *p;
7125         char *tok;
7126
7127         if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
7128                 driver_directory += 2;
7129         }
7130
7131         p = talloc_strdup(tctx, driver_directory);
7132
7133         torture_assert(tctx,
7134                 next_token_talloc(tctx, &p, &tok, "\\"),
7135                 "cannot explode uri");
7136         torture_assert(tctx,
7137                 next_token_talloc(tctx, &p, &tok, "\\"),
7138                 "cannot explode uri");
7139
7140         return tok;
7141 }
7142
7143 static bool upload_printer_driver_file(struct torture_context *tctx,
7144                                        struct smbcli_state *cli,
7145                                        struct torture_driver_context *d,
7146                                        const char *file_name)
7147 {
7148         XFILE *f;
7149         int fnum;
7150         uint8_t *buf;
7151         int maxwrite = 64512;
7152         off_t nread = 0;
7153         size_t start = 0;
7154         const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
7155         const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
7156         const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
7157
7158         if (!file_name) {
7159                 return true;
7160         }
7161
7162         torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
7163
7164         fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
7165         if (fnum == -1) {
7166                 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
7167         }
7168
7169         f = x_fopen(local_name, O_RDONLY, 0);
7170         if (f == NULL) {
7171                 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
7172         }
7173
7174         buf = talloc_array(tctx, uint8_t, maxwrite);
7175         if (!buf) {
7176                 return false;
7177         }
7178
7179         while (!x_feof(f)) {
7180                 int n = maxwrite;
7181                 int ret;
7182
7183                 if ((n = x_fread(buf, 1, n, f)) < 1) {
7184                         if((n == 0) && x_feof(f))
7185                                 break; /* Empty local file. */
7186
7187                         torture_warning(tctx,
7188                                 "failed to read file: %s\n", strerror(errno));
7189                         break;
7190                 }
7191
7192                 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
7193
7194                 if (n != ret) {
7195                         torture_warning(tctx,
7196                                 "failed to write file: %s\n", smbcli_errstr(cli->tree));
7197                         break;
7198                 }
7199
7200                 nread += n;
7201         }
7202
7203         x_fclose(f);
7204
7205         torture_assert_ntstatus_ok(tctx,
7206                 smbcli_close(cli->tree, fnum),
7207                 "failed to close file");
7208
7209         return true;
7210 }
7211
7212 static bool connect_printer_driver_share(struct torture_context *tctx,
7213                                          const char *server_name,
7214                                          const char *share_name,
7215                                          struct smbcli_state **cli)
7216 {
7217         struct smbcli_options smb_options;
7218         struct smbcli_session_options smb_session_options;
7219
7220         torture_comment(tctx, "Connecting printer driver share\n");
7221
7222         lp_smbcli_options(tctx->lp_ctx, &smb_options);
7223         lp_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
7224
7225         torture_assert_ntstatus_ok(tctx,
7226                 smbcli_full_connection(tctx, cli, server_name,
7227                                         lp_smb_ports(tctx->lp_ctx),
7228                                         share_name, NULL,
7229                                         lp_socket_options(tctx->lp_ctx),
7230                                         cmdline_credentials,
7231                                         lp_resolve_context(tctx->lp_ctx),
7232                                         tctx->ev,
7233                                         &smb_options,
7234                                         &smb_session_options,
7235                                         lp_iconv_convenience(tctx->lp_ctx),
7236                                         lp_gensec_settings(tctx, tctx->lp_ctx)),
7237                 "failed to open driver share");
7238
7239         return true;
7240 }
7241
7242 static bool upload_printer_driver(struct torture_context *tctx,
7243                                   const char *server_name,
7244                                   struct torture_driver_context *d)
7245 {
7246         struct smbcli_state *cli;
7247         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
7248         int i;
7249
7250         torture_assert(tctx,
7251                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
7252                 "failed to connect to driver share");
7253
7254         torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
7255                 server_name, share_name);
7256
7257         torture_assert(tctx,
7258                 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
7259                 "failed to upload driver_path");
7260         torture_assert(tctx,
7261                 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
7262                 "failed to upload data_file");
7263         torture_assert(tctx,
7264                 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
7265                 "failed to upload config_file");
7266         torture_assert(tctx,
7267                 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
7268                 "failed to upload help_file");
7269         if (d->info8.dependent_files) {
7270                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
7271                         torture_assert(tctx,
7272                                 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
7273                                 "failed to upload dependent_files");
7274                 }
7275         }
7276
7277         talloc_free(cli);
7278
7279         return true;
7280 }
7281
7282 static bool remove_printer_driver_file(struct torture_context *tctx,
7283                                        struct smbcli_state *cli,
7284                                        struct torture_driver_context *d,
7285                                        const char *file_name)
7286 {
7287         const char *remote_name;
7288         const char *remote_dir =  driver_directory_dir(d->remote.driver_directory);
7289
7290         if (!file_name) {
7291                 return true;
7292         }
7293
7294         remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
7295
7296         torture_comment(tctx, "Removing %s\n", remote_name);
7297
7298         torture_assert_ntstatus_ok(tctx,
7299                 smbcli_unlink(cli->tree, remote_name),
7300                 "failed to unlink");
7301
7302         return true;
7303 }
7304
7305 static bool remove_printer_driver(struct torture_context *tctx,
7306                                   const char *server_name,
7307                                   struct torture_driver_context *d)
7308 {
7309         struct smbcli_state *cli;
7310         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
7311         int i;
7312
7313         torture_assert(tctx,
7314                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
7315                 "failed to connect to driver share");
7316
7317         torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
7318                 server_name, share_name);
7319
7320         torture_assert(tctx,
7321                 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
7322                 "failed to remove driver_path");
7323         torture_assert(tctx,
7324                 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
7325                 "failed to remove data_file");
7326         torture_assert(tctx,
7327                 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
7328                 "failed to remove config_file");
7329         torture_assert(tctx,
7330                 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
7331                 "failed to remove help_file");
7332         if (d->info8.dependent_files) {
7333                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
7334                         torture_assert(tctx,
7335                                 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
7336                                 "failed to remove dependent_files");
7337                 }
7338         }
7339
7340         talloc_free(cli);
7341
7342         return true;
7343
7344 }
7345
7346 static bool test_add_driver_arg(struct torture_context *tctx,
7347                                 struct dcerpc_pipe *p,
7348                                 struct torture_driver_context *d)
7349 {
7350         bool ret = true;
7351         struct dcerpc_binding_handle *b = p->binding_handle;
7352         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7353         uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
7354         int i;
7355         struct spoolss_AddDriverInfo8 info8;
7356         uint32_t add_flags = APD_COPY_NEW_FILES;
7357         uint32_t delete_flags = 0;
7358
7359         torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
7360                 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
7361
7362         torture_assert(tctx,
7363                 fillup_printserver_info(tctx, p, d),
7364                 "failed to fillup printserver info");
7365
7366         if (!directory_exist(d->local.driver_directory)) {
7367                 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
7368         }
7369
7370         torture_assert(tctx,
7371                 upload_printer_driver(tctx, dcerpc_server_name(p), d),
7372                 "failed to upload printer driver");
7373
7374         info8.version           = d->info8.version;
7375         info8.driver_name       = d->info8.driver_name;
7376         info8.architecture      = d->local.environment;
7377         info8.driver_path       = d->info8.driver_path;
7378         info8.data_file         = d->info8.data_file;
7379         info8.config_file       = d->info8.config_file;
7380
7381         for (i=0; i < ARRAY_SIZE(levels); i++) {
7382
7383                 if (torture_setting_bool(tctx, "samba3", false)) {
7384                         switch (levels[i]) {
7385                         case 2:
7386                         case 4:
7387                         case 8:
7388                                 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
7389                                 continue;
7390                         default:
7391                                 break;
7392                         }
7393                 }
7394
7395                 torture_comment(tctx,
7396                         "Testing PrinterDriver%s '%s' add & delete level %d\n",
7397                                 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
7398
7399                 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
7400         }
7401
7402         info8.driver_path       = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
7403         info8.data_file         = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
7404         info8.config_file       = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
7405
7406         for (i=0; i < ARRAY_SIZE(levels); i++) {
7407
7408                 if (torture_setting_bool(tctx, "samba3", false)) {
7409                         switch (levels[i]) {
7410                         case 2:
7411                         case 4:
7412                         case 8:
7413                                 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
7414                                 continue;
7415                         default:
7416                                 break;
7417                         }
7418                 }
7419
7420
7421                 torture_comment(tctx,
7422                         "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
7423                                 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
7424
7425                 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
7426         }
7427
7428         torture_assert(tctx,
7429                 remove_printer_driver(tctx, dcerpc_server_name(p), d),
7430                 "failed to remove printer driver");
7431
7432         torture_comment(tctx, "\n");
7433
7434         return ret;
7435 }
7436
7437 static bool test_add_driver_ex_64(struct torture_context *tctx,
7438                                   struct dcerpc_pipe *p,
7439                                   void *private_data)
7440 {
7441         struct torture_driver_context *d =
7442                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
7443
7444         d->local.environment            = talloc_strdup(d, "Windows x64");
7445         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/x64");
7446         d->info8.driver_name            = TORTURE_DRIVER_EX;
7447         d->ex                           = true;
7448
7449         return test_add_driver_arg(tctx, p, d);
7450 }
7451
7452 static bool test_add_driver_ex_32(struct torture_context *tctx,
7453                                   struct dcerpc_pipe *p,
7454                                   void *private_data)
7455 {
7456         struct torture_driver_context *d =
7457                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
7458
7459         d->local.environment            = talloc_strdup(d, "Windows NT x86");
7460         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
7461         d->info8.driver_name            = TORTURE_DRIVER_EX;
7462         d->ex                           = true;
7463
7464         return test_add_driver_arg(tctx, p, d);
7465 }
7466
7467 static bool test_add_driver_64(struct torture_context *tctx,
7468                                struct dcerpc_pipe *p,
7469                                void *private_data)
7470 {
7471         struct torture_driver_context *d =
7472                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
7473
7474         d->local.environment            = talloc_strdup(d, "Windows x64");
7475         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/x64");
7476         d->info8.driver_name            = TORTURE_DRIVER;
7477         d->ex                           = false;
7478
7479         return test_add_driver_arg(tctx, p, d);
7480 }
7481
7482 static bool test_add_driver_32(struct torture_context *tctx,
7483                                struct dcerpc_pipe *p,
7484                                void *private_data)
7485 {
7486         struct torture_driver_context *d =
7487                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
7488
7489         d->local.environment            = talloc_strdup(d, "Windows NT x86");
7490         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
7491         d->info8.driver_name            = TORTURE_DRIVER;
7492         d->ex                           = false;
7493
7494         return test_add_driver_arg(tctx, p, d);
7495 }
7496
7497 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
7498 {
7499         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-DRIVER");
7500
7501         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
7502                                                         "driver", &ndr_table_spoolss);
7503         struct torture_driver_context *t;
7504
7505         t = talloc_zero(mem_ctx, struct torture_driver_context);
7506
7507         t->info8.version        = SPOOLSS_DRIVER_VERSION_200X;
7508         t->info8.driver_name    = NULL;
7509         t->info8.architecture   = NULL;
7510         t->info8.driver_path    = talloc_strdup(t, "pscript5.dll");
7511         t->info8.data_file      = talloc_strdup(t, "cups6.ppd");
7512         t->info8.config_file    = talloc_strdup(t, "cupsui6.dll");
7513
7514         torture_rpc_tcase_add_test_ex(tcase, "add_driver_64", test_add_driver_64, t);
7515         torture_rpc_tcase_add_test_ex(tcase, "add_driver_ex_64", test_add_driver_ex_64, t);
7516
7517         torture_rpc_tcase_add_test_ex(tcase, "add_driver_32", test_add_driver_32, t);
7518         torture_rpc_tcase_add_test_ex(tcase, "add_driver_ex_32", test_add_driver_ex_32, t);
7519
7520         return suite;
7521 }