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