s4-smbtorture: split out a "printerdata_keys" test for RPC-SPOOLSS-PRINTER.
[kai/samba.git] / source4 / torture / rpc / spoolss.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for spoolss rpc operations
4
5    Copyright (C) Tim Potter 2003
6    Copyright (C) Stefan Metzmacher 2005
7    Copyright (C) Jelmer Vernooij 2007
8    Copyright (C) Guenther Deschner 2009-2010
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "torture/torture.h"
26 #include "librpc/gen_ndr/ndr_misc.h"
27 #include "librpc/gen_ndr/ndr_spoolss.h"
28 #include "librpc/gen_ndr/ndr_spoolss_c.h"
29 #include "librpc/gen_ndr/ndr_winreg_c.h"
30 #include "librpc/gen_ndr/ndr_security.h"
31 #include "libcli/security/security.h"
32 #include "torture/rpc/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 #if 0
4810         /* FIXME: not working with s3 atm. */
4811                 "torturedataex_with_subkey\\subkey",
4812                 "torturedataex_with_subkey\\subkey:0",
4813                 "torturedataex_with_subkey\\subkey:1",
4814                 "torturedataex_with_subkey\\subkey\\subsubkey",
4815                 "torturedataex_with_subkey\\subkey\\subsubkey:0",
4816                 "torturedataex_with_subkey\\subkey\\subsubkey:1",
4817 #endif
4818                 "torture,data",
4819 #if 0
4820         /* FIXME: not working with s3 atm. */
4821
4822                 "torture,data,ex",
4823                 "torture,data\\ex",
4824                 "torture\\data,ex"
4825 #endif
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                 blob_in = data_blob_talloc(tctx, NULL, 42);
4841
4842                 generate_random_buffer(blob_in.data, blob_in.length);
4843
4844                 torture_assert(tctx,
4845                         test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
4846                         "failed to call SetPrinterDataEx");
4847
4848                 torture_assert(tctx,
4849                         test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
4850                         "failed to call GetPrinterDataEx");
4851
4852                 blob_out.length = needed;
4853                 torture_assert(tctx,
4854                         test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
4855                         "failed to call EnumPrinterDataEx");
4856
4857                 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
4858                 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
4859                 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
4860
4861                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
4862                 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
4863                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
4864                 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
4865                 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
4866                 if (einfo[0].data_length > 0) {
4867                         torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
4868                 }
4869
4870                 key = talloc_strdup(tctx, keys[i]);
4871
4872                 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
4873                         return false;
4874                 }
4875
4876                 c = strchr(key, '\\');
4877                 if (c) {
4878                         int k;
4879
4880                         /* we have subkeys */
4881
4882                         *c = 0;
4883
4884                         if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
4885                                 return false;
4886                         }
4887
4888                         for (k=0; subkeys && subkeys[k]; k++) {
4889
4890                                 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
4891
4892                                 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
4893                                         return false;
4894                                 }
4895                         }
4896
4897                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4898                                 return false;
4899                         }
4900
4901                 } else {
4902                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4903                                 return false;
4904                         }
4905                 }
4906         }
4907
4908         return true;
4909 }
4910
4911 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
4912                                          struct dcerpc_pipe *p,
4913                                          struct policy_handle *handle,
4914                                          const char *printername,
4915                                          struct dcerpc_binding_handle *winreg_handle,
4916                                          struct policy_handle *hive_handle)
4917 {
4918         struct dcerpc_binding_handle *b = p->binding_handle;
4919         const char *value_name = "dog";
4920         const char *key_name = "torturedataex";
4921         enum winreg_Type types[] = {
4922                 REG_SZ,
4923                 REG_MULTI_SZ,
4924                 REG_DWORD,
4925                 REG_BINARY
4926         };
4927         const char *str = "abcdefghi";
4928         int t, s;
4929
4930         for (t=0; t < ARRAY_SIZE(types); t++) {
4931         for (s=0; s < strlen(str); s++) {
4932
4933                 enum winreg_Type type;
4934                 const char *string = talloc_strndup(tctx, str, s);
4935                 const char *array[2];
4936                 DATA_BLOB blob = data_blob_string_const(string);
4937                 DATA_BLOB data;
4938                 uint8_t *data_out;
4939                 uint32_t needed, offered = 0;
4940                 uint32_t ecount;
4941                 struct spoolss_PrinterEnumValues *einfo;
4942
4943                 array[0] = talloc_strdup(tctx, string);
4944                 array[1] = NULL;
4945
4946                 if (types[t] == REG_DWORD) {
4947                         s = 0xffff;
4948                 }
4949
4950                 if (torture_setting_bool(tctx, "samba3", false)) {
4951                         if ((types[t] == REG_MULTI_SZ) && s == 0) {
4952                                 torture_warning(tctx, "samba3 does not handle 4 byte emtpy REG_MULTI_SZ buffers");
4953                                 continue;
4954                         }
4955                 }
4956
4957                 switch (types[t]) {
4958                 case REG_BINARY:
4959                         data = blob;
4960                         offered = blob.length;
4961                         break;
4962                 case REG_DWORD:
4963                         data = data_blob_talloc(tctx, NULL, 4);
4964                         SIVAL(data.data, 0, 0x12345678);
4965                         offered = 4;
4966                         break;
4967                 case REG_SZ:
4968                         torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
4969                         type = REG_SZ;
4970                         offered = data.length;
4971                         /*strlen_m_term(data.string)*2;*/
4972                         break;
4973                 case REG_MULTI_SZ:
4974                         torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
4975                         type = REG_MULTI_SZ;
4976                         offered = data.length;
4977                         break;
4978                 default:
4979                         torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
4980                 }
4981
4982                 torture_assert(tctx,
4983                         test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
4984                         "failed to call SetPrinterDataEx");
4985
4986                 torture_assert(tctx,
4987                         test_GetPrinterDataEx(tctx, p, handle, key_name, value_name, &type, &data_out, &needed),
4988                         "failed to call GetPrinterDataEx");
4989
4990                 torture_assert(tctx,
4991                         test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
4992                         "failed to call EnumPrinterDataEx");
4993
4994                 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
4995                 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
4996                 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
4997
4998                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
4999                 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5000                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5001                 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5002                 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5003                 if (einfo[0].data_length > 0) {
5004                         torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5005                 }
5006
5007                 if (winreg_handle && hive_handle) {
5008                         enum winreg_Type w_type;
5009                         uint32_t w_size;
5010                         uint32_t w_length;
5011                         uint8_t *w_data;
5012
5013                         torture_assert(tctx,
5014                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5015                                         printername, key_name, value_name,
5016                                         &w_type, &w_size, &w_length, &w_data), "");
5017
5018                         torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5019                         torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5020                         torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5021                         torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5022                 }
5023
5024                 torture_assert(tctx,
5025                         test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5026                         "failed to call DeletePrinterDataEx");
5027         }
5028         }
5029
5030         return true;
5031 }
5032
5033 static bool test_PrinterData_winreg(struct torture_context *tctx,
5034                                     struct dcerpc_pipe *p,
5035                                     struct policy_handle *handle,
5036                                     const char *printer_name)
5037 {
5038         struct dcerpc_binding_handle *b = p->binding_handle;
5039         struct dcerpc_pipe *p2;
5040         bool ret = true;
5041         struct policy_handle hive_handle;
5042         struct dcerpc_binding_handle *b2;
5043
5044         torture_assert_ntstatus_ok(tctx,
5045                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5046                 "could not open winreg pipe");
5047         b2 = p2->binding_handle;
5048
5049         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5050
5051         ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5052         ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5053
5054         test_winreg_CloseKey(tctx, b2, &hive_handle);
5055
5056         talloc_free(p2);
5057
5058         return ret;
5059 }
5060
5061 static bool test_Forms_winreg(struct torture_context *tctx,
5062                               struct dcerpc_binding_handle *b,
5063                               struct policy_handle *handle,
5064                               bool print_server,
5065                               const char *printer_name)
5066 {
5067         struct dcerpc_pipe *p2;
5068         bool ret = true;
5069         struct policy_handle hive_handle;
5070         struct dcerpc_binding_handle *b2;
5071
5072         torture_assert_ntstatus_ok(tctx,
5073                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5074                 "could not open winreg pipe");
5075         b2 = p2->binding_handle;
5076
5077         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5078
5079         ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5080
5081         test_winreg_CloseKey(tctx, b2, &hive_handle);
5082
5083         talloc_free(p2);
5084
5085         return ret;
5086 }
5087
5088 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5089                                     struct dcerpc_pipe *p,
5090                                     struct policy_handle *handle,
5091                                     const char *printer_name)
5092 {
5093         struct dcerpc_binding_handle *b = p->binding_handle;
5094         struct dcerpc_pipe *p2;
5095         bool ret = true;
5096         struct policy_handle hive_handle;
5097         struct dcerpc_binding_handle *b2;
5098
5099         torture_assert_ntstatus_ok(tctx,
5100                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5101                 "could not open winreg pipe");
5102         b2 = p2->binding_handle;
5103
5104         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5105
5106         ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5107
5108         test_winreg_CloseKey(tctx, b2, &hive_handle);
5109
5110         talloc_free(p2);
5111
5112         return ret;
5113 }
5114
5115 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5116                                    struct dcerpc_pipe *p,
5117                                    struct policy_handle *handle,
5118                                    const char *printer_name,
5119                                    const char *driver_name,
5120                                    const char *environment)
5121 {
5122         struct dcerpc_binding_handle *b = p->binding_handle;
5123         struct dcerpc_pipe *p2;
5124         bool ret = true;
5125         struct policy_handle hive_handle;
5126         struct dcerpc_binding_handle *b2;
5127
5128         torture_assert_ntstatus_ok(tctx,
5129                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5130                 "could not open winreg pipe");
5131         b2 = p2->binding_handle;
5132
5133         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5134
5135         ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, 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_PrintProcessors_winreg(struct torture_context *tctx,
5145                                         struct dcerpc_binding_handle *b,
5146                                         const char *environment)
5147 {
5148         struct dcerpc_pipe *p2;
5149         bool ret = true;
5150         struct policy_handle hive_handle;
5151         struct dcerpc_binding_handle *b2;
5152
5153         torture_assert_ntstatus_ok(tctx,
5154                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5155                 "could not open winreg pipe");
5156         b2 = p2->binding_handle;
5157
5158         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5159
5160         ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5161
5162         test_winreg_CloseKey(tctx, b2, &hive_handle);
5163
5164         talloc_free(p2);
5165
5166         return ret;
5167 }
5168
5169 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5170                                        struct dcerpc_pipe *p,
5171                                        struct policy_handle *handle,
5172                                        const char *printer_name)
5173 {
5174         struct spoolss_SetPrinterInfoCtr info_ctr;
5175         struct spoolss_DevmodeContainer devmode_ctr;
5176         struct sec_desc_buf secdesc_ctr;
5177         union spoolss_SetPrinterInfo sinfo;
5178         union spoolss_PrinterInfo info;
5179         struct dcerpc_binding_handle *b = p->binding_handle;
5180         const char *pname;
5181
5182         ZERO_STRUCT(info_ctr);
5183         ZERO_STRUCT(devmode_ctr);
5184         ZERO_STRUCT(secdesc_ctr);
5185
5186         torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5187
5188         torture_assert(tctx,
5189                 test_GetPrinter_level(tctx, b, handle, 2, &info),
5190                 "failed to query Printer level 2");
5191
5192         torture_assert(tctx,
5193                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5194                 "failed to convert");
5195
5196         info_ctr.level = 2;
5197         info_ctr.info = sinfo;
5198
5199 #define TEST_SZ(wname, iname) \
5200 do {\
5201         enum winreg_Type type;\
5202         uint8_t *data;\
5203         uint32_t needed;\
5204         DATA_BLOB blob;\
5205         const char *str;\
5206         torture_assert(tctx,\
5207                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5208                 "failed to query");\
5209         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5210         blob = data_blob_const(data, needed);\
5211         torture_assert(tctx,\
5212                 pull_reg_sz(tctx, &blob, &str),\
5213                 "failed to pull REG_SZ");\
5214         torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5215 } while(0);
5216
5217
5218 #define TEST_SET_SZ(wname, iname, val) \
5219 do {\
5220         enum winreg_Type type;\
5221         uint8_t *data;\
5222         uint32_t needed;\
5223         DATA_BLOB blob;\
5224         const char *str;\
5225         sinfo.info2->iname = val;\
5226         torture_assert(tctx,\
5227                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5228                 "failed to call SetPrinter");\
5229         torture_assert(tctx,\
5230                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5231                 "failed to query");\
5232         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5233         blob = data_blob_const(data, needed);\
5234         torture_assert(tctx,\
5235                 pull_reg_sz(tctx, &blob, &str),\
5236                 "failed to pull REG_SZ");\
5237         torture_assert_str_equal(tctx, str, val, "unexpected result");\
5238 } while(0);
5239
5240 #define TEST_SET_DWORD(wname, iname, val) \
5241 do {\
5242         enum winreg_Type type;\
5243         uint8_t *data;\
5244         uint32_t needed;\
5245         uint32_t value;\
5246         sinfo.info2->iname = val;\
5247         torture_assert(tctx,\
5248                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5249                 "failed to call SetPrinter");\
5250         torture_assert(tctx,\
5251                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5252                 "failed to query");\
5253         torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5254         torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5255         value = IVAL(data, 0); \
5256         torture_assert_int_equal(tctx, value, val, "unexpected result");\
5257 } while(0);
5258
5259         TEST_SET_SZ("description", comment, "newval");
5260         TEST_SET_SZ("location", location, "newval");
5261 /*      TEST_SET_DWORD("priority", priority, 25); */
5262
5263         torture_assert(tctx,
5264                 test_GetPrinter_level(tctx, b, handle, 2, &info),
5265                 "failed to query Printer level 2");
5266
5267         TEST_SZ("description", info.info2.comment);
5268 /*      TEST_SZ("driverName", info.info2.drivername); */
5269         TEST_SZ("location", info.info2.location);
5270
5271         pname = strrchr(info.info2.printername, '\\');
5272         if (pname == NULL) {
5273                 pname = info.info2.printername;
5274         } else {
5275                 pname++;
5276         }
5277 /*      TEST_SZ("printerName", pname); */
5278         /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5279         /* TEST_SZ("printShareName", info.info2.sharename); */
5280
5281         /* FIXME gd: complete the list */
5282
5283 #undef TEST_SZ
5284 #undef TEST_SET_SZ
5285 #undef TEST_DWORD
5286
5287         torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5288
5289         return true;
5290 }
5291
5292 static bool test_print_processors_winreg(struct torture_context *tctx,
5293                                          void *private_data)
5294 {
5295         struct test_spoolss_context *ctx =
5296                 talloc_get_type_abort(private_data, struct test_spoolss_context);
5297         struct dcerpc_pipe *p = ctx->spoolss_pipe;
5298         struct dcerpc_binding_handle *b = p->binding_handle;
5299
5300         return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5301 }
5302
5303 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5304                                          struct dcerpc_binding_handle *b,
5305                                          struct policy_handle *handle,
5306                                          uint32_t *change_id)
5307 {
5308         enum winreg_Type type;
5309         uint8_t *data;
5310         uint32_t needed;
5311
5312         torture_assert(tctx,
5313                 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5314                 "failed to call GetPrinterData");
5315
5316         torture_assert(tctx, type == REG_DWORD, "unexpected type");
5317         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5318
5319         *change_id = IVAL(data, 0);
5320
5321         return true;
5322 }
5323
5324 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5325                                            struct dcerpc_pipe *p,
5326                                            struct policy_handle *handle,
5327                                            uint32_t *change_id)
5328 {
5329         enum winreg_Type type;
5330         uint8_t *data;
5331         uint32_t needed;
5332
5333         torture_assert(tctx,
5334                 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5335                 "failed to call GetPrinterData");
5336
5337         torture_assert(tctx, type == REG_DWORD, "unexpected type");
5338         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5339
5340         *change_id = IVAL(data, 0);
5341
5342         return true;
5343 }
5344
5345 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5346                                          struct dcerpc_binding_handle *b,
5347                                          struct policy_handle *handle,
5348                                          uint32_t *change_id)
5349 {
5350         union spoolss_PrinterInfo info;
5351
5352         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5353                 "failed to query Printer level 0");
5354
5355         *change_id = info.info0.change_id;
5356
5357         return true;
5358 }
5359
5360 static bool test_ChangeID(struct torture_context *tctx,
5361                           struct dcerpc_pipe *p,
5362                           struct policy_handle *handle)
5363 {
5364         uint32_t change_id, change_id_ex, change_id_info;
5365         uint32_t change_id2, change_id_ex2, change_id_info2;
5366         union spoolss_PrinterInfo info;
5367         const char *comment;
5368         struct dcerpc_binding_handle *b = p->binding_handle;
5369
5370         torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5371
5372         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5373                 "failed to query for ChangeID");
5374         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5375                 "failed to query for ChangeID");
5376         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5377                 "failed to query for ChangeID");
5378
5379         torture_assert_int_equal(tctx, change_id, change_id_ex,
5380                 "change_ids should all be equal");
5381         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5382                 "change_ids should all be equal");
5383
5384
5385         torture_comment(tctx, "Testing ChangeID: id change test #2\n");
5386
5387         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5388                 "failed to query for ChangeID");
5389         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5390                 "failed to query Printer level 2");
5391         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5392                 "failed to query for ChangeID");
5393         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5394                 "failed to query for ChangeID");
5395         torture_assert_int_equal(tctx, change_id, change_id_ex,
5396                 "change_id should not have changed");
5397         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5398                 "change_id should not have changed");
5399
5400
5401         torture_comment(tctx, "Testing ChangeID: id change test #3\n");
5402
5403         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5404                 "failed to query for ChangeID");
5405         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5406                 "failed to query for ChangeID");
5407         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5408                 "failed to query for ChangeID");
5409         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5410                 "failed to query Printer level 2");
5411         comment = talloc_strdup(tctx, info.info2.comment);
5412
5413         {
5414                 struct spoolss_SetPrinterInfoCtr info_ctr;
5415                 struct spoolss_DevmodeContainer devmode_ctr;
5416                 struct sec_desc_buf secdesc_ctr;
5417                 union spoolss_SetPrinterInfo sinfo;
5418
5419                 ZERO_STRUCT(info_ctr);
5420                 ZERO_STRUCT(devmode_ctr);
5421                 ZERO_STRUCT(secdesc_ctr);
5422
5423
5424                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5425                 sinfo.info2->comment    = "torture_comment";
5426
5427                 info_ctr.level = 2;
5428                 info_ctr.info = sinfo;
5429
5430                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5431                         "failed to call SetPrinter");
5432
5433                 sinfo.info2->comment    = comment;
5434
5435                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5436                         "failed to call SetPrinter");
5437
5438         }
5439
5440         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5441                 "failed to query for ChangeID");
5442         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5443                 "failed to query for ChangeID");
5444         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5445                 "failed to query for ChangeID");
5446
5447         torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5448                 "change_ids should all be equal");
5449         torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5450                 "change_ids should all be equal");
5451
5452         torture_assert(tctx, (change_id < change_id2),
5453                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5454                 change_id2, change_id));
5455         torture_assert(tctx, (change_id_ex < change_id_ex2),
5456                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5457                 change_id_ex2, change_id_ex));
5458         torture_assert(tctx, (change_id_info < change_id_info2),
5459                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5460                 change_id_info2, change_id_info));
5461
5462         torture_comment(tctx, "ChangeID tests succeeded\n\n");
5463
5464         return true;
5465 }
5466
5467 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5468                                        struct dcerpc_pipe *p,
5469                                        struct policy_handle *handle)
5470 {
5471         NTSTATUS status;
5472         struct dcerpc_binding *b;
5473         struct dcerpc_pipe *p2;
5474         struct spoolss_ClosePrinter cp;
5475
5476         /* only makes sense on SMB */
5477         if (p->conn->transport.transport != NCACN_NP) {
5478                 return true;
5479         }
5480
5481         torture_comment(tctx, "Testing close on secondary pipe\n");
5482
5483         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
5484         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
5485
5486         status = dcerpc_secondary_connection(p, &p2, b);
5487         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
5488
5489         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
5490         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
5491
5492         cp.in.handle = handle;
5493         cp.out.handle = handle;
5494
5495         status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
5496         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
5497                         "ERROR: Allowed close on secondary connection");
5498
5499         talloc_free(p2);
5500
5501         return true;
5502 }
5503
5504 static bool test_OpenPrinter_badname(struct torture_context *tctx,
5505                                      struct dcerpc_binding_handle *b, const char *name)
5506 {
5507         NTSTATUS status;
5508         struct spoolss_OpenPrinter op;
5509         struct spoolss_OpenPrinterEx opEx;
5510         struct policy_handle handle;
5511         bool ret = true;
5512
5513         op.in.printername       = name;
5514         op.in.datatype          = NULL;
5515         op.in.devmode_ctr.devmode= NULL;
5516         op.in.access_mask       = 0;
5517         op.out.handle           = &handle;
5518
5519         torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
5520
5521         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
5522         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5523         torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
5524                 "unexpected result");
5525
5526         if (W_ERROR_IS_OK(op.out.result)) {
5527                 ret &=test_ClosePrinter(tctx, b, &handle);
5528         }
5529
5530         opEx.in.printername             = name;
5531         opEx.in.datatype                = NULL;
5532         opEx.in.devmode_ctr.devmode     = NULL;
5533         opEx.in.access_mask             = 0;
5534         opEx.in.level                   = 1;
5535         opEx.in.userlevel.level1        = NULL;
5536         opEx.out.handle                 = &handle;
5537
5538         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
5539
5540         status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
5541         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5542         torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
5543                 "unexpected result");
5544
5545         if (W_ERROR_IS_OK(opEx.out.result)) {
5546                 ret &=test_ClosePrinter(tctx, b, &handle);
5547         }
5548
5549         return ret;
5550 }
5551
5552 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
5553                                           void *private_data)
5554 {
5555         struct test_spoolss_context *ctx =
5556                 talloc_get_type_abort(private_data, struct test_spoolss_context);
5557
5558         const char *badnames[] = {
5559                 "__INVALID_PRINTER__",
5560                 "\\\\__INVALID_HOST__",
5561                 "",
5562                 "\\\\\\",
5563                 "\\\\\\__INVALID_PRINTER__"
5564         };
5565         const char *badname;
5566         struct dcerpc_pipe *p = ctx->spoolss_pipe;
5567         const char *server_name = dcerpc_server_name(p);
5568         struct dcerpc_binding_handle *b = p->binding_handle;
5569         int i;
5570
5571         for (i=0; i < ARRAY_SIZE(badnames); i++) {
5572                 torture_assert(tctx,
5573                         test_OpenPrinter_badname(tctx, b, badnames[i]),
5574                         "");
5575         }
5576
5577         badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
5578         torture_assert(tctx,
5579                 test_OpenPrinter_badname(tctx, b, badname),
5580                 "");
5581
5582         badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
5583         torture_assert(tctx,
5584                 test_OpenPrinter_badname(tctx, b, badname),
5585                 "");
5586
5587         return true;
5588 }
5589
5590 static bool test_OpenPrinter(struct torture_context *tctx,
5591                              struct dcerpc_pipe *p,
5592                              const char *name,
5593                              const char *environment)
5594 {
5595         NTSTATUS status;
5596         struct spoolss_OpenPrinter r;
5597         struct policy_handle handle;
5598         bool ret = true;
5599         struct dcerpc_binding_handle *b = p->binding_handle;
5600
5601         r.in.printername        = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
5602         r.in.datatype           = NULL;
5603         r.in.devmode_ctr.devmode= NULL;
5604         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
5605         r.out.handle            = &handle;
5606
5607         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5608
5609         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5610
5611         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5612
5613         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5614
5615         if (!test_GetPrinter(tctx, b, &handle, environment)) {
5616                 ret = false;
5617         }
5618
5619         if (!torture_setting_bool(tctx, "samba3", false)) {
5620                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5621                         ret = false;
5622                 }
5623         }
5624
5625         if (!test_ClosePrinter(tctx, b, &handle)) {
5626                 ret = false;
5627         }
5628
5629         return ret;
5630 }
5631
5632 static bool call_OpenPrinterEx(struct torture_context *tctx,
5633                                struct dcerpc_pipe *p,
5634                                const char *name,
5635                                struct spoolss_DeviceMode *devmode,
5636                                struct policy_handle *handle)
5637 {
5638         struct spoolss_OpenPrinterEx r;
5639         struct spoolss_UserLevel1 userlevel1;
5640         NTSTATUS status;
5641         struct dcerpc_binding_handle *b = p->binding_handle;
5642
5643         if (name && name[0]) {
5644                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
5645                                                    dcerpc_server_name(p), name);
5646         } else {
5647                 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
5648                                                    dcerpc_server_name(p));
5649         }
5650
5651         r.in.datatype           = NULL;
5652         r.in.devmode_ctr.devmode= devmode;
5653         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
5654         r.in.level              = 1;
5655         r.in.userlevel.level1   = &userlevel1;
5656         r.out.handle = handle;
5657
5658         userlevel1.size = 1234;
5659         userlevel1.client = "hello";
5660         userlevel1.user = "spottyfoot!";
5661         userlevel1.build = 1;
5662         userlevel1.major = 2;
5663         userlevel1.minor = 3;
5664         userlevel1.processor = 4;
5665
5666         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5667
5668         status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r);
5669
5670         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5671
5672         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
5673
5674         return true;
5675 }
5676
5677 static bool test_printer_rename(struct torture_context *tctx,
5678                                 void *private_data)
5679 {
5680         struct torture_printer_context *t =
5681                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
5682         struct dcerpc_pipe *p = t->spoolss_pipe;
5683
5684         bool ret = true;
5685         union spoolss_PrinterInfo info;
5686         union spoolss_SetPrinterInfo sinfo;
5687         struct spoolss_SetPrinterInfoCtr info_ctr;
5688         struct spoolss_DevmodeContainer devmode_ctr;
5689         struct sec_desc_buf secdesc_ctr;
5690         const char *printer_name;
5691         const char *printer_name_orig;
5692         const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5693         struct policy_handle new_handle;
5694         const char *q;
5695         struct dcerpc_binding_handle *b = p->binding_handle;
5696
5697         ZERO_STRUCT(devmode_ctr);
5698         ZERO_STRUCT(secdesc_ctr);
5699
5700         torture_comment(tctx, "Testing Printer rename operations\n");
5701
5702         torture_assert(tctx,
5703                 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5704                 "failed to call GetPrinter level 2");
5705
5706         printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5707
5708         q = strrchr(info.info2.printername, '\\');
5709         if (q) {
5710                 torture_warning(tctx,
5711                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5712         }
5713
5714         torture_assert(tctx,
5715                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5716
5717         sinfo.info2->printername = printer_name_new;
5718
5719         info_ctr.level = 2;
5720         info_ctr.info = sinfo;
5721
5722         torture_assert(tctx,
5723                 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5724                 "failed to call SetPrinter level 2");
5725
5726         torture_assert(tctx,
5727                 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5728                 "failed to call GetPrinter level 2");
5729
5730         printer_name = talloc_strdup(tctx, info.info2.printername);
5731
5732         q = strrchr(info.info2.printername, '\\');
5733         if (q) {
5734                 torture_warning(tctx,
5735                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5736                 q++;
5737                 printer_name = q;
5738         }
5739
5740         torture_assert_str_equal(tctx, printer_name, printer_name_new,
5741                 "new printer name was not set");
5742
5743         /* samba currently cannot fully rename printers */
5744         if (!torture_setting_bool(tctx, "samba3", false)) {
5745                 torture_assert(tctx,
5746                         test_OpenPrinter_badname(tctx, b, printer_name_orig),
5747                         "still can open printer with oldname after rename");
5748         } else {
5749                 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
5750         }
5751
5752         torture_assert(tctx,
5753                 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
5754                 "failed to open printer with new name");
5755
5756         torture_assert(tctx,
5757                 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
5758                 "failed to call GetPrinter level 2");
5759
5760         /* FIXME: we openend with servername! */
5761         printer_name = talloc_asprintf(tctx, "\\\\%s\\%s",
5762                 dcerpc_server_name(p), printer_name_new);
5763
5764         torture_assert_str_equal(tctx, info.info2.printername, printer_name,
5765                 "new printer name was not set");
5766
5767         torture_assert(tctx,
5768                 test_ClosePrinter(tctx, b, &new_handle),
5769                 "failed to close printer");
5770
5771         torture_comment(tctx, "Printer rename operations test succeeded\n\n");
5772
5773         return ret;
5774 }
5775
5776
5777 static bool test_OpenPrinterEx(struct torture_context *tctx,
5778                                struct dcerpc_pipe *p,
5779                                const char *name,
5780                                const char *environment)
5781 {
5782         struct policy_handle handle;
5783         bool ret = true;
5784         struct dcerpc_binding_handle *b = p->binding_handle;
5785
5786         if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
5787                 return false;
5788         }
5789
5790         if (!test_PrinterInfo_SD(tctx, b, &handle)) {
5791                 ret = false;
5792         }
5793
5794         if (!test_GetPrinter(tctx, b, &handle, environment)) {
5795                 ret = false;
5796         }
5797
5798         if (!test_EnumForms_all(tctx, b, &handle, false)) {
5799                 ret = false;
5800         }
5801
5802         if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
5803                 ret = false;
5804         }
5805
5806         if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
5807                 ret = false;
5808         }
5809
5810         if (!test_EnumPrinterData_all(tctx, p, &handle)) {
5811                 ret = false;
5812         }
5813
5814         if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
5815                 ret = false;
5816         }
5817
5818         if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
5819                 ret = false;
5820         }
5821
5822         if (!test_printer_all_keys(tctx, b, &handle)) {
5823                 ret = false;
5824         }
5825
5826         if (!test_PausePrinter(tctx, b, &handle)) {
5827                 ret = false;
5828         }
5829
5830         if (!test_DoPrintTest(tctx, b, &handle)) {
5831                 ret = false;
5832         }
5833
5834         if (!test_ResumePrinter(tctx, b, &handle)) {
5835                 ret = false;
5836         }
5837
5838         if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
5839                 ret = false;
5840         }
5841
5842         if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
5843                 ret = false;
5844         }
5845
5846         if (!torture_setting_bool(tctx, "samba3", false)) {
5847                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5848                         ret = false;
5849                 }
5850         }
5851
5852         if (!test_ClosePrinter(tctx, b, &handle)) {
5853                 ret = false;
5854         }
5855
5856         return ret;
5857 }
5858
5859 static bool test_EnumPrinters_old(struct torture_context *tctx,
5860                                   void *private_data)
5861 {
5862         struct test_spoolss_context *ctx =
5863                 talloc_get_type_abort(private_data, struct test_spoolss_context);
5864         struct spoolss_EnumPrinters r;
5865         NTSTATUS status;
5866         uint16_t levels[] = {1, 2, 4, 5};
5867         int i;
5868         bool ret = true;
5869         struct dcerpc_pipe *p = ctx->spoolss_pipe;
5870         struct dcerpc_binding_handle *b = p->binding_handle;
5871
5872         for (i=0;i<ARRAY_SIZE(levels);i++) {
5873                 union spoolss_PrinterInfo *info;
5874                 int j;
5875                 uint32_t needed;
5876                 uint32_t count;
5877
5878                 r.in.flags      = PRINTER_ENUM_LOCAL;
5879                 r.in.server     = "";
5880                 r.in.level      = levels[i];
5881                 r.in.buffer     = NULL;
5882                 r.in.offered    = 0;
5883                 r.out.needed    = &needed;
5884                 r.out.count     = &count;
5885                 r.out.info      = &info;
5886
5887                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
5888
5889                 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
5890                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
5891
5892                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5893                         DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5894                         r.in.buffer = &blob;
5895                         r.in.offered = needed;
5896                         status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
5897                 }
5898
5899                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
5900
5901                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
5902
5903                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
5904
5905                 if (!info) {
5906                         torture_comment(tctx, "No printers returned\n");
5907                         return true;
5908                 }
5909
5910                 for (j=0;j<count;j++) {
5911                         if (r.in.level == 1) {
5912                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
5913                                 char *slash, *name;
5914                                 name = unc;
5915                                 if (unc[0] == '\\' && unc[1] == '\\') {
5916                                         unc +=2;
5917                                 }
5918                                 slash = strchr(unc, '\\');
5919                                 if (slash) {
5920                                         slash++;
5921                                         name = slash;
5922                                 }
5923                                 if (!test_OpenPrinter(tctx, p, name, ctx->environment)) {
5924                                         ret = false;
5925                                 }
5926                                 if (!test_OpenPrinterEx(tctx, p, name, ctx->environment)) {
5927                                         ret = false;
5928                                 }
5929                         }
5930                 }
5931         }
5932
5933         return ret;
5934 }
5935
5936 static bool test_GetPrinterDriver(struct torture_context *tctx,
5937                                   struct dcerpc_binding_handle *b,
5938                                   struct policy_handle *handle,
5939                                   const char *driver_name)
5940 {
5941         struct spoolss_GetPrinterDriver r;
5942         uint32_t needed;
5943
5944         r.in.handle = handle;
5945         r.in.architecture = "W32X86";
5946         r.in.level = 1;
5947         r.in.buffer = NULL;
5948         r.in.offered = 0;
5949         r.out.needed = &needed;
5950
5951         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
5952
5953         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
5954                 "failed to call GetPrinterDriver");
5955         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5956                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5957                 r.in.buffer = &blob;
5958                 r.in.offered = needed;
5959                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
5960                         "failed to call GetPrinterDriver");
5961         }
5962
5963         torture_assert_werr_ok(tctx, r.out.result,
5964                 "failed to call GetPrinterDriver");
5965
5966         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
5967
5968         return true;
5969 }
5970
5971 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
5972                                          struct dcerpc_binding_handle *b,
5973                                          struct policy_handle *handle,
5974                                          const char *driver_name,
5975                                          const char *architecture,
5976                                          uint32_t level,
5977                                          uint32_t client_major_version,
5978                                          uint32_t client_minor_version,
5979                                          union spoolss_DriverInfo *info_p,
5980                                          WERROR *result_p)
5981
5982 {
5983         struct spoolss_GetPrinterDriver2 r;
5984         uint32_t needed;
5985         uint32_t server_major_version;
5986         uint32_t server_minor_version;
5987
5988         r.in.handle = handle;
5989         r.in.architecture = architecture;
5990         r.in.client_major_version = client_major_version;
5991         r.in.client_minor_version = client_minor_version;
5992         r.in.buffer = NULL;
5993         r.in.offered = 0;
5994         r.in.level = level;
5995         r.out.needed = &needed;
5996         r.out.server_major_version = &server_major_version;
5997         r.out.server_minor_version = &server_minor_version;
5998
5999         torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
6000                 driver_name, r.in.level);
6001
6002         torture_assert_ntstatus_ok(tctx,
6003                 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6004                 "failed to call GetPrinterDriver2");
6005         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6006                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6007                 r.in.buffer = &blob;
6008                 r.in.offered = needed;
6009                 torture_assert_ntstatus_ok(tctx,
6010                         dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6011                         "failed to call GetPrinterDriver2");
6012         }
6013
6014         if (result_p) {
6015                 *result_p = r.out.result;
6016         }
6017
6018         if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
6019                 switch (r.in.level) {
6020                 case 101:
6021                 case 8:
6022                         torture_comment(tctx,
6023                                 "level %d not implemented, not considering as an error\n",
6024                                 r.in.level);
6025                         return true;
6026                 default:
6027                         break;
6028                 }
6029         }
6030
6031         torture_assert_werr_ok(tctx, r.out.result,
6032                 "failed to call GetPrinterDriver2");
6033
6034         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6035
6036         if (info_p) {
6037                 *info_p = *r.out.info;
6038         }
6039
6040         return true;
6041 }
6042
6043 static bool test_GetPrinterDriver2(struct torture_context *tctx,
6044                                    struct dcerpc_binding_handle *b,
6045                                    struct policy_handle *handle,
6046                                    const char *driver_name,
6047                                    const char *architecture)
6048 {
6049         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
6050         int i;
6051
6052
6053         for (i=0;i<ARRAY_SIZE(levels);i++) {
6054
6055                 torture_assert(tctx,
6056                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
6057                         "");
6058         }
6059
6060         return true;
6061 }
6062
6063 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
6064                                         void *private_data)
6065 {
6066         struct test_spoolss_context *ctx =
6067                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6068         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
6069         int i;
6070         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6071         struct dcerpc_binding_handle *b = p->binding_handle;
6072         const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6073
6074         for (i=0;i<ARRAY_SIZE(levels);i++) {
6075
6076                 uint32_t count;
6077                 union spoolss_DriverInfo *info;
6078
6079                 torture_assert(tctx,
6080                         test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
6081                         "failed to enumerate drivers");
6082
6083                 if (!info) {
6084                         torture_comment(tctx, "No printer drivers returned\n");
6085                         break;
6086                 }
6087         }
6088
6089         return true;
6090 }
6091
6092 static bool test_DeletePrinter(struct torture_context *tctx,
6093                                struct dcerpc_binding_handle *b,
6094                                struct policy_handle *handle)
6095 {
6096         struct spoolss_DeletePrinter r;
6097
6098         torture_comment(tctx, "Testing DeletePrinter\n");
6099
6100         r.in.handle = handle;
6101
6102         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
6103                 "failed to delete printer");
6104         torture_assert_werr_ok(tctx, r.out.result,
6105                 "failed to delete printer");
6106
6107         return true;
6108 }
6109
6110 static bool test_EnumPrinters_findname(struct torture_context *tctx,
6111                                        struct dcerpc_binding_handle *b,
6112                                        uint32_t flags,
6113                                        uint32_t level,
6114                                        const char *name,
6115                                        bool *found)
6116 {
6117         struct spoolss_EnumPrinters e;
6118         uint32_t count;
6119         union spoolss_PrinterInfo *info;
6120         uint32_t needed;
6121         int i;
6122
6123         *found = false;
6124
6125         e.in.flags = flags;
6126         e.in.server = NULL;
6127         e.in.level = level;
6128         e.in.buffer = NULL;
6129         e.in.offered = 0;
6130         e.out.count = &count;
6131         e.out.info = &info;
6132         e.out.needed = &needed;
6133
6134         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6135                 "failed to enum printers");
6136
6137         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
6138                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6139                 e.in.buffer = &blob;
6140                 e.in.offered = needed;
6141
6142                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6143                         "failed to enum printers");
6144         }
6145
6146         torture_assert_werr_ok(tctx, e.out.result,
6147                 "failed to enum printers");
6148
6149         for (i=0; i < count; i++) {
6150
6151                 const char *current = NULL;
6152                 const char *q;
6153
6154                 switch (level) {
6155                 case 1:
6156                         current = info[i].info1.name;
6157                         break;
6158                 }
6159
6160                 if (strequal(current, name)) {
6161                         *found = true;
6162                         break;
6163                 }
6164
6165                 q = strrchr(current, '\\');
6166                 if (q) {
6167                         if (!e.in.server) {
6168                                 torture_warning(tctx,
6169                                         "server returns printername %s incl. servername although we did not set servername", current);
6170                         }
6171                         q++;
6172                         if (strequal(q, name)) {
6173                                 *found = true;
6174                                 break;
6175                         }
6176                 }
6177         }
6178
6179         return true;
6180 }
6181
6182 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
6183                                       struct dcerpc_pipe *p,
6184                                       const char *printername,
6185                                       bool ex)
6186 {
6187         WERROR result;
6188         struct spoolss_AddPrinter r;
6189         struct spoolss_AddPrinterEx rex;
6190         struct spoolss_SetPrinterInfoCtr info_ctr;
6191         struct spoolss_SetPrinterInfo1 info1;
6192         struct spoolss_DevmodeContainer devmode_ctr;
6193         struct sec_desc_buf secdesc_ctr;
6194         struct spoolss_UserLevelCtr userlevel_ctr;
6195         struct policy_handle handle;
6196         bool found = false;
6197         struct dcerpc_binding_handle *b = p->binding_handle;
6198
6199         ZERO_STRUCT(devmode_ctr);
6200         ZERO_STRUCT(secdesc_ctr);
6201         ZERO_STRUCT(userlevel_ctr);
6202         ZERO_STRUCT(info1);
6203
6204         torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
6205                         ex ? "Ex":"", printername);
6206
6207         /* try to add printer to wellknown printer list (level 1) */
6208
6209         userlevel_ctr.level = 1;
6210
6211         info_ctr.info.info1 = &info1;
6212         info_ctr.level = 1;
6213
6214         rex.in.server = NULL;
6215         rex.in.info_ctr = &info_ctr;
6216         rex.in.devmode_ctr = &devmode_ctr;
6217         rex.in.secdesc_ctr = &secdesc_ctr;
6218         rex.in.userlevel_ctr = &userlevel_ctr;
6219         rex.out.handle = &handle;
6220
6221         r.in.server = NULL;
6222         r.in.info_ctr = &info_ctr;
6223         r.in.devmode_ctr = &devmode_ctr;
6224         r.in.secdesc_ctr = &secdesc_ctr;
6225         r.out.handle = &handle;
6226
6227         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6228                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6229                 "failed to add printer");
6230         result = ex ? rex.out.result : r.out.result;
6231         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6232                 "unexpected result code");
6233
6234         info1.name = printername;
6235         info1.flags = PRINTER_ATTRIBUTE_SHARED;
6236
6237         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6238                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6239                 "failed to add printer");
6240         result = ex ? rex.out.result : r.out.result;
6241         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6242                 "unexpected result code");
6243
6244         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6245            better do a real check to see the printer is really there */
6246
6247         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6248                                                         PRINTER_ENUM_NETWORK, 1,
6249                                                         printername,
6250                                                         &found),
6251                         "failed to enum printers");
6252
6253         torture_assert(tctx, found, "failed to find newly added printer");
6254
6255         info1.flags = 0;
6256
6257         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6258                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6259                 "failed to add printer");
6260         result = ex ? rex.out.result : r.out.result;
6261         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6262                 "unexpected result code");
6263
6264         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6265            better do a real check to see the printer has really been removed
6266            from the well known printer list */
6267
6268         found = false;
6269
6270         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6271                                                         PRINTER_ENUM_NETWORK, 1,
6272                                                         printername,
6273                                                         &found),
6274                         "failed to enum printers");
6275 #if 0
6276         torture_assert(tctx, !found, "printer still in well known printer list");
6277 #endif
6278         return true;
6279 }
6280
6281 static bool test_AddPrinter_normal(struct torture_context *tctx,
6282                                    struct dcerpc_pipe *p,
6283                                    struct policy_handle *handle_p,
6284                                    const char *printername,
6285                                    const char *drivername,
6286                                    const char *portname,
6287                                    struct spoolss_DeviceMode *devmode,
6288                                    bool ex)
6289 {
6290         WERROR result;
6291         struct spoolss_AddPrinter r;
6292         struct spoolss_AddPrinterEx rex;
6293         struct spoolss_SetPrinterInfoCtr info_ctr;
6294         struct spoolss_SetPrinterInfo2 info2;
6295         struct spoolss_DevmodeContainer devmode_ctr;
6296         struct sec_desc_buf secdesc_ctr;
6297         struct spoolss_UserLevelCtr userlevel_ctr;
6298         struct policy_handle handle;
6299         bool found = false;
6300         bool existing_printer_deleted = false;
6301         struct dcerpc_binding_handle *b = p->binding_handle;
6302
6303         ZERO_STRUCT(devmode_ctr);
6304         ZERO_STRUCT(secdesc_ctr);
6305         ZERO_STRUCT(userlevel_ctr);
6306
6307         torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
6308                         ex ? "Ex":"", printername);
6309
6310         devmode_ctr.devmode = devmode;
6311
6312         userlevel_ctr.level = 1;
6313
6314         rex.in.server = NULL;
6315         rex.in.info_ctr = &info_ctr;
6316         rex.in.devmode_ctr = &devmode_ctr;
6317         rex.in.secdesc_ctr = &secdesc_ctr;
6318         rex.in.userlevel_ctr = &userlevel_ctr;
6319         rex.out.handle = &handle;
6320
6321         r.in.server = NULL;
6322         r.in.info_ctr = &info_ctr;
6323         r.in.devmode_ctr = &devmode_ctr;
6324         r.in.secdesc_ctr = &secdesc_ctr;
6325         r.out.handle = &handle;
6326
6327  again:
6328
6329         /* try to add printer to printer list (level 2) */
6330
6331         ZERO_STRUCT(info2);
6332
6333         info_ctr.info.info2 = &info2;
6334         info_ctr.level = 2;
6335
6336         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6337                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6338                 "failed to add printer");
6339         result = ex ? rex.out.result : r.out.result;
6340         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6341                 "unexpected result code");
6342
6343         info2.printername = printername;
6344
6345         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6346                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6347                 "failed to add printer");
6348         result = ex ? rex.out.result : r.out.result;
6349
6350         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
6351                 struct policy_handle printer_handle;
6352
6353                 if (existing_printer_deleted) {
6354                         torture_fail(tctx, "already deleted printer still existing?");
6355                 }
6356
6357                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
6358                         "failed to open printer handle");
6359
6360                 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
6361                         "failed to delete printer");
6362
6363                 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
6364                         "failed to close server handle");
6365
6366                 existing_printer_deleted = true;
6367
6368                 goto again;
6369         }
6370
6371         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
6372                 "unexpected result code");
6373
6374         info2.portname = portname;
6375
6376         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6377                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6378                 "failed to add printer");
6379         result = ex ? rex.out.result : r.out.result;
6380         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
6381                 "unexpected result code");
6382
6383         info2.drivername = drivername;
6384
6385         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6386                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6387                 "failed to add printer");
6388         result = ex ? rex.out.result : r.out.result;
6389
6390         /* w2k8r2 allows to add printer w/o defining printprocessor */
6391
6392         if (!W_ERROR_IS_OK(result)) {
6393                 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
6394                         "unexpected result code");
6395
6396                 info2.printprocessor = "winprint";
6397
6398                 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6399                                                       dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6400                         "failed to add printer");
6401                 result = ex ? rex.out.result : r.out.result;
6402                 torture_assert_werr_ok(tctx, result,
6403                         "failed to add printer");
6404         }
6405
6406         *handle_p = handle;
6407
6408         /* we are paranoid, really check if the printer is there now */
6409
6410         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6411                                                         PRINTER_ENUM_LOCAL, 1,
6412                                                         printername,
6413                                                         &found),
6414                         "failed to enum printers");
6415         torture_assert(tctx, found, "failed to find newly added printer");
6416
6417         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6418                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6419                 "failed to add printer");
6420         result = ex ? rex.out.result : r.out.result;
6421         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6422                 "unexpected result code");
6423
6424         return true;
6425 }
6426
6427 static bool test_printer_info(struct torture_context *tctx,
6428                               void *private_data)
6429 {
6430         struct torture_printer_context *t =
6431                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6432         struct dcerpc_pipe *p = t->spoolss_pipe;
6433         struct dcerpc_binding_handle *b = p->binding_handle;
6434
6435         bool ret = true;
6436
6437         if (torture_setting_bool(tctx, "samba3", false)) {
6438                 torture_skip(tctx, "skipping printer info cross tests against samba 3");
6439         }
6440
6441         if (!test_PrinterInfo(tctx, b, &t->handle)) {
6442                 ret = false;
6443         }
6444
6445         if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
6446                 ret = false;
6447         }
6448
6449         return ret;
6450 }
6451
6452 static bool test_EnumPrinterKey(struct torture_context *tctx,
6453                                 struct dcerpc_binding_handle *b,
6454                                 struct policy_handle *handle,
6455                                 const char *key_name,
6456                                 const char ***array)
6457 {
6458         struct spoolss_EnumPrinterKey r;
6459         uint32_t needed = 0;
6460         union spoolss_KeyNames key_buffer;
6461         int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
6462         uint32_t _ndr_size;
6463         int i;
6464
6465         r.in.handle = handle;
6466         r.in.key_name = key_name;
6467         r.out.key_buffer = &key_buffer;
6468         r.out.needed = &needed;
6469         r.out._ndr_size = &_ndr_size;
6470
6471         for (i=0; i < ARRAY_SIZE(offered); i++) {
6472
6473                 if (offered[i] < 0 && needed) {
6474                         if (needed <= 4) {
6475                                 continue;
6476                         }
6477                         r.in.offered = needed + offered[i];
6478                 } else {
6479                         r.in.offered = offered[i];
6480                 }
6481
6482                 ZERO_STRUCT(key_buffer);
6483
6484                 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
6485
6486                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
6487                         "failed to call EnumPrinterKey");
6488                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
6489
6490                         torture_assert(tctx, (_ndr_size == r.in.offered/2),
6491                                 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
6492                                         _ndr_size, r.in.offered/2));
6493
6494                         r.in.offered = needed;
6495                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
6496                                 "failed to call EnumPrinterKey");
6497                 }
6498
6499                 if (offered[i] > 0) {
6500                         torture_assert_werr_ok(tctx, r.out.result,
6501                                 "failed to call EnumPrinterKey");
6502                 }
6503
6504                 torture_assert(tctx, (_ndr_size == r.in.offered/2),
6505                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
6506                                 _ndr_size, r.in.offered/2));
6507
6508                 torture_assert(tctx, (*r.out.needed <= r.in.offered),
6509                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
6510
6511                 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
6512                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
6513
6514                 if (key_buffer.string_array) {
6515                         uint32_t calc_needed = 0;
6516                         int s;
6517                         for (s=0; key_buffer.string_array[s]; s++) {
6518                                 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
6519                         }
6520                         if (!key_buffer.string_array[0]) {
6521                                 calc_needed += 2;
6522                         }
6523                         calc_needed += 2;
6524
6525                         torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
6526                                 "EnumPrinterKey unexpected size");
6527                 }
6528         }
6529
6530         if (array) {
6531                 *array = key_buffer.string_array;
6532         }
6533
6534         return true;
6535 }
6536
6537 bool test_printer_all_keys(struct torture_context *tctx,
6538                            struct dcerpc_binding_handle *b,
6539                            struct policy_handle *handle)
6540 {
6541         const char **key_array = NULL;
6542         int i;
6543
6544         torture_comment(tctx, "Testing Printer Keys\n");
6545
6546         torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
6547                 "failed to call test_EnumPrinterKey");
6548
6549         for (i=0; key_array && key_array[i]; i++) {
6550                 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
6551                         "failed to call test_EnumPrinterKey");
6552         }
6553         for (i=0; key_array && key_array[i]; i++) {
6554                 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
6555                         "failed to call test_EnumPrinterDataEx");
6556         }
6557
6558         torture_comment(tctx, "Printer Keys test succeeded\n\n");
6559
6560         return true;
6561 }
6562
6563 static bool test_csetprinter(struct torture_context *tctx,
6564                              void *private_data)
6565 {
6566         struct torture_printer_context *t =
6567                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6568         struct dcerpc_pipe *p = t->spoolss_pipe;
6569
6570         const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
6571         const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
6572         const char *portname = t->info2.portname;
6573
6574         union spoolss_PrinterInfo info;
6575         struct policy_handle new_handle, new_handle2;
6576         struct dcerpc_binding_handle *b = p->binding_handle;
6577
6578         torture_comment(tctx, "Testing c_setprinter\n");
6579
6580         torture_assert(tctx,
6581                 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
6582                 "failed to get level 0 printer info");
6583         torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
6584                 info.info0.c_setprinter);
6585
6586         /* check if c_setprinter on 1st handle increases after a printer has
6587          * been added */
6588
6589         torture_assert(tctx,
6590                 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
6591                 "failed to add new printer");
6592         torture_assert(tctx,
6593                 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
6594                 "failed to get level 0 printer info");
6595         torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
6596                 info.info0.c_setprinter);
6597
6598         /* check if c_setprinter on new handle increases after a printer has
6599          * been added */
6600
6601         torture_assert(tctx,
6602                 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
6603                 "failed to get level 0 printer info");
6604         torture_comment(tctx, "csetprinter on created handle: %d\n",
6605                 info.info0.c_setprinter);
6606
6607         /* open the new printer and check if c_setprinter increases */
6608
6609         torture_assert(tctx,
6610                 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
6611                 "failed to open created printer");
6612         torture_assert(tctx,
6613                 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
6614                 "failed to get level 0 printer info");
6615         torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
6616                 info.info0.c_setprinter);
6617
6618         /* cleanup */
6619
6620         torture_assert(tctx,
6621                 test_ClosePrinter(tctx, b, &new_handle2),
6622                 "failed to close printer");
6623         torture_assert(tctx,
6624                 test_DeletePrinter(tctx, b, &new_handle),
6625                 "failed to delete new printer");
6626
6627         return true;
6628 }
6629
6630 static bool compose_local_driver_directory(struct torture_context *tctx,
6631                                            const char *environment,
6632                                            const char *local_dir,
6633                                            const char **path)
6634 {
6635         char *p;
6636
6637         p = strrchr(local_dir, '/');
6638         if (!p) {
6639                 return NULL;
6640         }
6641         p++;
6642
6643         if (strequal(environment, "Windows x64")) {
6644                 if (!strequal(p, "x64")) {
6645                         *path = talloc_asprintf(tctx, "%s/x64", local_dir);
6646                 }
6647         } else if (strequal(environment, "Windows NT x86")) {
6648                 if (!strequal(p, "i386")) {
6649                         *path = talloc_asprintf(tctx, "%s/i386", local_dir);
6650                 }
6651         } else {
6652                 torture_assert(tctx, "unknown environment: '%s'\n", environment);
6653         }
6654
6655         return true;
6656 }
6657
6658 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
6659                                                      const char *devicename)
6660 {
6661         struct spoolss_DeviceMode *r;
6662
6663         r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
6664         if (r == NULL) {
6665                 return NULL;
6666         }
6667
6668         r->devicename           = talloc_strdup(r, devicename);
6669         r->specversion          = DMSPEC_NT4_AND_ABOVE;
6670         r->driverversion        = 0x0600;
6671         r->size                 = 0x00dc;
6672         r->__driverextra_length = 0;
6673         r->fields               = DEVMODE_FORMNAME |
6674                                   DEVMODE_TTOPTION |
6675                                   DEVMODE_PRINTQUALITY |
6676                                   DEVMODE_DEFAULTSOURCE |
6677                                   DEVMODE_COPIES |
6678                                   DEVMODE_SCALE |
6679                                   DEVMODE_PAPERSIZE |
6680                                   DEVMODE_ORIENTATION;
6681         r->orientation          = DMORIENT_PORTRAIT;
6682         r->papersize            = DMPAPER_LETTER;
6683         r->paperlength          = 0;
6684         r->paperwidth           = 0;
6685         r->scale                = 100;
6686         r->copies               = 55;
6687         r->defaultsource        = DMBIN_FORMSOURCE;
6688         r->printquality         = DMRES_HIGH;
6689         r->color                = DMRES_MONOCHROME;
6690         r->duplex               = DMDUP_SIMPLEX;
6691         r->yresolution          = 0;
6692         r->ttoption             = DMTT_SUBDEV;
6693         r->collate              = DMCOLLATE_FALSE;
6694         r->formname             = talloc_strdup(r, "Letter");
6695
6696         return r;
6697 }
6698
6699 static bool test_architecture_buffer(struct torture_context *tctx,
6700                                      void *private_data)
6701 {
6702         struct test_spoolss_context *ctx =
6703                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6704
6705         struct spoolss_OpenPrinterEx r;
6706         struct spoolss_UserLevel1 u1;
6707         struct policy_handle handle;
6708         uint32_t architectures[] = {
6709                 PROCESSOR_ARCHITECTURE_INTEL,
6710                 PROCESSOR_ARCHITECTURE_IA64,
6711                 PROCESSOR_ARCHITECTURE_AMD64
6712         };
6713         uint32_t needed[3];
6714         int i;
6715         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6716         struct dcerpc_binding_handle *b = p->binding_handle;
6717
6718         for (i=0; i < ARRAY_SIZE(architectures); i++) {
6719
6720                 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
6721
6722                 u1.size = 0;
6723                 u1.client = NULL;
6724                 u1.user = NULL;
6725                 u1.build = 0;
6726                 u1.major = 3;
6727                 u1.minor = 0;
6728                 u1.processor = architectures[i];
6729
6730                 r.in.printername        = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6731                 r.in.datatype           = NULL;
6732                 r.in.devmode_ctr.devmode= NULL;
6733                 r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
6734                 r.in.level               = 1;
6735                 r.in.userlevel.level1   = &u1;
6736                 r.out.handle            = &handle;
6737
6738                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
6739                 torture_assert_werr_ok(tctx, r.out.result, "");
6740
6741                 {
6742                         struct spoolss_EnumPrinters e;
6743                         uint32_t count;
6744                         union spoolss_PrinterInfo *info;
6745
6746                         e.in.flags = PRINTER_ENUM_LOCAL;
6747                         e.in.server = NULL;
6748                         e.in.level = 2;
6749                         e.in.buffer = NULL;
6750                         e.in.offered = 0;
6751                         e.out.count = &count;
6752                         e.out.info = &info;
6753                         e.out.needed = &needed[i];
6754
6755                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
6756 #if 0
6757                         torture_comment(tctx, "needed was %d\n", needed[i]);
6758 #endif
6759                 }
6760
6761                 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
6762         }
6763
6764         for (i=1; i < ARRAY_SIZE(architectures); i++) {
6765                 if (needed[i-1] != needed[i]) {
6766                         torture_fail(tctx,
6767                                 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
6768                                                 needed[i-1], architectures[i-1], needed[i], architectures[i]));
6769                 }
6770         }
6771
6772         return true;
6773 }
6774
6775 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
6776                                           void *private_data)
6777 {
6778         struct test_spoolss_context *ctx =
6779                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6780         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6781         struct dcerpc_binding_handle *b = p->binding_handle;
6782
6783         return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
6784 }
6785
6786 static bool test_PrintServer_Forms(struct torture_context *tctx,
6787                                    void *private_data)
6788 {
6789         struct test_spoolss_context *ctx =
6790                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6791         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6792         struct dcerpc_binding_handle *b = p->binding_handle;
6793
6794         return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
6795 }
6796
6797 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
6798                                        void *private_data)
6799 {
6800         struct test_spoolss_context *ctx =
6801                 talloc_get_type_abort(private_data, struct test_spoolss_context);
6802         struct dcerpc_pipe *p = ctx->spoolss_pipe;
6803         struct dcerpc_binding_handle *b = p->binding_handle;
6804
6805         return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
6806 }
6807
6808 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
6809 {
6810         NTSTATUS status;
6811
6812         status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
6813
6814         torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
6815
6816         torture_assert(tctx,
6817                 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
6818                 "failed to open printserver");
6819         torture_assert(tctx,
6820                 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
6821                 "failed to get environment");
6822
6823         return true;
6824 }
6825
6826 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
6827 {
6828         struct test_spoolss_context *t;
6829
6830         *data = t = talloc_zero(tctx, struct test_spoolss_context);
6831
6832         return torture_rpc_spoolss_setup_common(tctx, t);
6833 }
6834
6835 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
6836 {
6837         test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
6838
6839         return true;
6840 }
6841
6842 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
6843 {
6844         struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
6845         bool ret;
6846
6847         ret = torture_rpc_spoolss_teardown_common(tctx, t);
6848         talloc_free(t);
6849
6850         return ret;
6851 }
6852
6853 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
6854 {
6855         struct dcerpc_pipe *p;
6856         struct dcerpc_binding_handle *b;
6857         const char *server_name_slash;
6858         const char *driver_name;
6859         const char *printer_name;
6860         const char *port_name;
6861
6862         torture_assert_ntstatus_ok(tctx,
6863                 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
6864                 "Error connecting to server");
6865
6866         p = t->spoolss_pipe;
6867         b = p->binding_handle;
6868         server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6869
6870         t->driver.info8.version                 = SPOOLSS_DRIVER_VERSION_200X;
6871         t->driver.info8.driver_name             = TORTURE_DRIVER;
6872         t->driver.info8.driver_path             = "pscript5.dll";
6873         t->driver.info8.data_file               = "cups6.ppd";
6874         t->driver.info8.config_file             = "ps5ui.dll";
6875         t->driver.info8.help_file               = "pscript.hlp";
6876         t->driver.info8.default_datatype        = "RAW";
6877         t->driver.info8.dependent_files         = talloc_zero(t, struct spoolss_StringArray);
6878         t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
6879         t->driver.info8.dependent_files->string[0] = "pscript5.dll";
6880         t->driver.info8.dependent_files->string[1] = "cups6.ppd";
6881         t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
6882         t->driver.info8.dependent_files->string[3] = "pscript.hlp";
6883         t->driver.info8.dependent_files->string[4] = "pscript.ntf";
6884         t->driver.info8.dependent_files->string[5] = "cups6.ini";
6885         t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
6886         t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
6887
6888         t->driver.local.driver_directory= "/usr/share/cups/drivers";
6889
6890         t->info2.drivername             = "Microsoft XPS Document Writer";
6891         t->info2.portname               = "LPT1:";
6892
6893         printer_name = t->info2.printername;
6894         port_name = t->info2.portname;
6895
6896         torture_assert(tctx,
6897                 fillup_printserver_info(tctx, p, &t->driver),
6898                 "failed to fillup printserver info");
6899
6900         t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
6901
6902         torture_assert(tctx,
6903                 compose_local_driver_directory(tctx, t->driver.remote.environment,
6904                                                t->driver.local.driver_directory,
6905                                                &t->driver.local.driver_directory),
6906                 "failed to compose local driver directory");
6907
6908         if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername)) {
6909                 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
6910                         t->info2.drivername, t->driver.remote.environment);
6911                 t->have_driver = true;
6912                 goto try_add;
6913         }
6914
6915         torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
6916                 t->info2.drivername, t->driver.remote.environment);
6917         torture_comment(tctx, "trying to upload own driver\n");
6918
6919         if (!directory_exist(t->driver.local.driver_directory)) {
6920                 torture_warning(tctx, "no local driver is available!");
6921                 t->have_driver = false;
6922                 goto try_add;
6923         }
6924
6925         torture_assert(tctx,
6926                 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
6927                 "failed to upload printer driver");
6928
6929         torture_assert(tctx,
6930                 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false),
6931                 "failed to add driver");
6932
6933         t->added_driver = true;
6934         t->have_driver = true;
6935
6936  try_add:
6937         driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
6938
6939         if (t->wellknown) {
6940                 torture_assert(tctx,
6941                         test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
6942                         "failed to add wellknown printer");
6943         } else {
6944                 torture_assert(tctx,
6945                         test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
6946                         "failed to add printer");
6947         }
6948
6949         return true;
6950 }
6951
6952 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
6953 {
6954         struct torture_printer_context *t;
6955
6956         *data = t = talloc_zero(tctx, struct torture_printer_context);
6957
6958         t->ex                   = false;
6959         t->wellknown            = false;
6960         t->info2.printername    = TORTURE_PRINTER;
6961         t->devmode              = NULL;
6962
6963         return torture_rpc_spoolss_printer_setup_common(tctx, t);
6964 }
6965
6966 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
6967 {
6968         struct torture_printer_context *t;
6969
6970         *data = t = talloc_zero(tctx, struct torture_printer_context);
6971
6972         t->ex                   = true;
6973         t->wellknown            = false;
6974         t->info2.printername    = TORTURE_PRINTER_EX;
6975         t->devmode              = NULL;
6976
6977         return torture_rpc_spoolss_printer_setup_common(tctx, t);
6978 }
6979
6980 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
6981 {
6982         struct torture_printer_context *t;
6983
6984         *data = t = talloc_zero(tctx, struct torture_printer_context);
6985
6986         t->ex                   = false;
6987         t->wellknown            = true;
6988         t->info2.printername    = TORTURE_WELLKNOWN_PRINTER;
6989         t->devmode              = NULL;
6990
6991         if (t->wellknown && torture_setting_bool(tctx, "samba3", false)) {
6992                 torture_skip(tctx, "skipping AddPrinter level 1 against samba");
6993         }
6994
6995         return torture_rpc_spoolss_printer_setup_common(tctx, t);
6996 }
6997
6998 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
6999 {
7000         struct torture_printer_context *t;
7001
7002         *data = t = talloc_zero(tctx, struct torture_printer_context);
7003
7004         t->ex                   = true;
7005         t->wellknown            = true;
7006         t->info2.printername    = TORTURE_WELLKNOWN_PRINTER_EX;
7007         t->devmode              = NULL;
7008
7009         if (t->wellknown && torture_setting_bool(tctx, "samba3", false)) {
7010                 torture_skip(tctx, "skipping AddPrinter level 1 against samba");
7011         }
7012
7013         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7014 }
7015
7016 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
7017 {
7018         struct torture_printer_context *t;
7019
7020         *data = t = talloc_zero(tctx, struct torture_printer_context);
7021
7022         t->ex                   = true;
7023         t->wellknown            = false;
7024         t->info2.printername    = TORTURE_PRINTER_EX;
7025         t->devmode              = torture_devicemode(t, TORTURE_PRINTER_EX);
7026
7027         return torture_rpc_spoolss_printer_setup_common(tctx, t);
7028 }
7029
7030 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
7031 {
7032         bool found = false;
7033         struct dcerpc_pipe *p = t->spoolss_pipe;
7034         struct dcerpc_binding_handle *b;
7035         const char *printer_name = t->info2.printername;
7036
7037         if (t->added_driver) {
7038                 torture_assert(tctx,
7039                         remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
7040                         "failed to remove printer driver");
7041         }
7042
7043         if (p) {
7044                 b = p->binding_handle;
7045         }
7046
7047         if (!t->wellknown) {
7048                 torture_assert(tctx,
7049                         test_DeletePrinter(tctx, b, &t->handle),
7050                         "failed to delete printer");
7051
7052                 torture_assert(tctx,
7053                         test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
7054                                                    printer_name, &found),
7055                         "failed to enumerate printers");
7056
7057                 torture_assert(tctx, !found, "deleted printer still there");
7058         }
7059
7060         return true;
7061 }
7062
7063 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
7064 {
7065         struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
7066         bool ret;
7067
7068         ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
7069         talloc_free(t);
7070
7071         return ret;
7072 }
7073
7074 static bool test_print_test(struct torture_context *tctx,
7075                             void *private_data)
7076 {
7077         struct torture_printer_context *t =
7078                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7079         struct dcerpc_pipe *p = t->spoolss_pipe;
7080         struct dcerpc_binding_handle *b = p->binding_handle;
7081
7082         torture_assert(tctx,
7083                 test_PausePrinter(tctx, b, &t->handle),
7084                 "failed to pause printer");
7085
7086         torture_assert(tctx,
7087                 test_DoPrintTest(tctx, b, &t->handle),
7088                 "failed to do print test");
7089
7090         torture_assert(tctx,
7091                 test_ResumePrinter(tctx, b, &t->handle),
7092                 "failed to resume printer");
7093
7094         return true;
7095 }
7096
7097 static bool test_print_test_extended(struct torture_context *tctx,
7098                                      void *private_data)
7099 {
7100         struct torture_printer_context *t =
7101                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7102         struct dcerpc_pipe *p = t->spoolss_pipe;
7103         struct dcerpc_binding_handle *b = p->binding_handle;
7104         bool ret = true;
7105
7106         torture_assert(tctx,
7107                 test_PausePrinter(tctx, b, &t->handle),
7108                 "failed to pause printer");
7109
7110         ret = test_DoPrintTest_extended(tctx, b, &t->handle);
7111         if (ret == false) {
7112                 torture_comment(tctx, "WARNING! failed to do extended print test\n");
7113                 if (torture_setting_bool(tctx, "samba3", false)) {
7114                         torture_comment(tctx, "non-critical for samba3\n");
7115                         ret = true;
7116                         tctx->last_result = TORTURE_SKIP;
7117                 }
7118         }
7119
7120         torture_assert(tctx,
7121                 test_ResumePrinter(tctx, b, &t->handle),
7122                 "failed to resume printer");
7123
7124         return ret;
7125 }
7126
7127 static bool test_printer_sd(struct torture_context *tctx,
7128                             void *private_data)
7129 {
7130         struct torture_printer_context *t =
7131                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7132         struct dcerpc_pipe *p = t->spoolss_pipe;
7133         struct dcerpc_binding_handle *b = p->binding_handle;
7134
7135         torture_assert(tctx,
7136                 test_PrinterInfo_SD(tctx, b, &t->handle),
7137                 "failed to test security descriptors");
7138
7139         return true;
7140 }
7141
7142 static bool test_printer_dm(struct torture_context *tctx,
7143                             void *private_data)
7144 {
7145         struct torture_printer_context *t =
7146                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7147         struct dcerpc_pipe *p = t->spoolss_pipe;
7148
7149         torture_assert(tctx,
7150                 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
7151                 "failed to test devicemodes");
7152
7153         return true;
7154 }
7155
7156 static bool test_printer_info_winreg(struct torture_context *tctx,
7157                                      void *private_data)
7158 {
7159         struct torture_printer_context *t =
7160                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7161         struct dcerpc_pipe *p = t->spoolss_pipe;
7162
7163         torture_assert(tctx,
7164                 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
7165                 "failed to test printer info winreg");
7166
7167         return true;
7168 }
7169
7170 static bool test_printer_change_id(struct torture_context *tctx,
7171                                    void *private_data)
7172 {
7173         struct torture_printer_context *t =
7174                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7175         struct dcerpc_pipe *p = t->spoolss_pipe;
7176
7177         torture_assert(tctx,
7178                 test_ChangeID(tctx, p, &t->handle),
7179                 "failed to test change id");
7180
7181         return true;
7182 }
7183
7184 static bool test_printer_keys(struct torture_context *tctx,
7185                               void *private_data)
7186 {
7187         struct torture_printer_context *t =
7188                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7189         struct dcerpc_pipe *p = t->spoolss_pipe;
7190         struct dcerpc_binding_handle *b = p->binding_handle;
7191
7192         torture_assert(tctx,
7193                 test_printer_all_keys(tctx, b, &t->handle),
7194                 "failed to test printer keys");
7195
7196         return true;
7197 }
7198
7199 static bool test_printer_data_consistency(struct torture_context *tctx,
7200                                           void *private_data)
7201 {
7202         struct torture_printer_context *t =
7203                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7204         struct dcerpc_pipe *p = t->spoolss_pipe;
7205
7206         torture_assert(tctx,
7207                 test_EnumPrinterData_consistency(tctx, p, &t->handle),
7208                 "failed to test printer data consistency");
7209
7210         return true;
7211 }
7212
7213 static bool test_printer_data_keys(struct torture_context *tctx,
7214                                    void *private_data)
7215 {
7216         struct torture_printer_context *t =
7217                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7218         struct dcerpc_pipe *p = t->spoolss_pipe;
7219
7220         torture_assert(tctx,
7221                 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
7222                 "failed to test printer data keys");
7223
7224         return true;
7225 }
7226
7227 static bool test_printer_data_set(struct torture_context *tctx,
7228                                   void *private_data)
7229 {
7230         struct torture_printer_context *t =
7231                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7232         struct dcerpc_pipe *p = t->spoolss_pipe;
7233
7234         torture_assert(tctx,
7235                 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
7236                 "failed to test printer data set");
7237
7238         return true;
7239 }
7240
7241 static bool test_printer_data_winreg(struct torture_context *tctx,
7242                                      void *private_data)
7243 {
7244         struct torture_printer_context *t =
7245                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7246         struct dcerpc_pipe *p = t->spoolss_pipe;
7247
7248         torture_assert(tctx,
7249                 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
7250                 "failed to test printer data winreg");
7251
7252         return true;
7253 }
7254
7255 static bool test_printer_data_dsspooler(struct torture_context *tctx,
7256                                         void *private_data)
7257 {
7258         struct torture_printer_context *t =
7259                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7260         struct dcerpc_pipe *p = t->spoolss_pipe;
7261
7262         torture_assert(tctx,
7263                 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
7264                 "failed to test printer data winreg dsspooler");
7265
7266         return true;
7267 }
7268
7269 static bool test_driver_info_winreg(struct torture_context *tctx,
7270                                     void *private_data)
7271 {
7272         struct torture_printer_context *t =
7273                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7274         struct dcerpc_pipe *p = t->spoolss_pipe;
7275         const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7276
7277         if (!t->have_driver) {
7278                 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
7279         }
7280
7281         torture_assert(tctx,
7282                 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment),
7283                 "failed to test driver info winreg");
7284
7285         return true;
7286 }
7287
7288 void torture_tcase_printer(struct torture_tcase *tcase)
7289 {
7290         torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
7291         torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
7292         torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
7293         torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
7294         torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
7295         torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
7296         torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
7297         torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
7298         torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
7299         torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
7300         torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
7301         torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
7302         torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
7303         torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
7304         torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
7305         torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
7306 }
7307
7308 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
7309 {
7310         struct torture_suite *suite = torture_suite_create(mem_ctx, "PRINTER");
7311         struct torture_tcase *tcase;
7312
7313         tcase = torture_suite_add_tcase(suite, "addprinter");
7314
7315         torture_tcase_set_fixture(tcase,
7316                                   torture_rpc_spoolss_printer_setup,
7317                                   torture_rpc_spoolss_printer_teardown);
7318
7319         torture_tcase_printer(tcase);
7320
7321         tcase = torture_suite_add_tcase(suite, "addprinterex");
7322
7323         torture_tcase_set_fixture(tcase,
7324                                   torture_rpc_spoolss_printerex_setup,
7325                                   torture_rpc_spoolss_printer_teardown);
7326
7327         torture_tcase_printer(tcase);
7328
7329         tcase = torture_suite_add_tcase(suite, "addprinterwkn");
7330
7331         torture_tcase_set_fixture(tcase,
7332                                   torture_rpc_spoolss_printerwkn_setup,
7333                                   torture_rpc_spoolss_printer_teardown);
7334
7335         tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
7336
7337         torture_tcase_set_fixture(tcase,
7338                                   torture_rpc_spoolss_printerexwkn_setup,
7339                                   torture_rpc_spoolss_printer_teardown);
7340
7341 #if 0
7342         /* test is not correct */
7343         tcase = torture_suite_add_tcase(suite, "addprinterdm");
7344
7345         torture_tcase_set_fixture(tcase,
7346                                   torture_rpc_spoolss_printerdm_setup,
7347                                   torture_rpc_spoolss_printer_teardown);
7348
7349         torture_tcase_printer(tcase);
7350 #endif
7351         return suite;
7352 }
7353
7354 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
7355 {
7356         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS");
7357         struct torture_tcase *tcase = torture_suite_add_tcase(suite, "PRINTSERVER");
7358
7359         torture_tcase_set_fixture(tcase,
7360                                   torture_rpc_spoolss_setup,
7361                                   torture_rpc_spoolss_teardown);
7362
7363         torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
7364         torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
7365         torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
7366         torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
7367         torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
7368         torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
7369         torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
7370         torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
7371         torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
7372         torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
7373         torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
7374         torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
7375         torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
7376         torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
7377         torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
7378         torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
7379         torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
7380         torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
7381         torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
7382
7383         torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
7384
7385         return suite;
7386 }
7387
7388 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
7389                                                   struct dcerpc_binding_handle *b,
7390                                                   const char *server,
7391                                                   const char *environment,
7392                                                   const char **dir_p)
7393 {
7394         struct spoolss_GetPrinterDriverDirectory r;
7395         uint32_t needed;
7396
7397         r.in.server             = server;
7398         r.in.environment        = environment;
7399         r.in.level              = 1;
7400         r.in.buffer             = NULL;
7401         r.in.offered            = 0;
7402         r.out.needed            = &needed;
7403
7404         torture_assert_ntstatus_ok(tctx,
7405                 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
7406                 "failed to query driver directory");
7407
7408         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
7409                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7410                 r.in.buffer = &blob;
7411                 r.in.offered = needed;
7412
7413                 torture_assert_ntstatus_ok(tctx,
7414                         dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
7415                         "failed to query driver directory");
7416         }
7417
7418         torture_assert_werr_ok(tctx, r.out.result,
7419                 "failed to query driver directory");
7420
7421         if (dir_p) {
7422                 *dir_p = r.out.info->info1.directory_name;
7423         }
7424
7425         return true;
7426 }
7427
7428 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
7429 {
7430         if (info_ctr == NULL) {
7431                 return NULL;
7432         }
7433
7434         switch (info_ctr->level) {
7435         case 1:
7436                 return info_ctr->info.info1->driver_name;
7437         case 2:
7438                 return info_ctr->info.info2->driver_name;
7439         case 3:
7440                 return info_ctr->info.info3->driver_name;
7441         case 4:
7442                 return info_ctr->info.info4->driver_name;
7443         case 6:
7444                 return info_ctr->info.info6->driver_name;
7445         case 8:
7446                 return info_ctr->info.info8->driver_name;
7447         default:
7448                 return NULL;
7449         }
7450 }
7451
7452 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
7453 {
7454         if (info_ctr == NULL) {
7455                 return NULL;
7456         }
7457
7458         switch (info_ctr->level) {
7459         case 2:
7460                 return info_ctr->info.info2->architecture;
7461         case 3:
7462                 return info_ctr->info.info3->architecture;
7463         case 4:
7464                 return info_ctr->info.info4->architecture;
7465         case 6:
7466                 return info_ctr->info.info6->architecture;
7467         case 8:
7468                 return info_ctr->info.info8->architecture;
7469         default:
7470                 return NULL;
7471         }
7472 }
7473
7474
7475 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
7476                                       struct dcerpc_binding_handle *b,
7477                                       const char *servername,
7478                                       struct spoolss_AddDriverInfoCtr *info_ctr,
7479                                       WERROR expected_result)
7480 {
7481         struct spoolss_AddPrinterDriver r;
7482         const char *drivername = get_driver_from_info(info_ctr);
7483         const char *environment = get_environment_from_info(info_ctr);
7484
7485         r.in.servername = servername;
7486         r.in.info_ctr = info_ctr;
7487
7488         torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
7489                 drivername, info_ctr->level, environment);
7490
7491         torture_assert_ntstatus_ok(tctx,
7492                 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
7493                 "spoolss_AddPrinterDriver failed");
7494         torture_assert_werr_equal(tctx, r.out.result, expected_result,
7495                 "spoolss_AddPrinterDriver failed with unexpected result");
7496
7497         return true;
7498
7499 }
7500
7501 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
7502                                         struct dcerpc_binding_handle *b,
7503                                         const char *servername,
7504                                         struct spoolss_AddDriverInfoCtr *info_ctr,
7505                                         uint32_t flags,
7506                                         WERROR expected_result)
7507 {
7508         struct spoolss_AddPrinterDriverEx r;
7509         const char *drivername = get_driver_from_info(info_ctr);
7510         const char *environment = get_environment_from_info(info_ctr);
7511
7512         r.in.servername = servername;
7513         r.in.info_ctr = info_ctr;
7514         r.in.flags = flags;
7515
7516         torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
7517                 drivername, info_ctr->level, environment);
7518
7519         torture_assert_ntstatus_ok(tctx,
7520                 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
7521                 "AddPrinterDriverEx failed");
7522         torture_assert_werr_equal(tctx, r.out.result, expected_result,
7523                 "AddPrinterDriverEx failed with unexpected result");
7524
7525         return true;
7526 }
7527
7528 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
7529                                                struct dcerpc_binding_handle *b,
7530                                                const char *server_name,
7531                                                struct spoolss_AddDriverInfo8 *r,
7532                                                uint32_t flags,
7533                                                bool ex)
7534 {
7535         struct spoolss_AddDriverInfoCtr info_ctr;
7536         struct spoolss_AddDriverInfo1 info1;
7537
7538         ZERO_STRUCT(info1);
7539
7540         info_ctr.level = 1;
7541         info_ctr.info.info1 = &info1;
7542
7543         if (ex) {
7544                 torture_assert(tctx,
7545                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
7546                         "failed to test AddPrinterDriverEx level 1");
7547         } else {
7548                 torture_assert(tctx,
7549                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7550                         "failed to test AddPrinterDriver level 1");
7551         }
7552
7553         info1.driver_name = r->driver_name;
7554
7555         if (ex) {
7556                 torture_assert(tctx,
7557                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
7558                         "failed to test AddPrinterDriverEx level 1");
7559         } else {
7560                 torture_assert(tctx,
7561                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7562                         "failed to test AddPrinterDriver level 1");
7563         }
7564
7565         return true;
7566 }
7567
7568 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
7569                                                struct dcerpc_binding_handle *b,
7570                                                const char *server_name,
7571                                                struct spoolss_AddDriverInfo8 *r,
7572                                                uint32_t flags,
7573                                                bool ex)
7574 {
7575         struct spoolss_AddDriverInfoCtr info_ctr;
7576         struct spoolss_AddDriverInfo2 info2;
7577
7578         ZERO_STRUCT(info2);
7579
7580         info_ctr.level = 2;
7581         info_ctr.info.info2 = &info2;
7582
7583         if (ex) {
7584                 torture_assert(tctx,
7585                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7586                         "failed to test AddPrinterDriverEx level 2");
7587         } else {
7588                 torture_assert(tctx,
7589                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7590                         "failed to test AddPrinterDriver level 2");
7591         }
7592
7593         info2.driver_name = r->driver_name;
7594
7595         if (ex) {
7596                 torture_assert(tctx,
7597                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7598                         "failed to test AddPrinterDriverEx level 2");
7599         } else {
7600                 torture_assert(tctx,
7601                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7602                         "failed to test AddPrinterDriver level 2");
7603         }
7604
7605         info2.version = r->version;
7606
7607         if (ex) {
7608                 torture_assert(tctx,
7609                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7610                         "failed to test AddPrinterDriverEx level 2");
7611         } else {
7612                 torture_assert(tctx,
7613                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7614                         "failed to test AddPrinterDriver level 2");
7615         }
7616
7617         info2.architecture = r->architecture;
7618
7619         if (ex) {
7620                 torture_assert(tctx,
7621                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7622                         "failed to test AddPrinterDriverEx level 2");
7623         } else {
7624                 torture_assert(tctx,
7625                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7626                         "failed to test AddPrinterDriver level 2");
7627         }
7628
7629         info2.driver_path = r->driver_path;
7630
7631         if (ex) {
7632                 torture_assert(tctx,
7633                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7634                         "failed to test AddPrinterDriverEx level 2");
7635         } else {
7636                 torture_assert(tctx,
7637                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7638                         "failed to test AddPrinterDriver level 2");
7639         }
7640
7641         info2.data_file = r->data_file;
7642
7643         if (ex) {
7644                 torture_assert(tctx,
7645                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
7646                         "failed to test AddPrinterDriverEx level 2");
7647         } else {
7648                 torture_assert(tctx,
7649                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
7650                         "failed to test AddPrinterDriver level 2");
7651         }
7652
7653         info2.config_file = r->config_file;
7654
7655         if (ex) {
7656                 torture_assert(tctx,
7657                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
7658                         "failed to test AddPrinterDriverEx");
7659         }
7660
7661         if (ex) {
7662                 torture_assert(tctx,
7663                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7664                         "failed to test AddPrinterDriverEx level 2");
7665         } else {
7666                 torture_assert(tctx,
7667                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7668                         "failed to test AddPrinterDriver level 2");
7669         }
7670
7671         torture_assert(tctx,
7672                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name),
7673                 "failed to find added printer driver");
7674
7675         return true;
7676 }
7677
7678 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
7679                                                struct dcerpc_binding_handle *b,
7680                                                const char *server_name,
7681                                                struct spoolss_AddDriverInfo8 *r,
7682                                                uint32_t flags,
7683                                                bool ex)
7684 {
7685         struct spoolss_AddDriverInfoCtr info_ctr;
7686         struct spoolss_AddDriverInfo3 info3;
7687
7688         info3.driver_name       = r->driver_name;
7689         info3.version           = r->version;
7690         info3.architecture      = r->architecture;
7691         info3.driver_path       = r->driver_path;
7692         info3.data_file         = r->data_file;
7693         info3.config_file       = r->config_file;
7694         info3.help_file         = r->help_file;
7695         info3.monitor_name      = r->monitor_name;
7696         info3.default_datatype  = r->default_datatype;
7697         info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7698         info3.dependent_files   = r->dependent_files;
7699
7700         info_ctr.level = 3;
7701         info_ctr.info.info3 = &info3;
7702
7703         if (ex) {
7704                 torture_assert(tctx,
7705                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7706                         "failed to test AddPrinterDriverEx level 3");
7707         } else {
7708                 torture_assert(tctx,
7709                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7710                         "failed to test AddPrinterDriver level 3");
7711         }
7712
7713         torture_assert(tctx,
7714                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name),
7715                 "failed to find added printer driver");
7716
7717         return true;
7718 }
7719
7720 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
7721                                                struct dcerpc_binding_handle *b,
7722                                                const char *server_name,
7723                                                struct spoolss_AddDriverInfo8 *r,
7724                                                uint32_t flags,
7725                                                bool ex)
7726 {
7727         struct spoolss_AddDriverInfoCtr info_ctr;
7728         struct spoolss_AddDriverInfo4 info4;
7729
7730         info4.version           = r->version;
7731         info4.driver_name       = r->driver_name;
7732         info4.architecture      = r->architecture;
7733         info4.driver_path       = r->driver_path;
7734         info4.data_file         = r->data_file;
7735         info4.config_file       = r->config_file;
7736         info4.help_file         = r->help_file;
7737         info4.monitor_name      = r->monitor_name;
7738         info4.default_datatype  = r->default_datatype;
7739         info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7740         info4.dependent_files   = r->dependent_files;
7741         info4._ndr_size_previous_names = r->_ndr_size_previous_names;
7742         info4.previous_names = r->previous_names;
7743
7744         info_ctr.level = 4;
7745         info_ctr.info.info4 = &info4;
7746
7747         if (ex) {
7748                 torture_assert(tctx,
7749                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7750                         "failed to test AddPrinterDriverEx level 4");
7751         } else {
7752                 torture_assert(tctx,
7753                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7754                         "failed to test AddPrinterDriver level 4");
7755         }
7756
7757         torture_assert(tctx,
7758                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name),
7759                 "failed to find added printer driver");
7760
7761         return true;
7762 }
7763
7764 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
7765                                                struct dcerpc_binding_handle *b,
7766                                                const char *server_name,
7767                                                struct spoolss_AddDriverInfo8 *r,
7768                                                uint32_t flags,
7769                                                bool ex)
7770 {
7771         struct spoolss_AddDriverInfoCtr info_ctr;
7772         struct spoolss_AddDriverInfo6 info6;
7773
7774         info6.version           = r->version;
7775         info6.driver_name       = r->driver_name;
7776         info6.architecture      = r->architecture;
7777         info6.driver_path       = r->driver_path;
7778         info6.data_file         = r->data_file;
7779         info6.config_file       = r->config_file;
7780         info6.help_file         = r->help_file;
7781         info6.monitor_name      = r->monitor_name;
7782         info6.default_datatype  = r->default_datatype;
7783         info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7784         info6.dependent_files   = r->dependent_files;
7785         info6._ndr_size_previous_names = r->_ndr_size_previous_names;
7786         info6.previous_names    = r->previous_names;
7787         info6.driver_date       = r->driver_date;
7788         info6.driver_version    = r->driver_version;
7789         info6.manufacturer_name = r->manufacturer_name;
7790         info6.manufacturer_url  = r->manufacturer_url;
7791         info6.hardware_id       = r->hardware_id;
7792         info6.provider          = r->provider;
7793
7794         info_ctr.level = 6;
7795         info_ctr.info.info6 = &info6;
7796
7797         if (ex) {
7798                 torture_assert(tctx,
7799                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7800                         "failed to test AddPrinterDriverEx level 6");
7801         } else {
7802                 torture_assert(tctx,
7803                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7804                         "failed to test AddPrinterDriver level 6");
7805         }
7806
7807         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
7808
7809         if (!ex) {
7810                 return true;
7811         }
7812
7813         torture_assert(tctx,
7814                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name),
7815                 "failed to find added printer driver");
7816
7817         return true;
7818 }
7819
7820 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
7821                                                struct dcerpc_binding_handle *b,
7822                                                const char *server_name,
7823                                                struct spoolss_AddDriverInfo8 *r,
7824                                                uint32_t flags,
7825                                                bool ex)
7826 {
7827         struct spoolss_AddDriverInfoCtr info_ctr;
7828
7829         info_ctr.level = 8;
7830         info_ctr.info.info8 = r;
7831
7832         if (ex) {
7833                 torture_assert(tctx,
7834                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7835                         "failed to test AddPrinterDriverEx level 8");
7836         } else {
7837                 torture_assert(tctx,
7838                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7839                         "failed to test AddPrinterDriver level 8");
7840         }
7841
7842         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
7843
7844         if (!ex) {
7845                 return true;
7846         }
7847
7848         torture_assert(tctx,
7849                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name),
7850                 "failed to find added printer driver");
7851
7852         return true;
7853 }
7854
7855 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
7856                                          struct dcerpc_binding_handle *b,
7857                                          const char *server,
7858                                          const char *driver,
7859                                          const char *environment,
7860                                          WERROR expected_result)
7861 {
7862         struct spoolss_DeletePrinterDriver r;
7863
7864         r.in.server = server;
7865         r.in.architecture = environment;
7866         r.in.driver = driver;
7867
7868         torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
7869
7870         torture_assert_ntstatus_ok(tctx,
7871                 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
7872                 "DeletePrinterDriver failed");
7873         torture_assert_werr_equal(tctx, r.out.result, expected_result,
7874                 "DeletePrinterDriver failed with unexpected result");
7875
7876         return true;
7877 }
7878
7879 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
7880                                            struct dcerpc_binding_handle *b,
7881                                            const char *server,
7882                                            const char *driver,
7883                                            const char *environment,
7884                                            uint32_t delete_flags,
7885                                            uint32_t version,
7886                                            WERROR expected_result)
7887 {
7888         struct spoolss_DeletePrinterDriverEx r;
7889
7890         r.in.server = server;
7891         r.in.architecture = environment;
7892         r.in.driver = driver;
7893         r.in.delete_flags = delete_flags;
7894         r.in.version = version;
7895
7896         torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
7897
7898         torture_assert_ntstatus_ok(tctx,
7899                 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
7900                 "DeletePrinterDriverEx failed");
7901         torture_assert_werr_equal(tctx, r.out.result, expected_result,
7902                 "DeletePrinterDriverEx failed with unexpected result");
7903
7904         return true;
7905 }
7906
7907 static bool test_DeletePrinterDriver(struct torture_context *tctx,
7908                                      struct dcerpc_binding_handle *b,
7909                                      const char *server_name,
7910                                      const char *driver,
7911                                      const char *environment)
7912 {
7913         torture_assert(tctx,
7914                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
7915                 "failed to delete driver");
7916
7917         torture_assert(tctx,
7918                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
7919                 "failed to delete driver");
7920
7921         if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
7922                 torture_fail(tctx, "deleted driver still enumerated");
7923         }
7924
7925         torture_assert(tctx,
7926                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
7927                 "2nd delete failed");
7928
7929         return true;
7930 }
7931
7932 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
7933                                        struct dcerpc_binding_handle *b,
7934                                        const char *server_name,
7935                                        const char *driver,
7936                                        const char *environment,
7937                                        uint32_t delete_flags,
7938                                        uint32_t version)
7939 {
7940         torture_assert(tctx,
7941                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
7942                 "failed to delete driver");
7943
7944         torture_assert(tctx,
7945                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
7946                 "failed to delete driver");
7947
7948         if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
7949                 torture_fail(tctx, "deleted driver still enumerated");
7950         }
7951
7952         torture_assert(tctx,
7953                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
7954                 "2nd delete failed");
7955
7956         return true;
7957 }
7958
7959 static bool test_PrinterDriver_args(struct torture_context *tctx,
7960                                     struct dcerpc_binding_handle *b,
7961                                     const char *server_name,
7962                                     uint32_t level,
7963                                     struct spoolss_AddDriverInfo8 *r,
7964                                     uint32_t add_flags,
7965                                     uint32_t delete_flags,
7966                                     uint32_t delete_version,
7967                                     bool ex)
7968 {
7969         bool ret = true;
7970
7971         switch (level) {
7972         case 1:
7973                 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex);
7974                 break;
7975         case 2:
7976                 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex);
7977                 break;
7978         case 3:
7979                 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex);
7980                 break;
7981         case 4:
7982                 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex);
7983                 break;
7984         case 6:
7985                 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex);
7986                 break;
7987         case 8:
7988                 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex);
7989                 break;
7990         default:
7991                 return false;
7992         }
7993
7994         if (ret == false) {
7995                 return ret;
7996         }
7997
7998         if (level == 1) {
7999                 return ret;
8000         }
8001
8002         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8003
8004         if (!ex && (level == 6 || level == 8)) {
8005                 return ret;
8006         }
8007
8008         if (ex) {
8009                 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
8010         } else {
8011                 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
8012         }
8013 }
8014
8015 static bool fillup_printserver_info(struct torture_context *tctx,
8016                                     struct dcerpc_pipe *p,
8017                                     struct torture_driver_context *d)
8018 {
8019         struct policy_handle server_handle;
8020         struct dcerpc_binding_handle *b = p->binding_handle;
8021         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8022
8023         torture_assert(tctx,
8024                 test_OpenPrinter_server(tctx, p, &server_handle),
8025                 "failed to open printserver");
8026         torture_assert(tctx,
8027                 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
8028                 "failed to get environment");
8029         torture_assert(tctx,
8030                 test_ClosePrinter(tctx, b, &server_handle),
8031                 "failed to close printserver");
8032
8033         torture_assert(tctx,
8034                 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
8035                         d->local.environment ? d->local.environment : d->remote.environment,
8036                         &d->remote.driver_directory),
8037                 "failed to get driver directory");
8038
8039         return true;
8040 }
8041
8042 static const char *driver_directory_dir(const char *driver_directory)
8043 {
8044         char *p;
8045
8046         p = strrchr(driver_directory, '\\');
8047         if (p) {
8048                 return p+1;
8049         }
8050
8051         return NULL;
8052 }
8053
8054 static const char *driver_directory_share(struct torture_context *tctx,
8055                                           const char *driver_directory)
8056 {
8057         const char *p;
8058         char *tok;
8059
8060         if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
8061                 driver_directory += 2;
8062         }
8063
8064         p = talloc_strdup(tctx, driver_directory);
8065
8066         torture_assert(tctx,
8067                 next_token_talloc(tctx, &p, &tok, "\\"),
8068                 "cannot explode uri");
8069         torture_assert(tctx,
8070                 next_token_talloc(tctx, &p, &tok, "\\"),
8071                 "cannot explode uri");
8072
8073         return tok;
8074 }
8075
8076 static bool upload_printer_driver_file(struct torture_context *tctx,
8077                                        struct smbcli_state *cli,
8078                                        struct torture_driver_context *d,
8079                                        const char *file_name)
8080 {
8081         XFILE *f;
8082         int fnum;
8083         uint8_t *buf;
8084         int maxwrite = 64512;
8085         off_t nread = 0;
8086         size_t start = 0;
8087         const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
8088         const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
8089         const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8090
8091         if (!file_name) {
8092                 return true;
8093         }
8094
8095         torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
8096
8097         fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
8098         if (fnum == -1) {
8099                 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
8100         }
8101
8102         f = x_fopen(local_name, O_RDONLY, 0);
8103         if (f == NULL) {
8104                 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
8105         }
8106
8107         buf = talloc_array(tctx, uint8_t, maxwrite);
8108         if (!buf) {
8109                 return false;
8110         }
8111
8112         while (!x_feof(f)) {
8113                 int n = maxwrite;
8114                 int ret;
8115
8116                 if ((n = x_fread(buf, 1, n, f)) < 1) {
8117                         if((n == 0) && x_feof(f))
8118                                 break; /* Empty local file. */
8119
8120                         torture_warning(tctx,
8121                                 "failed to read file: %s\n", strerror(errno));
8122                         break;
8123                 }
8124
8125                 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
8126
8127                 if (n != ret) {
8128                         torture_warning(tctx,
8129                                 "failed to write file: %s\n", smbcli_errstr(cli->tree));
8130                         break;
8131                 }
8132
8133                 nread += n;
8134         }
8135
8136         x_fclose(f);
8137
8138         torture_assert_ntstatus_ok(tctx,
8139                 smbcli_close(cli->tree, fnum),
8140                 "failed to close file");
8141
8142         return true;
8143 }
8144
8145 static bool connect_printer_driver_share(struct torture_context *tctx,
8146                                          const char *server_name,
8147                                          const char *share_name,
8148                                          struct smbcli_state **cli)
8149 {
8150         struct smbcli_options smb_options;
8151         struct smbcli_session_options smb_session_options;
8152
8153         torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
8154                 share_name, server_name);
8155
8156         lp_smbcli_options(tctx->lp_ctx, &smb_options);
8157         lp_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
8158
8159         torture_assert_ntstatus_ok(tctx,
8160                 smbcli_full_connection(tctx, cli, server_name,
8161                                         lp_smb_ports(tctx->lp_ctx),
8162                                         share_name, NULL,
8163                                         lp_socket_options(tctx->lp_ctx),
8164                                         cmdline_credentials,
8165                                         lp_resolve_context(tctx->lp_ctx),
8166                                         tctx->ev,
8167                                         &smb_options,
8168                                         &smb_session_options,
8169                                         lp_gensec_settings(tctx, tctx->lp_ctx)),
8170                 "failed to open driver share");
8171
8172         return true;
8173 }
8174
8175 static bool upload_printer_driver(struct torture_context *tctx,
8176                                   const char *server_name,
8177                                   struct torture_driver_context *d)
8178 {
8179         struct smbcli_state *cli;
8180         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8181         int i;
8182
8183         torture_assert(tctx,
8184                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8185                 "failed to connect to driver share");
8186
8187         torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
8188                 server_name, share_name);
8189
8190         torture_assert(tctx,
8191                 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8192                 "failed to upload driver_path");
8193         torture_assert(tctx,
8194                 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
8195                 "failed to upload data_file");
8196         torture_assert(tctx,
8197                 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
8198                 "failed to upload config_file");
8199         torture_assert(tctx,
8200                 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
8201                 "failed to upload help_file");
8202         if (d->info8.dependent_files) {
8203                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8204                         torture_assert(tctx,
8205                                 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8206                                 "failed to upload dependent_files");
8207                 }
8208         }
8209
8210         talloc_free(cli);
8211
8212         return true;
8213 }
8214
8215 static bool remove_printer_driver_file(struct torture_context *tctx,
8216                                        struct smbcli_state *cli,
8217                                        struct torture_driver_context *d,
8218                                        const char *file_name)
8219 {
8220         const char *remote_name;
8221         const char *remote_dir =  driver_directory_dir(d->remote.driver_directory);
8222
8223         if (!file_name) {
8224                 return true;
8225         }
8226
8227         remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8228
8229         torture_comment(tctx, "Removing %s\n", remote_name);
8230
8231         torture_assert_ntstatus_ok(tctx,
8232                 smbcli_unlink(cli->tree, remote_name),
8233                 "failed to unlink");
8234
8235         return true;
8236 }
8237
8238 static bool remove_printer_driver(struct torture_context *tctx,
8239                                   const char *server_name,
8240                                   struct torture_driver_context *d)
8241 {
8242         struct smbcli_state *cli;
8243         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8244         int i;
8245
8246         torture_assert(tctx,
8247                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8248                 "failed to connect to driver share");
8249
8250         torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
8251                 server_name, share_name);
8252
8253         torture_assert(tctx,
8254                 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8255                 "failed to remove driver_path");
8256         torture_assert(tctx,
8257                 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
8258                 "failed to remove data_file");
8259         torture_assert(tctx,
8260                 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
8261                 "failed to remove config_file");
8262         torture_assert(tctx,
8263                 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
8264                 "failed to remove help_file");
8265         if (d->info8.dependent_files) {
8266                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8267                         if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
8268                             strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
8269                             strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
8270                             strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
8271                                 continue;
8272                         }
8273                         torture_assert(tctx,
8274                                 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8275                                 "failed to remove dependent_files");
8276                 }
8277         }
8278
8279         talloc_free(cli);
8280
8281         return true;
8282
8283 }
8284
8285 static bool test_add_driver_arg(struct torture_context *tctx,
8286                                 struct dcerpc_pipe *p,
8287                                 struct torture_driver_context *d)
8288 {
8289         bool ret = true;
8290         struct dcerpc_binding_handle *b = p->binding_handle;
8291         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8292         uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
8293         int i;
8294         struct spoolss_AddDriverInfo8 info8;
8295         uint32_t add_flags = APD_COPY_NEW_FILES;
8296         uint32_t delete_flags = 0;
8297
8298         ZERO_STRUCT(info8);
8299
8300         torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
8301                 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
8302
8303         torture_assert(tctx,
8304                 fillup_printserver_info(tctx, p, d),
8305                 "failed to fillup printserver info");
8306
8307         if (!directory_exist(d->local.driver_directory)) {
8308                 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
8309         }
8310
8311         torture_assert(tctx,
8312                 upload_printer_driver(tctx, dcerpc_server_name(p), d),
8313                 "failed to upload printer driver");
8314
8315         info8.version           = d->info8.version;
8316         info8.driver_name       = d->info8.driver_name;
8317         info8.architecture      = d->local.environment;
8318         info8.driver_path       = d->info8.driver_path;
8319         info8.data_file         = d->info8.data_file;
8320         info8.config_file       = d->info8.config_file;
8321
8322         for (i=0; i < ARRAY_SIZE(levels); i++) {
8323
8324                 if (torture_setting_bool(tctx, "samba3", false)) {
8325                         switch (levels[i]) {
8326                         case 2:
8327                         case 4:
8328                         case 8:
8329                                 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
8330                                 continue;
8331                         default:
8332                                 break;
8333                         }
8334                 }
8335
8336                 torture_comment(tctx,
8337                         "Testing PrinterDriver%s '%s' add & delete level %d\n",
8338                                 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
8339
8340                 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
8341         }
8342
8343         info8.driver_path       = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
8344         info8.data_file         = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
8345         info8.config_file       = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
8346
8347         for (i=0; i < ARRAY_SIZE(levels); i++) {
8348
8349                 if (torture_setting_bool(tctx, "samba3", false)) {
8350                         switch (levels[i]) {
8351                         case 2:
8352                         case 4:
8353                         case 8:
8354                                 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
8355                                 continue;
8356                         default:
8357                                 break;
8358                         }
8359                 }
8360
8361
8362                 torture_comment(tctx,
8363                         "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
8364                                 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
8365
8366                 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
8367         }
8368
8369         torture_assert(tctx,
8370                 remove_printer_driver(tctx, dcerpc_server_name(p), d),
8371                 "failed to remove printer driver");
8372
8373         torture_comment(tctx, "\n");
8374
8375         return ret;
8376 }
8377
8378 static bool test_add_driver_ex_64(struct torture_context *tctx,
8379                                   struct dcerpc_pipe *p,
8380                                   void *private_data)
8381 {
8382         struct torture_driver_context *d =
8383                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8384
8385         d->local.environment            = talloc_strdup(d, "Windows x64");
8386         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/x64");
8387         d->info8.driver_name            = TORTURE_DRIVER_EX;
8388         d->ex                           = true;
8389
8390         return test_add_driver_arg(tctx, p, d);
8391 }
8392
8393 static bool test_add_driver_ex_32(struct torture_context *tctx,
8394                                   struct dcerpc_pipe *p,
8395                                   void *private_data)
8396 {
8397         struct torture_driver_context *d =
8398                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8399
8400         d->local.environment            = talloc_strdup(d, "Windows NT x86");
8401         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
8402         d->info8.driver_name            = TORTURE_DRIVER_EX;
8403         d->ex                           = true;
8404
8405         return test_add_driver_arg(tctx, p, d);
8406 }
8407
8408 static bool test_add_driver_64(struct torture_context *tctx,
8409                                struct dcerpc_pipe *p,
8410                                void *private_data)
8411 {
8412         struct torture_driver_context *d =
8413                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8414
8415         d->local.environment            = talloc_strdup(d, "Windows x64");
8416         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/x64");
8417         d->info8.driver_name            = TORTURE_DRIVER;
8418         d->ex                           = false;
8419
8420         return test_add_driver_arg(tctx, p, d);
8421 }
8422
8423 static bool test_add_driver_32(struct torture_context *tctx,
8424                                struct dcerpc_pipe *p,
8425                                void *private_data)
8426 {
8427         struct torture_driver_context *d =
8428                 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
8429
8430         d->local.environment            = talloc_strdup(d, "Windows NT x86");
8431         d->local.driver_directory       = talloc_strdup(d, "/usr/share/cups/drivers/i386");
8432         d->info8.driver_name            = TORTURE_DRIVER;
8433         d->ex                           = false;
8434
8435         return test_add_driver_arg(tctx, p, d);
8436 }
8437
8438 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
8439 {
8440         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-DRIVER");
8441
8442         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
8443                                                         "driver", &ndr_table_spoolss);
8444         struct torture_driver_context *t;
8445
8446         t = talloc_zero(mem_ctx, struct torture_driver_context);
8447
8448         t->info8.version        = SPOOLSS_DRIVER_VERSION_200X;
8449         t->info8.driver_name    = NULL;
8450         t->info8.architecture   = NULL;
8451         t->info8.driver_path    = talloc_strdup(t, "pscript5.dll");
8452         t->info8.data_file      = talloc_strdup(t, "cups6.ppd");
8453         t->info8.config_file    = talloc_strdup(t, "cupsui6.dll");
8454
8455         torture_rpc_tcase_add_test_ex(tcase, "add_driver_64", test_add_driver_64, t);
8456         torture_rpc_tcase_add_test_ex(tcase, "add_driver_ex_64", test_add_driver_ex_64, t);
8457
8458         torture_rpc_tcase_add_test_ex(tcase, "add_driver_32", test_add_driver_32, t);
8459         torture_rpc_tcase_add_test_ex(tcase, "add_driver_ex_32", test_add_driver_ex_32, t);
8460
8461         return suite;
8462 }