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