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