s4-smbtorture: also try renaming jobname in test_DoPrintTest_check_jobs().
[Samba/ekacnet.git] / source4 / torture / rpc / spoolss.c
blob674682b6ab1fc41896fd8fb43abd7af3ac438bcc
1 /*
2 Unix SMB/CIFS implementation.
3 test suite for spoolss rpc operations
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
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.
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.
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/>.
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"
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"
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"
55 struct test_spoolss_context {
56 /* print server handle */
57 struct policy_handle server_handle;
59 /* for EnumPorts */
60 uint32_t port_count[3];
61 union spoolss_PortInfo *ports[3];
63 /* for EnumPrinterDrivers */
64 uint32_t driver_count[8];
65 union spoolss_DriverInfo *drivers[8];
67 /* for EnumMonitors */
68 uint32_t monitor_count[3];
69 union spoolss_MonitorInfo *monitors[3];
71 /* for EnumPrintProcessors */
72 uint32_t print_processor_count[2];
73 union spoolss_PrintProcessorInfo *print_processors[2];
75 /* for EnumPrinters */
76 uint32_t printer_count[6];
77 union spoolss_PrinterInfo *printers[6];
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;
93 struct torture_printer_context {
94 struct spoolss_SetPrinterInfo2 info2;
95 struct torture_driver_context driver;
96 bool ex;
97 bool wellknown;
98 bool added_driver;
99 bool have_driver;
102 static bool upload_printer_driver(struct torture_context *tctx,
103 const char *server_name,
104 struct torture_driver_context *d);
105 static bool remove_printer_driver(struct torture_context *tctx,
106 const char *server_name,
107 struct torture_driver_context *d);
108 static bool fillup_printserver_info(struct torture_context *tctx,
109 struct dcerpc_pipe *p,
110 struct torture_driver_context *d);
111 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
112 struct dcerpc_binding_handle *b,
113 const char *server_name,
114 struct spoolss_AddDriverInfo8 *r,
115 uint32_t flags,
116 bool ex);
118 #define COMPARE_STRING(tctx, c,r,e) \
119 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
121 /* not every compiler supports __typeof__() */
122 #if (__GNUC__ >= 3)
123 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
124 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
125 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
127 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
128 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
130 } while(0)
131 #else
132 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
133 #endif
135 #define COMPARE_UINT32(tctx, c, r, e) do {\
136 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
137 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
138 } while(0)
140 #define COMPARE_UINT64(tctx, c, r, e) do {\
141 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
142 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
143 } while(0)
146 #define COMPARE_NTTIME(tctx, c, r, e) do {\
147 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
148 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
149 } while(0)
151 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
152 int __i; \
153 if (!c.e && !r.e) { \
154 break; \
156 if (c.e && !r.e) { \
157 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
159 if (!c.e && r.e) { \
160 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
162 for (__i=0;c.e[__i] != NULL; __i++) { \
163 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
165 } while(0)
167 #define CHECK_ALIGN(size, n) do {\
168 if (size % n) {\
169 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
170 size, n, size + n - (size % n));\
172 } while(0)
174 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
176 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, ic, needed, align) do { \
177 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
178 uint32_t size = ndr_size_##fn##_info(tctx, ic, level, count, info);\
179 uint32_t round_size = DO_ROUND(size, align);\
180 if (round_size != needed) {\
181 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
182 CHECK_ALIGN(size, align);\
185 } while(0)
187 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, ic, needed, align) do { \
188 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
189 uint32_t size = ndr_size_##fn##_info(tctx, ic, count, info);\
190 uint32_t round_size = DO_ROUND(size, align);\
191 if (round_size != needed) {\
192 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
193 CHECK_ALIGN(size, align);\
196 } while(0)
198 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, ic, needed, align) do { \
199 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
200 uint32_t size = ndr_size_##fn(info, level, ic, 0);\
201 uint32_t round_size = DO_ROUND(size, align);\
202 if (round_size != needed) {\
203 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
204 CHECK_ALIGN(size, align);\
207 } while(0)
209 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context *tctx,
210 const union spoolss_PrinterInfo *i,
211 uint32_t level,
212 union spoolss_SetPrinterInfo *s)
214 switch (level) {
215 case 0:
216 s->info0 = talloc(tctx, struct spoolss_SetPrinterInfo0);
217 break;
218 case 2:
219 s->info2 = talloc(tctx, struct spoolss_SetPrinterInfo2);
220 s->info2->servername = i->info2.servername;
221 s->info2->printername = i->info2.printername;
222 s->info2->sharename = i->info2.sharename;
223 s->info2->portname = i->info2.portname;
224 s->info2->drivername = i->info2.drivername;
225 s->info2->comment = i->info2.comment;
226 s->info2->location = i->info2.location;
227 s->info2->devmode_ptr = 0;
228 s->info2->sepfile = i->info2.sepfile;
229 s->info2->printprocessor = i->info2.printprocessor;
230 s->info2->datatype = i->info2.datatype;
231 s->info2->parameters = i->info2.parameters;
232 s->info2->secdesc_ptr = 0;
233 s->info2->attributes = i->info2.attributes;
234 s->info2->priority = i->info2.priority;
235 s->info2->defaultpriority = i->info2.defaultpriority;
236 s->info2->starttime = i->info2.starttime;
237 s->info2->untiltime = i->info2.untiltime;
238 s->info2->status = i->info2.status;
239 s->info2->cjobs = i->info2.cjobs;
240 s->info2->averageppm = i->info2.averageppm;
241 break;
242 case 3:
243 case 4:
244 case 5:
245 case 6:
246 case 7:
247 case 8:
248 case 9:
249 default:
250 return false;
253 return true;
256 static bool test_OpenPrinter_server(struct torture_context *tctx,
257 struct dcerpc_pipe *p,
258 struct policy_handle *server_handle)
260 NTSTATUS status;
261 struct spoolss_OpenPrinter op;
262 struct dcerpc_binding_handle *b = p->binding_handle;
264 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
265 op.in.datatype = NULL;
266 op.in.devmode_ctr.devmode= NULL;
267 op.in.access_mask = 0;
268 op.out.handle = server_handle;
270 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
272 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
273 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
274 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
276 return true;
279 static bool test_EnumPorts(struct torture_context *tctx,
280 struct dcerpc_binding_handle *b,
281 struct test_spoolss_context *ctx)
283 NTSTATUS status;
284 struct spoolss_EnumPorts r;
285 uint16_t levels[] = { 1, 2 };
286 int i, j;
288 for (i=0;i<ARRAY_SIZE(levels);i++) {
289 int level = levels[i];
290 DATA_BLOB blob;
291 uint32_t needed;
292 uint32_t count;
293 union spoolss_PortInfo *info;
295 r.in.servername = "";
296 r.in.level = level;
297 r.in.buffer = NULL;
298 r.in.offered = 0;
299 r.out.needed = &needed;
300 r.out.count = &count;
301 r.out.info = &info;
303 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
305 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
306 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
307 if (W_ERROR_IS_OK(r.out.result)) {
308 /* TODO: do some more checks here */
309 continue;
311 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
312 "EnumPorts unexpected return code");
314 blob = data_blob_talloc_zero(ctx, needed);
315 r.in.buffer = &blob;
316 r.in.offered = needed;
318 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
319 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
321 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
323 torture_assert(tctx, info, "EnumPorts returned no info");
325 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
327 ctx->port_count[level] = count;
328 ctx->ports[level] = info;
331 for (i=1;i<ARRAY_SIZE(levels);i++) {
332 int level = levels[i];
333 int old_level = levels[i-1];
334 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
335 "EnumPorts invalid value");
337 /* if the array sizes are not the same we would maybe segfault in the following code */
339 for (i=0;i<ARRAY_SIZE(levels);i++) {
340 int level = levels[i];
341 for (j=0;j<ctx->port_count[level];j++) {
342 union spoolss_PortInfo *cur = &ctx->ports[level][j];
343 union spoolss_PortInfo *ref = &ctx->ports[2][j];
344 switch (level) {
345 case 1:
346 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
347 break;
348 case 2:
349 /* level 2 is our reference, and it makes no sense to compare it to itself */
350 break;
355 return true;
358 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
359 struct dcerpc_pipe *p,
360 const char *environment)
362 NTSTATUS status;
363 struct dcerpc_binding_handle *b = p->binding_handle;
364 struct spoolss_GetPrintProcessorDirectory r;
365 struct {
366 uint16_t level;
367 const char *server;
368 } levels[] = {{
369 .level = 1,
370 .server = NULL
372 .level = 1,
373 .server = ""
375 .level = 78,
376 .server = ""
378 .level = 1,
379 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
381 .level = 1024,
382 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
385 int i;
386 uint32_t needed;
388 for (i=0;i<ARRAY_SIZE(levels);i++) {
389 int level = levels[i].level;
390 DATA_BLOB blob;
392 r.in.server = levels[i].server;
393 r.in.environment = environment;
394 r.in.level = level;
395 r.in.buffer = NULL;
396 r.in.offered = 0;
397 r.out.needed = &needed;
399 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
401 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
402 torture_assert_ntstatus_ok(tctx, status,
403 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
404 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
405 "GetPrintProcessorDirectory unexpected return code");
407 blob = data_blob_talloc_zero(tctx, needed);
408 r.in.buffer = &blob;
409 r.in.offered = needed;
411 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
412 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
414 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
416 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
419 return true;
423 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
424 struct dcerpc_pipe *p,
425 const char *environment)
427 NTSTATUS status;
428 struct dcerpc_binding_handle *b = p->binding_handle;
429 struct spoolss_GetPrinterDriverDirectory r;
430 struct {
431 uint16_t level;
432 const char *server;
433 } levels[] = {{
434 .level = 1,
435 .server = NULL
437 .level = 1,
438 .server = ""
440 .level = 78,
441 .server = ""
443 .level = 1,
444 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
446 .level = 1024,
447 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
450 int i;
451 uint32_t needed;
453 for (i=0;i<ARRAY_SIZE(levels);i++) {
454 int level = levels[i].level;
455 DATA_BLOB blob;
457 r.in.server = levels[i].server;
458 r.in.environment = environment;
459 r.in.level = level;
460 r.in.buffer = NULL;
461 r.in.offered = 0;
462 r.out.needed = &needed;
464 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
466 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
467 torture_assert_ntstatus_ok(tctx, status,
468 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
469 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
470 "GetPrinterDriverDirectory unexpected return code");
472 blob = data_blob_talloc_zero(tctx, needed);
473 r.in.buffer = &blob;
474 r.in.offered = needed;
476 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
477 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
479 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
481 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
484 return true;
487 static bool test_EnumPrinterDrivers_args(struct torture_context *tctx,
488 struct dcerpc_binding_handle *b,
489 const char *server_name,
490 const char *environment,
491 uint32_t level,
492 uint32_t *count_p,
493 union spoolss_DriverInfo **info_p)
495 struct spoolss_EnumPrinterDrivers r;
496 uint32_t needed;
497 uint32_t count;
498 union spoolss_DriverInfo *info;
500 r.in.server = server_name;
501 r.in.environment = environment;
502 r.in.level = level;
503 r.in.buffer = NULL;
504 r.in.offered = 0;
505 r.out.needed = &needed;
506 r.out.count = &count;
507 r.out.info = &info;
509 torture_comment(tctx, "Testing EnumPrinterDrivers(%s) level %u\n",
510 r.in.environment, r.in.level);
512 torture_assert_ntstatus_ok(tctx,
513 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
514 "EnumPrinterDrivers failed");
515 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
516 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
517 r.in.buffer = &blob;
518 r.in.offered = needed;
520 torture_assert_ntstatus_ok(tctx,
521 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
522 "EnumPrinterDrivers failed");
525 torture_assert_werr_ok(tctx, r.out.result,
526 "EnumPrinterDrivers failed");
528 if (count_p) {
529 *count_p = count;
531 if (info_p) {
532 *info_p = info;
535 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
537 return true;
541 static bool test_EnumPrinterDrivers_findone(struct torture_context *tctx,
542 struct dcerpc_binding_handle *b,
543 const char *server_name,
544 const char *environment,
545 uint32_t level,
546 const char *driver_name)
548 uint32_t count;
549 union spoolss_DriverInfo *info;
550 int i;
552 torture_assert(tctx,
553 test_EnumPrinterDrivers_args(tctx, b, server_name, environment, level, &count, &info),
554 "failed to enumerate printer drivers");
556 for (i=0; i < count; i++) {
557 const char *driver_name_ret;
558 switch (level) {
559 case 1:
560 driver_name_ret = info[i].info1.driver_name;
561 break;
562 case 2:
563 driver_name_ret = info[i].info2.driver_name;
564 break;
565 case 3:
566 driver_name_ret = info[i].info3.driver_name;
567 break;
568 case 4:
569 driver_name_ret = info[i].info4.driver_name;
570 break;
571 case 5:
572 driver_name_ret = info[i].info5.driver_name;
573 break;
574 case 6:
575 driver_name_ret = info[i].info6.driver_name;
576 break;
577 case 7:
578 driver_name_ret = info[i].info7.driver_name;
579 break;
580 case 8:
581 driver_name_ret = info[i].info8.driver_name;
582 break;
583 default:
584 break;
586 if (strequal(driver_name, driver_name_ret)) {
587 return true;
591 return false;
594 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
595 struct dcerpc_pipe *p,
596 struct test_spoolss_context *ctx,
597 const char *architecture)
599 struct dcerpc_binding_handle *b = p->binding_handle;
600 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
601 int i, j;
603 /* FIXME: gd, come back and fix "" as server, and handle
604 * priority of returned error codes in torture test and samba 3
605 * server */
606 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
608 for (i=0;i<ARRAY_SIZE(levels);i++) {
609 int level = levels[i];
610 uint32_t count;
611 union spoolss_DriverInfo *info;
613 torture_assert(tctx,
614 test_EnumPrinterDrivers_args(tctx, b, server_name, architecture, level, &count, &info),
615 "failed to enumerate drivers");
617 ctx->driver_count[level] = count;
618 ctx->drivers[level] = info;
621 for (i=1;i<ARRAY_SIZE(levels);i++) {
622 int level = levels[i];
623 int old_level = levels[i-1];
625 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
626 "EnumPrinterDrivers invalid value");
629 for (i=0;i<ARRAY_SIZE(levels);i++) {
630 int level = levels[i];
632 for (j=0;j<ctx->driver_count[level];j++) {
633 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
634 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
636 switch (level) {
637 case 1:
638 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
639 break;
640 case 2:
641 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
642 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
643 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
644 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
645 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
646 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
647 break;
648 case 3:
649 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
650 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
651 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
652 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
653 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
654 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
655 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
656 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
657 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
658 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
659 break;
660 case 4:
661 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
662 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
663 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
664 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
665 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
666 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
667 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
668 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
669 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
670 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
671 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
672 break;
673 case 5:
674 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
675 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
676 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
677 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
678 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
679 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
680 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
681 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
682 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
683 break;
684 case 6:
685 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
686 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
687 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
688 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
689 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
690 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
691 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
692 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
693 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
694 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
695 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
696 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
697 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
698 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
699 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
700 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
701 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
702 break;
703 case 8:
704 /* level 8 is our reference, and it makes no sense to compare it to itself */
705 break;
710 return true;
713 static bool test_EnumMonitors(struct torture_context *tctx,
714 struct dcerpc_binding_handle *b,
715 struct test_spoolss_context *ctx)
717 NTSTATUS status;
718 struct spoolss_EnumMonitors r;
719 uint16_t levels[] = { 1, 2 };
720 int i, j;
722 for (i=0;i<ARRAY_SIZE(levels);i++) {
723 int level = levels[i];
724 DATA_BLOB blob;
725 uint32_t needed;
726 uint32_t count;
727 union spoolss_MonitorInfo *info;
729 r.in.servername = "";
730 r.in.level = level;
731 r.in.buffer = NULL;
732 r.in.offered = 0;
733 r.out.needed = &needed;
734 r.out.count = &count;
735 r.out.info = &info;
737 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
739 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
740 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
741 if (W_ERROR_IS_OK(r.out.result)) {
742 /* TODO: do some more checks here */
743 continue;
745 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
746 "EnumMonitors failed");
748 blob = data_blob_talloc_zero(ctx, needed);
749 r.in.buffer = &blob;
750 r.in.offered = needed;
752 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
753 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
755 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
757 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
759 ctx->monitor_count[level] = count;
760 ctx->monitors[level] = info;
763 for (i=1;i<ARRAY_SIZE(levels);i++) {
764 int level = levels[i];
765 int old_level = levels[i-1];
766 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
767 "EnumMonitors invalid value");
770 for (i=0;i<ARRAY_SIZE(levels);i++) {
771 int level = levels[i];
772 for (j=0;j<ctx->monitor_count[level];j++) {
773 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
774 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
775 switch (level) {
776 case 1:
777 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
778 break;
779 case 2:
780 /* level 2 is our reference, and it makes no sense to compare it to itself */
781 break;
786 return true;
789 static bool test_EnumPrintProcessors(struct torture_context *tctx,
790 struct dcerpc_binding_handle *b,
791 struct test_spoolss_context *ctx,
792 const char *environment)
794 NTSTATUS status;
795 struct spoolss_EnumPrintProcessors r;
796 uint16_t levels[] = { 1 };
797 int i, j;
799 for (i=0;i<ARRAY_SIZE(levels);i++) {
800 int level = levels[i];
801 DATA_BLOB blob;
802 uint32_t needed;
803 uint32_t count;
804 union spoolss_PrintProcessorInfo *info;
806 r.in.servername = "";
807 r.in.environment = environment;
808 r.in.level = level;
809 r.in.buffer = NULL;
810 r.in.offered = 0;
811 r.out.needed = &needed;
812 r.out.count = &count;
813 r.out.info = &info;
815 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
817 status = dcerpc_spoolss_EnumPrintProcessors_r(b, ctx, &r);
818 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
819 if (W_ERROR_IS_OK(r.out.result)) {
820 /* TODO: do some more checks here */
821 continue;
823 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
824 "EnumPrintProcessors unexpected return code");
826 blob = data_blob_talloc_zero(ctx, needed);
827 r.in.buffer = &blob;
828 r.in.offered = needed;
830 status = dcerpc_spoolss_EnumPrintProcessors_r(b, ctx, &r);
831 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
833 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
835 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
837 ctx->print_processor_count[level] = count;
838 ctx->print_processors[level] = info;
841 for (i=1;i<ARRAY_SIZE(levels);i++) {
842 int level = levels[i];
843 int old_level = levels[i-1];
844 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
845 "EnumPrintProcessors failed");
848 for (i=0;i<ARRAY_SIZE(levels);i++) {
849 int level = levels[i];
850 for (j=0;j<ctx->print_processor_count[level];j++) {
851 #if 0
852 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
853 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
854 #endif
855 switch (level) {
856 case 1:
857 /* level 1 is our reference, and it makes no sense to compare it to itself */
858 break;
863 return true;
866 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
867 struct dcerpc_binding_handle *b)
869 NTSTATUS status;
870 struct spoolss_EnumPrintProcDataTypes r;
871 uint16_t levels[] = { 1 };
872 int i;
874 for (i=0;i<ARRAY_SIZE(levels);i++) {
875 int level = levels[i];
876 DATA_BLOB blob;
877 uint32_t needed;
878 uint32_t count;
879 union spoolss_PrintProcDataTypesInfo *info;
881 r.in.servername = "";
882 r.in.print_processor_name = "winprint";
883 r.in.level = level;
884 r.in.buffer = NULL;
885 r.in.offered = 0;
886 r.out.needed = &needed;
887 r.out.count = &count;
888 r.out.info = &info;
890 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
892 status = dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r);
893 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
894 if (W_ERROR_IS_OK(r.out.result)) {
895 /* TODO: do some more checks here */
896 continue;
898 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
899 "EnumPrintProcDataTypes unexpected return code");
901 blob = data_blob_talloc_zero(tctx, needed);
902 r.in.buffer = &blob;
903 r.in.offered = needed;
905 status = dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r);
906 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
908 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
910 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
914 return true;
918 static bool test_EnumPrinters(struct torture_context *tctx,
919 struct dcerpc_binding_handle *b,
920 struct test_spoolss_context *ctx)
922 struct spoolss_EnumPrinters r;
923 NTSTATUS status;
924 uint16_t levels[] = { 0, 1, 2, 4, 5 };
925 int i, j;
927 for (i=0;i<ARRAY_SIZE(levels);i++) {
928 int level = levels[i];
929 DATA_BLOB blob;
930 uint32_t needed;
931 uint32_t count;
932 union spoolss_PrinterInfo *info;
934 r.in.flags = PRINTER_ENUM_LOCAL;
935 r.in.server = "";
936 r.in.level = level;
937 r.in.buffer = NULL;
938 r.in.offered = 0;
939 r.out.needed = &needed;
940 r.out.count = &count;
941 r.out.info = &info;
943 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
945 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
946 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
947 if (W_ERROR_IS_OK(r.out.result)) {
948 /* TODO: do some more checks here */
949 continue;
951 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
952 "EnumPrinters unexpected return code");
954 blob = data_blob_talloc_zero(ctx, needed);
955 r.in.buffer = &blob;
956 r.in.offered = needed;
958 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
959 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
961 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
963 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
965 ctx->printer_count[level] = count;
966 ctx->printers[level] = info;
969 for (i=1;i<ARRAY_SIZE(levels);i++) {
970 int level = levels[i];
971 int old_level = levels[i-1];
972 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
973 "EnumPrinters invalid value");
976 for (i=0;i<ARRAY_SIZE(levels);i++) {
977 int level = levels[i];
978 for (j=0;j<ctx->printer_count[level];j++) {
979 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
980 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
981 switch (level) {
982 case 0:
983 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
984 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
985 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
986 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
987 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
988 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
989 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
990 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
991 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
992 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
993 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
994 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
995 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
996 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
997 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
998 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
999 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
1000 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
1001 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
1002 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
1003 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
1004 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
1005 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
1006 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
1007 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
1008 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
1009 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
1010 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
1011 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
1012 break;
1013 case 1:
1014 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
1015 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
1016 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
1017 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
1018 break;
1019 case 2:
1020 /* level 2 is our reference, and it makes no sense to compare it to itself */
1021 break;
1022 case 4:
1023 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
1024 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
1025 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
1026 break;
1027 case 5:
1028 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
1029 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
1030 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
1031 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
1032 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
1033 break;
1038 /* TODO:
1039 * - verify that the port of a printer was in the list returned by EnumPorts
1042 return true;
1045 static bool test_GetPrinterDriver2(struct torture_context *tctx,
1046 struct dcerpc_binding_handle *b,
1047 struct policy_handle *handle,
1048 const char *driver_name,
1049 const char *environment);
1051 bool test_GetPrinter_level(struct torture_context *tctx,
1052 struct dcerpc_binding_handle *b,
1053 struct policy_handle *handle,
1054 uint32_t level,
1055 union spoolss_PrinterInfo *info)
1057 struct spoolss_GetPrinter r;
1058 uint32_t needed;
1060 r.in.handle = handle;
1061 r.in.level = level;
1062 r.in.buffer = NULL;
1063 r.in.offered = 0;
1064 r.out.needed = &needed;
1066 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
1068 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1069 "GetPrinter failed");
1071 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1072 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
1073 r.in.buffer = &blob;
1074 r.in.offered = needed;
1076 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1077 "GetPrinter failed");
1080 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
1082 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
1084 if (info && r.out.info) {
1085 *info = *r.out.info;
1088 return true;
1092 static bool test_GetPrinter(struct torture_context *tctx,
1093 struct dcerpc_binding_handle *b,
1094 struct policy_handle *handle,
1095 const char *environment)
1097 uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1098 int i;
1100 for (i=0;i<ARRAY_SIZE(levels);i++) {
1102 union spoolss_PrinterInfo info;
1104 ZERO_STRUCT(info);
1106 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
1107 "failed to call GetPrinter");
1109 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
1110 torture_assert(tctx,
1111 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
1112 "failed to call test_GetPrinterDriver2");
1116 return true;
1119 static bool test_SetPrinter(struct torture_context *tctx,
1120 struct dcerpc_binding_handle *b,
1121 struct policy_handle *handle,
1122 struct spoolss_SetPrinterInfoCtr *info_ctr,
1123 struct spoolss_DevmodeContainer *devmode_ctr,
1124 struct sec_desc_buf *secdesc_ctr,
1125 enum spoolss_PrinterControl command)
1127 struct spoolss_SetPrinter r;
1129 r.in.handle = handle;
1130 r.in.info_ctr = info_ctr;
1131 r.in.devmode_ctr = devmode_ctr;
1132 r.in.secdesc_ctr = secdesc_ctr;
1133 r.in.command = command;
1135 torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1137 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1138 "failed to call SetPrinter");
1139 torture_assert_werr_ok(tctx, r.out.result,
1140 "failed to call SetPrinter");
1142 return true;
1145 static bool test_SetPrinter_errors(struct torture_context *tctx,
1146 struct dcerpc_binding_handle *b,
1147 struct policy_handle *handle)
1149 struct spoolss_SetPrinter r;
1150 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1151 int i;
1153 struct spoolss_SetPrinterInfoCtr info_ctr;
1154 struct spoolss_DevmodeContainer devmode_ctr;
1155 struct sec_desc_buf secdesc_ctr;
1157 info_ctr.level = 0;
1158 info_ctr.info.info0 = NULL;
1160 ZERO_STRUCT(devmode_ctr);
1161 ZERO_STRUCT(secdesc_ctr);
1163 r.in.handle = handle;
1164 r.in.info_ctr = &info_ctr;
1165 r.in.devmode_ctr = &devmode_ctr;
1166 r.in.secdesc_ctr = &secdesc_ctr;
1167 r.in.command = 0;
1169 torture_comment(tctx, "Testing SetPrinter all zero\n");
1171 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1172 "failed to call SetPrinter");
1173 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1174 "failed to call SetPrinter");
1176 again:
1177 for (i=0; i < ARRAY_SIZE(levels); i++) {
1179 struct spoolss_SetPrinterInfo0 info0;
1180 struct spoolss_SetPrinterInfo1 info1;
1181 struct spoolss_SetPrinterInfo2 info2;
1182 struct spoolss_SetPrinterInfo3 info3;
1183 struct spoolss_SetPrinterInfo4 info4;
1184 struct spoolss_SetPrinterInfo5 info5;
1185 struct spoolss_SetPrinterInfo6 info6;
1186 struct spoolss_SetPrinterInfo7 info7;
1187 struct spoolss_SetPrinterInfo8 info8;
1188 struct spoolss_SetPrinterInfo9 info9;
1191 info_ctr.level = levels[i];
1192 switch (levels[i]) {
1193 case 0:
1194 ZERO_STRUCT(info0);
1195 info_ctr.info.info0 = &info0;
1196 break;
1197 case 1:
1198 ZERO_STRUCT(info1);
1199 info_ctr.info.info1 = &info1;
1200 break;
1201 case 2:
1202 ZERO_STRUCT(info2);
1203 info_ctr.info.info2 = &info2;
1204 break;
1205 case 3:
1206 ZERO_STRUCT(info3);
1207 info_ctr.info.info3 = &info3;
1208 break;
1209 case 4:
1210 ZERO_STRUCT(info4);
1211 info_ctr.info.info4 = &info4;
1212 break;
1213 case 5:
1214 ZERO_STRUCT(info5);
1215 info_ctr.info.info5 = &info5;
1216 break;
1217 case 6:
1218 ZERO_STRUCT(info6);
1219 info_ctr.info.info6 = &info6;
1220 break;
1221 case 7:
1222 ZERO_STRUCT(info7);
1223 info_ctr.info.info7 = &info7;
1224 break;
1225 case 8:
1226 ZERO_STRUCT(info8);
1227 info_ctr.info.info8 = &info8;
1228 break;
1229 case 9:
1230 ZERO_STRUCT(info9);
1231 info_ctr.info.info9 = &info9;
1232 break;
1235 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1236 info_ctr.level, r.in.command);
1238 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1239 "failed to call SetPrinter");
1241 switch (r.in.command) {
1242 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1243 /* is ignored for all levels other then 0 */
1244 if (info_ctr.level > 0) {
1245 /* ignored then */
1246 break;
1248 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1249 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1250 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1251 if (info_ctr.level > 0) {
1252 /* is invalid for all levels other then 0 */
1253 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1254 "unexpected error code returned");
1255 continue;
1256 } else {
1257 torture_assert_werr_ok(tctx, r.out.result,
1258 "failed to call SetPrinter with non 0 command");
1259 continue;
1261 break;
1263 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1264 /* FIXME: gd needs further investigation */
1265 default:
1266 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1267 "unexpected error code returned");
1268 continue;
1271 switch (info_ctr.level) {
1272 case 1:
1273 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1274 "unexpected error code returned");
1275 break;
1276 case 2:
1277 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1278 "unexpected error code returned");
1279 break;
1280 case 3:
1281 case 4:
1282 case 5:
1283 case 7:
1284 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1285 "unexpected error code returned");
1286 break;
1287 case 9:
1288 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1289 "unexpected error code returned");
1290 break;
1291 default:
1292 torture_assert_werr_ok(tctx, r.out.result,
1293 "failed to call SetPrinter");
1294 break;
1298 if (r.in.command < 5) {
1299 r.in.command++;
1300 goto again;
1303 return true;
1306 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1308 if ((r->level == 2) && (r->info.info2)) {
1309 r->info.info2->secdesc_ptr = 0;
1310 r->info.info2->devmode_ptr = 0;
1314 static bool test_PrinterInfo(struct torture_context *tctx,
1315 struct dcerpc_binding_handle *b,
1316 struct policy_handle *handle)
1318 NTSTATUS status;
1319 struct spoolss_SetPrinter s;
1320 struct spoolss_GetPrinter q;
1321 struct spoolss_GetPrinter q0;
1322 struct spoolss_SetPrinterInfoCtr info_ctr;
1323 union spoolss_PrinterInfo info;
1324 struct spoolss_DevmodeContainer devmode_ctr;
1325 struct sec_desc_buf secdesc_ctr;
1326 uint32_t needed;
1327 bool ret = true;
1328 int i;
1330 uint32_t status_list[] = {
1331 /* these do not stick
1332 PRINTER_STATUS_PAUSED,
1333 PRINTER_STATUS_ERROR,
1334 PRINTER_STATUS_PENDING_DELETION, */
1335 PRINTER_STATUS_PAPER_JAM,
1336 PRINTER_STATUS_PAPER_OUT,
1337 PRINTER_STATUS_MANUAL_FEED,
1338 PRINTER_STATUS_PAPER_PROBLEM,
1339 PRINTER_STATUS_OFFLINE,
1340 PRINTER_STATUS_IO_ACTIVE,
1341 PRINTER_STATUS_BUSY,
1342 PRINTER_STATUS_PRINTING,
1343 PRINTER_STATUS_OUTPUT_BIN_FULL,
1344 PRINTER_STATUS_NOT_AVAILABLE,
1345 PRINTER_STATUS_WAITING,
1346 PRINTER_STATUS_PROCESSING,
1347 PRINTER_STATUS_INITIALIZING,
1348 PRINTER_STATUS_WARMING_UP,
1349 PRINTER_STATUS_TONER_LOW,
1350 PRINTER_STATUS_NO_TONER,
1351 PRINTER_STATUS_PAGE_PUNT,
1352 PRINTER_STATUS_USER_INTERVENTION,
1353 PRINTER_STATUS_OUT_OF_MEMORY,
1354 PRINTER_STATUS_DOOR_OPEN,
1355 PRINTER_STATUS_SERVER_UNKNOWN,
1356 PRINTER_STATUS_POWER_SAVE,
1357 /* these do not stick
1358 0x02000000,
1359 0x04000000,
1360 0x08000000,
1361 0x10000000,
1362 0x20000000,
1363 0x40000000,
1364 0x80000000 */
1366 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1367 uint32_t attribute_list[] = {
1368 PRINTER_ATTRIBUTE_QUEUED,
1369 /* fails with WERR_INVALID_DATATYPE:
1370 PRINTER_ATTRIBUTE_DIRECT, */
1371 /* does not stick
1372 PRINTER_ATTRIBUTE_DEFAULT, */
1373 PRINTER_ATTRIBUTE_SHARED,
1374 /* does not stick
1375 PRINTER_ATTRIBUTE_NETWORK, */
1376 PRINTER_ATTRIBUTE_HIDDEN,
1377 PRINTER_ATTRIBUTE_LOCAL,
1378 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1379 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1380 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1381 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1382 /* does not stick
1383 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1384 /* fails with WERR_INVALID_DATATYPE:
1385 PRINTER_ATTRIBUTE_RAW_ONLY, */
1386 /* these do not stick
1387 PRINTER_ATTRIBUTE_PUBLISHED,
1388 PRINTER_ATTRIBUTE_FAX,
1389 PRINTER_ATTRIBUTE_TS,
1390 0x00010000,
1391 0x00020000,
1392 0x00040000,
1393 0x00080000,
1394 0x00100000,
1395 0x00200000,
1396 0x00400000,
1397 0x00800000,
1398 0x01000000,
1399 0x02000000,
1400 0x04000000,
1401 0x08000000,
1402 0x10000000,
1403 0x20000000,
1404 0x40000000,
1405 0x80000000 */
1408 ZERO_STRUCT(devmode_ctr);
1409 ZERO_STRUCT(secdesc_ctr);
1411 s.in.handle = handle;
1412 s.in.command = 0;
1413 s.in.info_ctr = &info_ctr;
1414 s.in.devmode_ctr = &devmode_ctr;
1415 s.in.secdesc_ctr = &secdesc_ctr;
1417 q.in.handle = handle;
1418 q.out.info = &info;
1419 q0 = q;
1421 #define TESTGETCALL(call, r) \
1422 r.in.buffer = NULL; \
1423 r.in.offered = 0;\
1424 r.out.needed = &needed; \
1425 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1426 if (!NT_STATUS_IS_OK(status)) { \
1427 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1428 r.in.level, nt_errstr(status), __location__); \
1429 ret = false; \
1430 break; \
1432 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1433 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1434 r.in.buffer = &blob; \
1435 r.in.offered = needed; \
1437 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1438 if (!NT_STATUS_IS_OK(status)) { \
1439 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1440 r.in.level, nt_errstr(status), __location__); \
1441 ret = false; \
1442 break; \
1444 if (!W_ERROR_IS_OK(r.out.result)) { \
1445 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1446 r.in.level, win_errstr(r.out.result), __location__); \
1447 ret = false; \
1448 break; \
1452 #define TESTSETCALL_EXP(call, r, err) \
1453 clear_info2(&info_ctr);\
1454 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1455 if (!NT_STATUS_IS_OK(status)) { \
1456 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1457 r.in.info_ctr->level, nt_errstr(status), __location__); \
1458 ret = false; \
1459 break; \
1461 if (!W_ERROR_IS_OK(err)) { \
1462 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1463 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1464 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1465 ret = false; \
1467 break; \
1469 if (!W_ERROR_IS_OK(r.out.result)) { \
1470 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1471 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1472 ret = false; \
1473 break; \
1476 #define TESTSETCALL(call, r) \
1477 TESTSETCALL_EXP(call, r, WERR_OK)
1479 #define STRING_EQUAL(s1, s2, field) \
1480 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1481 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1482 #field, s2, __location__); \
1483 ret = false; \
1484 break; \
1487 #define MEM_EQUAL(s1, s2, length, field) \
1488 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1489 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1490 #field, (const char *)s2, __location__); \
1491 ret = false; \
1492 break; \
1495 #define INT_EQUAL(i1, i2, field) \
1496 if (i1 != i2) { \
1497 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1498 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1499 ret = false; \
1500 break; \
1503 #define SD_EQUAL(sd1, sd2, field) \
1504 if (!security_descriptor_equal(sd1, sd2)) { \
1505 torture_comment(tctx, "Failed to set %s (%s)\n", \
1506 #field, __location__); \
1507 ret = false; \
1508 break; \
1511 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1512 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1513 q.in.level = lvl1; \
1514 TESTGETCALL(GetPrinter, q) \
1515 info_ctr.level = lvl1; \
1516 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1517 info_ctr.info.info ## lvl1->field1 = value;\
1518 TESTSETCALL_EXP(SetPrinter, s, err) \
1519 info_ctr.info.info ## lvl1->field1 = ""; \
1520 TESTGETCALL(GetPrinter, q) \
1521 info_ctr.info.info ## lvl1->field1 = value; \
1522 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1523 q.in.level = lvl2; \
1524 TESTGETCALL(GetPrinter, q) \
1525 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1526 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1527 } while (0)
1529 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1530 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1531 } while (0);
1533 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1534 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1535 q.in.level = lvl1; \
1536 TESTGETCALL(GetPrinter, q) \
1537 info_ctr.level = lvl1; \
1538 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1539 info_ctr.info.info ## lvl1->field1 = value; \
1540 TESTSETCALL(SetPrinter, s) \
1541 info_ctr.info.info ## lvl1->field1 = 0; \
1542 TESTGETCALL(GetPrinter, q) \
1543 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1544 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1545 q.in.level = lvl2; \
1546 TESTGETCALL(GetPrinter, q) \
1547 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1548 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1549 } while (0)
1551 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1552 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1553 } while (0)
1555 q0.in.level = 0;
1556 do { TESTGETCALL(GetPrinter, q0) } while (0);
1558 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1559 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1561 /* level 0 printername does not stick */
1562 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1563 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1564 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1565 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1566 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1567 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1568 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1569 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1570 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1571 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1572 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1573 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1574 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1575 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1576 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1578 /* servername can be set but does not stick
1579 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1580 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1581 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1584 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1585 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1586 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1587 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1588 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1590 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1591 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1592 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1593 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1594 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1595 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1596 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1597 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1598 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1599 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1601 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1602 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1603 attribute_list[i],
1604 (attribute_list[i] | default_attribute)
1605 ); */
1606 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1607 attribute_list[i],
1608 (attribute_list[i] | default_attribute)
1610 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1611 attribute_list[i],
1612 (attribute_list[i] | default_attribute)
1614 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1615 attribute_list[i],
1616 (attribute_list[i] | default_attribute)
1618 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1619 attribute_list[i],
1620 (attribute_list[i] | default_attribute)
1621 ); */
1622 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1623 attribute_list[i],
1624 (attribute_list[i] | default_attribute)
1626 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1627 attribute_list[i],
1628 (attribute_list[i] | default_attribute)
1630 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1631 attribute_list[i],
1632 (attribute_list[i] | default_attribute)
1634 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1635 attribute_list[i],
1636 (attribute_list[i] | default_attribute)
1637 ); */
1638 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1639 attribute_list[i],
1640 (attribute_list[i] | default_attribute)
1642 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1643 attribute_list[i],
1644 (attribute_list[i] | default_attribute)
1646 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1647 attribute_list[i],
1648 (attribute_list[i] | default_attribute)
1652 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1653 /* level 2 sets do not stick
1654 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1655 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1656 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1657 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1658 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1659 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1662 /* priorities need to be between 0 and 99
1663 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1664 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1665 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1666 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1667 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1668 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1669 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1670 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1671 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1673 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1674 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1676 /* does not stick
1677 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1678 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1680 /* does not stick
1681 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1682 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1684 /* FIXME: gd also test devmode and secdesc behavior */
1687 /* verify composition of level 1 description field */
1688 const char *description;
1689 const char *tmp;
1691 q0.in.level = 1;
1692 do { TESTGETCALL(GetPrinter, q0) } while (0);
1694 description = talloc_strdup(tctx, q0.out.info->info1.description);
1696 q0.in.level = 2;
1697 do { TESTGETCALL(GetPrinter, q0) } while (0);
1699 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1700 q0.out.info->info2.printername,
1701 q0.out.info->info2.drivername,
1702 q0.out.info->info2.location);
1704 do { STRING_EQUAL(description, tmp, "description")} while (0);
1707 return ret;
1710 #define torture_assert_sid_equal(torture_ctx,got,expected,cmt)\
1711 do { struct dom_sid *__got = (got), *__expected = (expected); \
1712 if (!dom_sid_equal(__got, __expected)) { \
1713 torture_result(torture_ctx, TORTURE_FAIL, \
1714 __location__": "#got" was %s, expected %s: %s", \
1715 dom_sid_string(torture_ctx, __got), dom_sid_string(torture_ctx, __expected), cmt); \
1716 return false; \
1718 } while(0)
1720 static bool test_security_descriptor_equal(struct torture_context *tctx,
1721 const struct security_descriptor *sd1,
1722 const struct security_descriptor *sd2)
1724 if (sd1 == sd2) {
1725 return true;
1728 if (!sd1 || !sd2) {
1729 torture_comment(tctx, "%s\n", __location__);
1730 return false;
1733 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1734 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1736 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1737 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1739 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1740 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1741 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1742 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1743 return false;
1745 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1746 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1747 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1748 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1749 return false;
1752 return true;
1755 static bool test_sd_set_level(struct torture_context *tctx,
1756 struct dcerpc_binding_handle *b,
1757 struct policy_handle *handle,
1758 uint32_t level,
1759 struct security_descriptor *sd)
1761 struct spoolss_SetPrinterInfoCtr info_ctr;
1762 struct spoolss_DevmodeContainer devmode_ctr;
1763 struct sec_desc_buf secdesc_ctr;
1764 union spoolss_SetPrinterInfo sinfo;
1766 ZERO_STRUCT(devmode_ctr);
1767 ZERO_STRUCT(secdesc_ctr);
1769 switch (level) {
1770 case 2: {
1771 union spoolss_PrinterInfo info;
1772 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1773 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1775 info_ctr.level = 2;
1776 info_ctr.info = sinfo;
1778 break;
1780 case 3: {
1781 struct spoolss_SetPrinterInfo3 info3;
1783 info3.sec_desc_ptr = 0;
1785 info_ctr.level = 3;
1786 info_ctr.info.info3 = &info3;
1788 break;
1790 default:
1791 return false;
1794 secdesc_ctr.sd = sd;
1796 torture_assert(tctx,
1797 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1799 return true;
1802 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1803 struct dcerpc_binding_handle *b,
1804 struct policy_handle *handle)
1806 union spoolss_PrinterInfo info;
1807 struct security_descriptor *sd1, *sd2;
1808 int i;
1810 /* just compare level 2 and level 3 */
1812 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1814 sd1 = info.info2.secdesc;
1816 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1818 sd2 = info.info3.secdesc;
1820 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1821 "SD level 2 != SD level 3");
1824 /* query level 2, set level 2, query level 2 */
1826 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1828 sd1 = info.info2.secdesc;
1830 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1832 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1834 sd2 = info.info2.secdesc;
1835 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1836 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1837 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1840 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1841 "SD level 2 != SD level 2 after SD has been set via level 2");
1844 /* query level 2, set level 3, query level 2 */
1846 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1848 sd1 = info.info2.secdesc;
1850 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1852 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1854 sd2 = info.info2.secdesc;
1856 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1857 "SD level 2 != SD level 2 after SD has been set via level 3");
1859 /* set modified sd level 3, query level 2 */
1861 for (i=0; i < 93; i++) {
1862 struct security_ace a;
1863 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1864 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1865 a.flags = 0;
1866 a.size = 0; /* autogenerated */
1867 a.access_mask = 0;
1868 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1869 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1872 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1874 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1875 sd2 = info.info2.secdesc;
1877 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1878 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1879 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1882 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1883 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1886 return true;
1890 * wrapper call that saves original sd, runs tests, and restores sd
1893 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1894 struct dcerpc_binding_handle *b,
1895 struct policy_handle *handle)
1897 union spoolss_PrinterInfo info;
1898 struct security_descriptor *sd;
1899 bool ret = true;
1901 torture_comment(tctx, "Testing Printer Security Descriptors\n");
1903 /* save original sd */
1905 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
1906 "failed to get initial security descriptor");
1908 sd = security_descriptor_copy(tctx, info.info2.secdesc);
1910 /* run tests */
1912 ret = test_PrinterInfo_SDs(tctx, b, handle);
1914 /* restore original sd */
1916 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
1917 "failed to restore initial security descriptor");
1919 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
1920 ret ? "succeeded" : "failed");
1923 return ret;
1926 static bool test_devmode_set_level(struct torture_context *tctx,
1927 struct dcerpc_binding_handle *b,
1928 struct policy_handle *handle,
1929 uint32_t level,
1930 struct spoolss_DeviceMode *devmode)
1932 struct spoolss_SetPrinterInfoCtr info_ctr;
1933 struct spoolss_DevmodeContainer devmode_ctr;
1934 struct sec_desc_buf secdesc_ctr;
1935 union spoolss_SetPrinterInfo sinfo;
1937 ZERO_STRUCT(devmode_ctr);
1938 ZERO_STRUCT(secdesc_ctr);
1940 switch (level) {
1941 case 2: {
1942 union spoolss_PrinterInfo info;
1943 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1944 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1946 info_ctr.level = 2;
1947 info_ctr.info = sinfo;
1949 break;
1951 case 8: {
1952 struct spoolss_SetPrinterInfo8 info8;
1954 info8.devmode_ptr = 0;
1956 info_ctr.level = 8;
1957 info_ctr.info.info8 = &info8;
1959 break;
1961 default:
1962 return false;
1965 devmode_ctr.devmode = devmode;
1967 torture_assert(tctx,
1968 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1970 return true;
1974 static bool test_devicemode_equal(struct torture_context *tctx,
1975 const struct spoolss_DeviceMode *d1,
1976 const struct spoolss_DeviceMode *d2)
1978 if (d1 == d2) {
1979 return true;
1982 if (!d1 || !d2) {
1983 torture_comment(tctx, "%s\n", __location__);
1984 return false;
1986 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
1987 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
1988 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
1989 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
1990 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
1991 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
1992 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
1993 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
1994 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
1995 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
1996 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
1997 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
1998 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
1999 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2000 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2001 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2002 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2003 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2004 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2005 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2006 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2007 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2008 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2009 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2010 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2011 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2012 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2013 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2014 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2015 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2016 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2017 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2018 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2019 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2020 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2022 return true;
2025 static bool test_devicemode_full(struct torture_context *tctx,
2026 struct dcerpc_binding_handle *b,
2027 struct policy_handle *handle)
2029 struct spoolss_SetPrinter s;
2030 struct spoolss_GetPrinter q;
2031 struct spoolss_GetPrinter q0;
2032 struct spoolss_SetPrinterInfoCtr info_ctr;
2033 struct spoolss_SetPrinterInfo8 info8;
2034 union spoolss_PrinterInfo info;
2035 struct spoolss_DevmodeContainer devmode_ctr;
2036 struct sec_desc_buf secdesc_ctr;
2037 uint32_t needed;
2038 bool ret = true;
2039 NTSTATUS status;
2041 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
2042 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2043 q.in.level = lvl1; \
2044 TESTGETCALL(GetPrinter, q) \
2045 info_ctr.level = lvl1; \
2046 if (lvl1 == 2) {\
2047 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
2048 } else if (lvl1 == 8) {\
2049 info_ctr.info.info ## lvl1 = &info8; \
2051 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2052 devmode_ctr.devmode->field1 = value; \
2053 TESTSETCALL(SetPrinter, s) \
2054 TESTGETCALL(GetPrinter, q) \
2055 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2056 q.in.level = lvl2; \
2057 TESTGETCALL(GetPrinter, q) \
2058 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2059 } while (0)
2061 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2062 TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
2063 } while (0)
2065 ZERO_STRUCT(devmode_ctr);
2066 ZERO_STRUCT(secdesc_ctr);
2067 ZERO_STRUCT(info8);
2069 s.in.handle = handle;
2070 s.in.command = 0;
2071 s.in.info_ctr = &info_ctr;
2072 s.in.devmode_ctr = &devmode_ctr;
2073 s.in.secdesc_ctr = &secdesc_ctr;
2075 q.in.handle = handle;
2076 q.out.info = &info;
2077 q0 = q;
2079 #if 0
2080 const char *devicename;/* [charset(UTF16)] */
2081 enum spoolss_DeviceModeSpecVersion specversion;
2082 uint16_t driverversion;
2083 uint16_t size;
2084 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2085 uint32_t fields;
2086 #endif
2088 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
2089 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
2090 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
2091 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
2092 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
2093 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
2094 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
2095 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
2096 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
2097 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
2098 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
2099 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
2100 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
2101 #if 0
2102 const char *formname;/* [charset(UTF16)] */
2103 #endif
2104 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
2105 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
2106 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
2107 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
2108 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
2109 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
2110 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
2111 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
2112 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
2113 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
2114 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
2115 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
2116 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
2117 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
2119 return ret;
2122 static bool call_OpenPrinterEx(struct torture_context *tctx,
2123 struct dcerpc_pipe *p,
2124 const char *name,
2125 struct spoolss_DeviceMode *devmode,
2126 struct policy_handle *handle);
2128 static bool test_ClosePrinter(struct torture_context *tctx,
2129 struct dcerpc_binding_handle *b,
2130 struct policy_handle *handle);
2132 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2133 struct dcerpc_pipe *p,
2134 struct policy_handle *handle,
2135 const char *name)
2137 union spoolss_PrinterInfo info;
2138 struct spoolss_DeviceMode *devmode;
2139 struct spoolss_DeviceMode *devmode2;
2140 struct policy_handle handle_devmode;
2141 struct dcerpc_binding_handle *b = p->binding_handle;
2143 /* simply compare level8 and level2 devmode */
2145 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2147 devmode = info.info8.devmode;
2149 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2151 devmode2 = info.info2.devmode;
2153 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2154 "DM level 8 != DM level 2");
2157 /* set devicemode level 8 and see if it persists */
2159 devmode->copies = 93;
2160 devmode->formname = talloc_strdup(tctx, "Legal");
2162 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2164 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2166 devmode2 = info.info8.devmode;
2168 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2169 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2171 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2173 devmode2 = info.info2.devmode;
2175 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2176 "modified DM level 8 != DM level 2");
2179 /* set devicemode level 2 and see if it persists */
2181 devmode->copies = 39;
2182 devmode->formname = talloc_strdup(tctx, "Executive");
2184 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2186 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2188 devmode2 = info.info8.devmode;
2190 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2191 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2193 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2195 devmode2 = info.info2.devmode;
2197 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2198 "modified DM level 8 != DM level 2");
2201 /* check every single bit in public part of devicemode */
2203 torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2204 "failed to set every single devicemode component");
2207 /* change formname upon open and see if it persists in getprinter calls */
2209 devmode->formname = talloc_strdup(tctx, "A4");
2210 devmode->copies = 42;
2212 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2213 "failed to open printer handle");
2215 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2217 devmode2 = info.info8.devmode;
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 8 get: %s\n", devmode2->devicename);
2226 if (strequal(devmode->formname, devmode2->formname)) {
2227 torture_warning(tctx, "formname are 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 8 get: %s\n", devmode2->formname);
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 8 get: %d\n", devmode2->copies);
2240 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2242 devmode2 = info.info2.devmode;
2244 if (strequal(devmode->devicename, devmode2->devicename)) {
2245 torture_warning(tctx, "devicenames are the same\n");
2246 } else {
2247 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2248 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2251 if (strequal(devmode->formname, devmode2->formname)) {
2252 torture_warning(tctx, "formname is the same\n");
2253 } else {
2254 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2255 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2258 if (devmode->copies == devmode2->copies) {
2259 torture_warning(tctx, "copies are the same\n");
2260 } else {
2261 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2262 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2265 test_ClosePrinter(tctx, b, &handle_devmode);
2267 return true;
2271 * wrapper call that saves original devmode, runs tests, and restores devmode
2274 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2275 struct dcerpc_pipe *p,
2276 struct policy_handle *handle,
2277 const char *name)
2279 union spoolss_PrinterInfo info;
2280 struct spoolss_DeviceMode *devmode;
2281 bool ret = true;
2282 struct dcerpc_binding_handle *b = p->binding_handle;
2284 torture_comment(tctx, "Testing Printer Devicemodes\n");
2286 /* save original devmode */
2288 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2289 "failed to get initial global devicemode");
2291 devmode = info.info8.devmode;
2293 /* run tests */
2295 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2297 /* restore original devmode */
2299 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2300 "failed to restore initial global device mode");
2302 torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2303 ret ? "succeeded" : "failed");
2306 return ret;
2309 static bool test_ClosePrinter(struct torture_context *tctx,
2310 struct dcerpc_binding_handle *b,
2311 struct policy_handle *handle)
2313 NTSTATUS status;
2314 struct spoolss_ClosePrinter r;
2316 r.in.handle = handle;
2317 r.out.handle = handle;
2319 torture_comment(tctx, "Testing ClosePrinter\n");
2321 status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2322 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2323 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2325 return true;
2328 static bool test_GetForm_args(struct torture_context *tctx,
2329 struct dcerpc_binding_handle *b,
2330 struct policy_handle *handle,
2331 const char *form_name,
2332 uint32_t level,
2333 union spoolss_FormInfo *info_p)
2335 NTSTATUS status;
2336 struct spoolss_GetForm r;
2337 uint32_t needed;
2339 r.in.handle = handle;
2340 r.in.form_name = form_name;
2341 r.in.level = level;
2342 r.in.buffer = NULL;
2343 r.in.offered = 0;
2344 r.out.needed = &needed;
2346 torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2348 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2349 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2351 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2352 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2353 r.in.buffer = &blob;
2354 r.in.offered = needed;
2355 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2356 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2358 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2360 torture_assert(tctx, r.out.info, "No form info returned");
2363 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2365 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2367 if (info_p) {
2368 *info_p = *r.out.info;
2371 return true;
2374 static bool test_GetForm(struct torture_context *tctx,
2375 struct dcerpc_binding_handle *b,
2376 struct policy_handle *handle,
2377 const char *form_name,
2378 uint32_t level)
2380 return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2383 static bool test_EnumForms(struct torture_context *tctx,
2384 struct dcerpc_binding_handle *b,
2385 struct policy_handle *handle,
2386 bool print_server,
2387 uint32_t level,
2388 uint32_t *count_p,
2389 union spoolss_FormInfo **info_p)
2391 struct spoolss_EnumForms r;
2392 uint32_t needed;
2393 uint32_t count;
2394 union spoolss_FormInfo *info;
2396 r.in.handle = handle;
2397 r.in.level = level;
2398 r.in.buffer = NULL;
2399 r.in.offered = 0;
2400 r.out.needed = &needed;
2401 r.out.count = &count;
2402 r.out.info = &info;
2404 torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2406 torture_assert_ntstatus_ok(tctx,
2407 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2408 "EnumForms failed");
2410 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2411 torture_skip(tctx, "EnumForms level 2 not supported");
2414 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2415 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2418 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2419 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2420 r.in.buffer = &blob;
2421 r.in.offered = needed;
2423 torture_assert_ntstatus_ok(tctx,
2424 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2425 "EnumForms failed");
2427 torture_assert(tctx, info, "No forms returned");
2430 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2432 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2434 if (info_p) {
2435 *info_p = info;
2437 if (count_p) {
2438 *count_p = count;
2441 return true;
2444 static bool test_EnumForms_all(struct torture_context *tctx,
2445 struct dcerpc_binding_handle *b,
2446 struct policy_handle *handle,
2447 bool print_server)
2449 uint32_t levels[] = { 1, 2 };
2450 int i, j;
2452 for (i=0; i<ARRAY_SIZE(levels); i++) {
2454 uint32_t count = 0;
2455 union spoolss_FormInfo *info = NULL;
2457 torture_assert(tctx,
2458 test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2459 "failed to enum forms");
2461 for (j = 0; j < count; j++) {
2462 if (!print_server) {
2463 torture_assert(tctx,
2464 test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2465 "failed to get form");
2470 return true;
2473 static bool test_EnumForms_find_one(struct torture_context *tctx,
2474 struct dcerpc_binding_handle *b,
2475 struct policy_handle *handle,
2476 bool print_server,
2477 const char *form_name)
2479 union spoolss_FormInfo *info;
2480 uint32_t count;
2481 bool found = false;
2482 int i;
2484 torture_assert(tctx,
2485 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2486 "failed to enumerate forms");
2488 for (i=0; i<count; i++) {
2489 if (strequal(form_name, info[i].info1.form_name)) {
2490 found = true;
2491 break;
2495 return found;
2498 static bool test_DeleteForm(struct torture_context *tctx,
2499 struct dcerpc_binding_handle *b,
2500 struct policy_handle *handle,
2501 const char *form_name,
2502 WERROR expected_result)
2504 struct spoolss_DeleteForm r;
2506 r.in.handle = handle;
2507 r.in.form_name = form_name;
2509 torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2511 torture_assert_ntstatus_ok(tctx,
2512 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2513 "DeleteForm failed");
2514 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2515 "DeleteForm gave unexpected result");
2516 if (W_ERROR_IS_OK(r.out.result)) {
2517 torture_assert_ntstatus_ok(tctx,
2518 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2519 "2nd DeleteForm failed");
2520 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2521 "2nd DeleteForm failed");
2524 return true;
2527 static bool test_AddForm(struct torture_context *tctx,
2528 struct dcerpc_binding_handle *b,
2529 struct policy_handle *handle,
2530 uint32_t level,
2531 union spoolss_AddFormInfo *info,
2532 WERROR expected_result)
2534 struct spoolss_AddForm r;
2536 if (level != 1) {
2537 torture_skip(tctx, "only level 1 supported");
2540 r.in.handle = handle;
2541 r.in.level = level;
2542 r.in.info = *info;
2544 torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2545 r.in.info.info1->form_name, r.in.level,
2546 r.in.info.info1->flags);
2548 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2549 "AddForm failed");
2550 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2551 "AddForm gave unexpected result");
2553 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2554 "2nd AddForm failed");
2555 if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2556 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2557 "2nd AddForm gave unexpected result");
2558 } else {
2559 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2560 "2nd AddForm gave unexpected result");
2563 return true;
2566 static bool test_SetForm(struct torture_context *tctx,
2567 struct dcerpc_binding_handle *b,
2568 struct policy_handle *handle,
2569 const char *form_name,
2570 uint32_t level,
2571 union spoolss_AddFormInfo *info)
2573 struct spoolss_SetForm r;
2575 r.in.handle = handle;
2576 r.in.form_name = form_name;
2577 r.in.level = level;
2578 r.in.info = *info;
2580 torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2581 form_name, r.in.level);
2583 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2584 "SetForm failed");
2586 torture_assert_werr_ok(tctx, r.out.result,
2587 "SetForm failed");
2589 return true;
2592 static bool test_GetForm_winreg(struct torture_context *tctx,
2593 struct dcerpc_binding_handle *b,
2594 struct policy_handle *handle,
2595 const char *key_name,
2596 const char *form_name,
2597 enum winreg_Type *w_type,
2598 uint32_t *w_size,
2599 uint32_t *w_length,
2600 uint8_t **w_data);
2602 static bool test_Forms_args(struct torture_context *tctx,
2603 struct dcerpc_binding_handle *b,
2604 struct policy_handle *handle,
2605 bool print_server,
2606 const char *printer_name,
2607 struct dcerpc_binding_handle *winreg_handle,
2608 struct policy_handle *hive_handle,
2609 const char *form_name,
2610 struct spoolss_AddFormInfo1 *info1,
2611 WERROR expected_add_result,
2612 WERROR expected_delete_result)
2614 union spoolss_FormInfo info;
2615 union spoolss_AddFormInfo add_info;
2617 enum winreg_Type w_type;
2618 uint32_t w_size;
2619 uint32_t w_length;
2620 uint8_t *w_data;
2622 add_info.info1 = info1;
2624 torture_assert(tctx,
2625 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2626 "failed to add form");
2628 if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2630 torture_assert(tctx,
2631 test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2632 "failed to get form via winreg");
2634 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2635 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2636 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2637 torture_assert_mem_equal(tctx, &w_data[0], &add_info.info1->size.width, 4, "width mismatch");
2638 torture_assert_mem_equal(tctx, &w_data[4], &add_info.info1->size.height, 4, "height mismatch");
2639 torture_assert_mem_equal(tctx, &w_data[8], &add_info.info1->area.left, 4, "left mismatch");
2640 torture_assert_mem_equal(tctx, &w_data[12], &add_info.info1->area.top, 4, "top mismatch");
2641 torture_assert_mem_equal(tctx, &w_data[16], &add_info.info1->area.right, 4, "right mismatch");
2642 torture_assert_mem_equal(tctx, &w_data[20], &add_info.info1->area.bottom, 4, "bottom mismatch");
2643 /* skip index here */
2644 torture_assert_mem_equal(tctx, &w_data[28], &add_info.info1->flags, 4, "flags mismatch");
2647 if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2648 torture_assert(tctx,
2649 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2650 "failed to get added form");
2652 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2653 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2654 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2655 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2656 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2657 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2658 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2660 if (winreg_handle && hive_handle) {
2661 torture_assert_mem_equal(tctx, &w_data[0], &info.info1.size.width, 4, "width mismatch");
2662 torture_assert_mem_equal(tctx, &w_data[4], &info.info1.size.height, 4, "height mismatch");
2663 torture_assert_mem_equal(tctx, &w_data[8], &info.info1.area.left, 4, "left mismatch");
2664 torture_assert_mem_equal(tctx, &w_data[12], &info.info1.area.top, 4, "top mismatch");
2665 torture_assert_mem_equal(tctx, &w_data[16], &info.info1.area.right, 4, "right mismatch");
2666 torture_assert_mem_equal(tctx, &w_data[20], &info.info1.area.bottom, 4, "bottom mismatch");
2667 /* skip index here */
2668 torture_assert_mem_equal(tctx, &w_data[28], &info.info1.flags, 4, "flags mismatch");
2671 add_info.info1->size.width = 1234;
2673 torture_assert(tctx,
2674 test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2675 "failed to set form");
2676 torture_assert(tctx,
2677 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2678 "failed to get setted form");
2680 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2683 if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2684 torture_assert(tctx,
2685 test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2686 "Newly added form not found in enum call");
2689 torture_assert(tctx,
2690 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2691 "failed to delete form");
2693 return true;
2696 static bool test_Forms(struct torture_context *tctx,
2697 struct dcerpc_binding_handle *b,
2698 struct policy_handle *handle,
2699 bool print_server,
2700 const char *printer_name,
2701 struct dcerpc_binding_handle *winreg_handle,
2702 struct policy_handle *hive_handle)
2704 const struct spoolss_FormSize size = {
2705 .width = 50,
2706 .height = 25
2708 const struct spoolss_FormArea area = {
2709 .left = 5,
2710 .top = 10,
2711 .right = 45,
2712 .bottom = 15
2714 int i;
2716 struct {
2717 struct spoolss_AddFormInfo1 info1;
2718 WERROR expected_add_result;
2719 WERROR expected_delete_result;
2720 } forms[] = {
2722 .info1 = {
2723 .flags = SPOOLSS_FORM_USER,
2724 .form_name = "testform_user",
2725 .size = size,
2726 .area = area,
2728 .expected_add_result = WERR_OK,
2729 .expected_delete_result = WERR_OK
2732 weird, we can add a builtin form but we can never remove it
2733 again - gd
2736 .info1 = {
2737 .flags = SPOOLSS_FORM_BUILTIN,
2738 .form_name = "testform_builtin",
2739 .size = size,
2740 .area = area,
2742 .expected_add_result = WERR_OK,
2743 .expected_delete_result = WERR_INVALID_PARAM,
2747 .info1 = {
2748 .flags = SPOOLSS_FORM_PRINTER,
2749 .form_name = "testform_printer",
2750 .size = size,
2751 .area = area,
2753 .expected_add_result = WERR_OK,
2754 .expected_delete_result = WERR_OK
2757 .info1 = {
2758 .flags = SPOOLSS_FORM_USER,
2759 .form_name = "Letter",
2760 .size = size,
2761 .area = area,
2763 .expected_add_result = WERR_FILE_EXISTS,
2764 .expected_delete_result = WERR_INVALID_PARAM
2767 .info1 = {
2768 .flags = SPOOLSS_FORM_BUILTIN,
2769 .form_name = "Letter",
2770 .size = size,
2771 .area = area,
2773 .expected_add_result = WERR_FILE_EXISTS,
2774 .expected_delete_result = WERR_INVALID_PARAM
2777 .info1 = {
2778 .flags = SPOOLSS_FORM_PRINTER,
2779 .form_name = "Letter",
2780 .size = size,
2781 .area = area,
2783 .expected_add_result = WERR_FILE_EXISTS,
2784 .expected_delete_result = WERR_INVALID_PARAM
2787 .info1 = {
2788 .flags = 12345,
2789 .form_name = "invalid_flags",
2790 .size = size,
2791 .area = area,
2793 .expected_add_result = WERR_INVALID_PARAM,
2794 .expected_delete_result = WERR_INVALID_FORM_NAME
2799 for (i=0; i < ARRAY_SIZE(forms); i++) {
2800 torture_assert(tctx,
2801 test_Forms_args(tctx, b, handle, print_server, printer_name,
2802 winreg_handle, hive_handle,
2803 forms[i].info1.form_name,
2804 &forms[i].info1,
2805 forms[i].expected_add_result,
2806 forms[i].expected_delete_result),
2807 talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2810 return true;
2813 static bool test_EnumPorts_old(struct torture_context *tctx,
2814 struct dcerpc_pipe *p)
2816 NTSTATUS status;
2817 struct spoolss_EnumPorts r;
2818 uint32_t needed;
2819 uint32_t count;
2820 union spoolss_PortInfo *info;
2821 struct dcerpc_binding_handle *b = p->binding_handle;
2823 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2824 dcerpc_server_name(p));
2825 r.in.level = 2;
2826 r.in.buffer = NULL;
2827 r.in.offered = 0;
2828 r.out.needed = &needed;
2829 r.out.count = &count;
2830 r.out.info = &info;
2832 torture_comment(tctx, "Testing EnumPorts\n");
2834 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2836 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2838 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2839 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2840 r.in.buffer = &blob;
2841 r.in.offered = needed;
2843 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2844 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2845 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2847 torture_assert(tctx, info, "No ports returned");
2850 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2852 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2854 return true;
2857 static bool test_AddPort(struct torture_context *tctx,
2858 struct dcerpc_pipe *p)
2860 NTSTATUS status;
2861 struct spoolss_AddPort r;
2862 struct dcerpc_binding_handle *b = p->binding_handle;
2864 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
2865 dcerpc_server_name(p));
2866 r.in.unknown = 0;
2867 r.in.monitor_name = "foo";
2869 torture_comment(tctx, "Testing AddPort\n");
2871 status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
2873 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
2875 /* win2k3 returns WERR_NOT_SUPPORTED */
2877 #if 0
2879 if (!W_ERROR_IS_OK(r.out.result)) {
2880 printf("AddPort failed - %s\n", win_errstr(r.out.result));
2881 return false;
2884 #endif
2886 return true;
2889 static bool test_GetJob_args(struct torture_context *tctx,
2890 struct dcerpc_binding_handle *b,
2891 struct policy_handle *handle,
2892 uint32_t job_id,
2893 uint32_t level,
2894 union spoolss_JobInfo *info_p)
2896 NTSTATUS status;
2897 struct spoolss_GetJob r;
2898 union spoolss_JobInfo info;
2899 uint32_t needed;
2901 r.in.handle = handle;
2902 r.in.job_id = job_id;
2903 r.in.level = level;
2904 r.in.buffer = NULL;
2905 r.in.offered = 0;
2906 r.out.needed = &needed;
2907 r.out.info = &info;
2909 torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
2911 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
2912 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2913 if (level == 0) {
2914 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
2917 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2918 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2919 r.in.buffer = &blob;
2920 r.in.offered = needed;
2922 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
2923 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2926 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
2927 torture_assert(tctx, r.out.info, "No job info returned");
2929 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2931 if (info_p) {
2932 *info_p = *r.out.info;
2935 return true;
2938 static bool test_GetJob(struct torture_context *tctx,
2939 struct dcerpc_binding_handle *b,
2940 struct policy_handle *handle,
2941 uint32_t job_id)
2943 uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
2944 uint32_t i;
2946 for (i=0; i < ARRAY_SIZE(levels); i++) {
2947 torture_assert(tctx,
2948 test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
2949 "GetJob failed");
2952 return true;
2955 static bool test_SetJob(struct torture_context *tctx,
2956 struct dcerpc_binding_handle *b,
2957 struct policy_handle *handle,
2958 uint32_t job_id,
2959 struct spoolss_JobInfoContainer *ctr,
2960 enum spoolss_JobControl command)
2962 NTSTATUS status;
2963 struct spoolss_SetJob r;
2965 r.in.handle = handle;
2966 r.in.job_id = job_id;
2967 r.in.ctr = ctr;
2968 r.in.command = command;
2970 switch (command) {
2971 case SPOOLSS_JOB_CONTROL_PAUSE:
2972 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
2973 break;
2974 case SPOOLSS_JOB_CONTROL_RESUME:
2975 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
2976 break;
2977 case SPOOLSS_JOB_CONTROL_CANCEL:
2978 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
2979 break;
2980 case SPOOLSS_JOB_CONTROL_RESTART:
2981 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
2982 break;
2983 case SPOOLSS_JOB_CONTROL_DELETE:
2984 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
2985 break;
2986 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
2987 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
2988 break;
2989 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
2990 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
2991 break;
2992 case SPOOLSS_JOB_CONTROL_RETAIN:
2993 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
2994 break;
2995 case SPOOLSS_JOB_CONTROL_RELEASE:
2996 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
2997 break;
2998 default:
2999 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3000 break;
3003 status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3004 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3005 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3007 return true;
3010 static bool test_AddJob(struct torture_context *tctx,
3011 struct dcerpc_binding_handle *b,
3012 struct policy_handle *handle)
3014 NTSTATUS status;
3015 struct spoolss_AddJob r;
3016 uint32_t needed;
3018 r.in.level = 0;
3019 r.in.handle = handle;
3020 r.in.offered = 0;
3021 r.out.needed = &needed;
3022 r.in.buffer = r.out.buffer = NULL;
3024 torture_comment(tctx, "Testing AddJob\n");
3026 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3027 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3029 r.in.level = 1;
3031 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3032 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3034 return true;
3038 static bool test_EnumJobs_args(struct torture_context *tctx,
3039 struct dcerpc_binding_handle *b,
3040 struct policy_handle *handle,
3041 uint32_t level,
3042 uint32_t *count_p,
3043 union spoolss_JobInfo **info_p)
3045 NTSTATUS status;
3046 struct spoolss_EnumJobs r;
3047 uint32_t needed;
3048 uint32_t count;
3049 union spoolss_JobInfo *info;
3051 r.in.handle = handle;
3052 r.in.firstjob = 0;
3053 r.in.numjobs = 0xffffffff;
3054 r.in.level = level;
3055 r.in.buffer = NULL;
3056 r.in.offered = 0;
3057 r.out.needed = &needed;
3058 r.out.count = &count;
3059 r.out.info = &info;
3061 torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3063 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3065 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3067 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3068 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3069 r.in.buffer = &blob;
3070 r.in.offered = needed;
3072 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3074 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3075 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3076 torture_assert(tctx, info, "No jobs returned");
3078 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3080 } else {
3081 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3084 if (count_p) {
3085 *count_p = count;
3087 if (info_p) {
3088 *info_p = info;
3091 return true;
3094 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3095 struct dcerpc_binding_handle *b,
3096 struct policy_handle *handle,
3097 uint32_t *job_id)
3099 NTSTATUS status;
3100 struct spoolss_StartDocPrinter s;
3101 struct spoolss_DocumentInfo1 info1;
3102 struct spoolss_StartPagePrinter sp;
3103 struct spoolss_WritePrinter w;
3104 struct spoolss_EndPagePrinter ep;
3105 struct spoolss_EndDocPrinter e;
3106 int i;
3107 uint32_t num_written;
3109 torture_comment(tctx, "Testing StartDocPrinter\n");
3111 s.in.handle = handle;
3112 s.in.level = 1;
3113 s.in.info.info1 = &info1;
3114 s.out.job_id = job_id;
3115 info1.document_name = "TorturePrintJob";
3116 info1.output_file = NULL;
3117 info1.datatype = "RAW";
3119 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3120 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3121 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3123 for (i=1; i < 4; i++) {
3124 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3126 sp.in.handle = handle;
3128 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3129 torture_assert_ntstatus_ok(tctx, status,
3130 "dcerpc_spoolss_StartPagePrinter failed");
3131 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3133 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3135 w.in.handle = handle;
3136 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3137 w.out.num_written = &num_written;
3139 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3140 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3141 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3143 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3145 ep.in.handle = handle;
3147 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3148 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3149 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3152 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3154 e.in.handle = handle;
3156 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3157 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3158 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3160 return true;
3163 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3164 struct dcerpc_binding_handle *b,
3165 struct policy_handle *handle,
3166 uint32_t num_jobs,
3167 uint32_t *job_ids)
3169 uint32_t count;
3170 union spoolss_JobInfo *info = NULL;
3171 int i;
3173 torture_assert(tctx,
3174 test_AddJob(tctx, b, handle),
3175 "AddJob failed");
3177 torture_assert(tctx,
3178 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3179 "EnumJobs level 1 failed");
3181 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3183 for (i=0; i < num_jobs; i++) {
3184 union spoolss_JobInfo ginfo;
3185 const char *document_name;
3186 const char *new_document_name = "any_other_docname";
3187 struct spoolss_JobInfoContainer ctr;
3188 struct spoolss_SetJobInfo1 info1;
3190 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3192 torture_assert(tctx,
3193 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3194 "failed to call test_GetJob");
3196 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3198 document_name = ginfo.info1.document_name;
3200 info1.job_id = ginfo.info1.job_id;
3201 info1.printer_name = ginfo.info1.printer_name;
3202 info1.server_name = ginfo.info1.server_name;
3203 info1.user_name = ginfo.info1.user_name;
3204 info1.document_name = new_document_name;
3205 info1.data_type = ginfo.info1.data_type;
3206 info1.text_status = ginfo.info1.text_status;
3207 info1.status = ginfo.info1.status;
3208 info1.priority = ginfo.info1.priority;
3209 info1.position = ginfo.info1.position;
3210 info1.total_pages = ginfo.info1.total_pages;
3211 info1.pages_printed = ginfo.info1.pages_printed;
3212 info1.submitted = ginfo.info1.submitted;
3214 ctr.level = 1;
3215 ctr.info.info1 = &info1;
3217 torture_assert(tctx,
3218 test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3219 "failed to call test_SetJob level 1");
3221 torture_assert(tctx,
3222 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3223 "failed to call test_GetJob");
3225 if (strequal(ginfo.info1.document_name, document_name)) {
3226 torture_warning(tctx,
3227 talloc_asprintf(tctx, "document_name did *NOT* change from '%s' to '%s'\n",
3228 document_name, new_document_name));
3232 for (i=0; i < num_jobs; i++) {
3233 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3234 torture_warning(tctx, "failed to pause printjob\n");
3236 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3237 torture_warning(tctx, "failed to resume printjob\n");
3241 return true;
3244 static bool test_DoPrintTest(struct torture_context *tctx,
3245 struct dcerpc_binding_handle *b,
3246 struct policy_handle *handle)
3248 bool ret = true;
3249 uint32_t num_jobs = 8;
3250 uint32_t *job_ids;
3251 int i;
3253 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3255 for (i=0; i < num_jobs; i++) {
3256 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
3259 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3261 for (i=0; i < num_jobs; i++) {
3262 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3265 return ret;
3268 static bool test_PausePrinter(struct torture_context *tctx,
3269 struct dcerpc_binding_handle *b,
3270 struct policy_handle *handle)
3272 NTSTATUS status;
3273 struct spoolss_SetPrinter r;
3274 struct spoolss_SetPrinterInfoCtr info_ctr;
3275 struct spoolss_DevmodeContainer devmode_ctr;
3276 struct sec_desc_buf secdesc_ctr;
3278 info_ctr.level = 0;
3279 info_ctr.info.info0 = NULL;
3281 ZERO_STRUCT(devmode_ctr);
3282 ZERO_STRUCT(secdesc_ctr);
3284 r.in.handle = handle;
3285 r.in.info_ctr = &info_ctr;
3286 r.in.devmode_ctr = &devmode_ctr;
3287 r.in.secdesc_ctr = &secdesc_ctr;
3288 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3290 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3292 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3294 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3296 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3298 return true;
3301 static bool test_ResumePrinter(struct torture_context *tctx,
3302 struct dcerpc_binding_handle *b,
3303 struct policy_handle *handle)
3305 NTSTATUS status;
3306 struct spoolss_SetPrinter r;
3307 struct spoolss_SetPrinterInfoCtr info_ctr;
3308 struct spoolss_DevmodeContainer devmode_ctr;
3309 struct sec_desc_buf secdesc_ctr;
3311 info_ctr.level = 0;
3312 info_ctr.info.info0 = NULL;
3314 ZERO_STRUCT(devmode_ctr);
3315 ZERO_STRUCT(secdesc_ctr);
3317 r.in.handle = handle;
3318 r.in.info_ctr = &info_ctr;
3319 r.in.devmode_ctr = &devmode_ctr;
3320 r.in.secdesc_ctr = &secdesc_ctr;
3321 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3323 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3325 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3327 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3329 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3331 return true;
3334 static bool test_GetPrinterData(struct torture_context *tctx,
3335 struct dcerpc_binding_handle *b,
3336 struct policy_handle *handle,
3337 const char *value_name,
3338 enum winreg_Type *type_p,
3339 uint8_t **data_p,
3340 uint32_t *needed_p)
3342 NTSTATUS status;
3343 struct spoolss_GetPrinterData r;
3344 uint32_t needed;
3345 enum winreg_Type type;
3346 union spoolss_PrinterData data;
3348 r.in.handle = handle;
3349 r.in.value_name = value_name;
3350 r.in.offered = 0;
3351 r.out.needed = &needed;
3352 r.out.type = &type;
3353 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3355 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3357 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3358 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3360 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3361 r.in.offered = needed;
3362 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3363 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3364 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3367 torture_assert_werr_ok(tctx, r.out.result,
3368 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3370 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3372 if (type_p) {
3373 *type_p = type;
3376 if (data_p) {
3377 *data_p = r.out.data;
3380 if (needed_p) {
3381 *needed_p = needed;
3384 return true;
3387 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3388 struct dcerpc_pipe *p,
3389 struct policy_handle *handle,
3390 const char *key_name,
3391 const char *value_name,
3392 enum winreg_Type *type_p,
3393 uint8_t **data_p,
3394 uint32_t *needed_p)
3396 NTSTATUS status;
3397 struct spoolss_GetPrinterDataEx r;
3398 enum winreg_Type type;
3399 uint32_t needed;
3400 union spoolss_PrinterData data;
3401 struct dcerpc_binding_handle *b = p->binding_handle;
3403 r.in.handle = handle;
3404 r.in.key_name = key_name;
3405 r.in.value_name = value_name;
3406 r.in.offered = 0;
3407 r.out.type = &type;
3408 r.out.needed = &needed;
3409 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3411 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3412 r.in.key_name, r.in.value_name);
3414 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3415 if (!NT_STATUS_IS_OK(status)) {
3416 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3417 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3419 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3422 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3423 r.in.offered = needed;
3424 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3425 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3426 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3429 torture_assert_werr_ok(tctx, r.out.result,
3430 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3432 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3434 if (type_p) {
3435 *type_p = type;
3438 if (data_p) {
3439 *data_p = r.out.data;
3442 if (needed_p) {
3443 *needed_p = needed;
3446 return true;
3449 static bool test_get_environment(struct torture_context *tctx,
3450 struct dcerpc_binding_handle *b,
3451 struct policy_handle *handle,
3452 const char **architecture)
3454 DATA_BLOB blob;
3455 enum winreg_Type type;
3456 uint8_t *data;
3457 uint32_t needed;
3459 torture_assert(tctx,
3460 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3461 "failed to get Architecture");
3463 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3465 blob = data_blob_const(data, needed);
3466 *architecture = reg_val_data_string(tctx, lp_iconv_convenience(tctx->lp_ctx), REG_SZ, blob);
3468 return true;
3471 static bool test_GetPrinterData_list(struct torture_context *tctx,
3472 struct dcerpc_pipe *p,
3473 struct policy_handle *handle,
3474 const char **architecture)
3476 struct dcerpc_binding_handle *b = p->binding_handle;
3477 const char *list[] = {
3478 "W3SvcInstalled",
3479 "BeepEnabled",
3480 "EventLog",
3481 /* "NetPopup", not on w2k8 */
3482 /* "NetPopupToComputer", not on w2k8 */
3483 "MajorVersion",
3484 "MinorVersion",
3485 "DefaultSpoolDirectory",
3486 "Architecture",
3487 "DsPresent",
3488 "OSVersion",
3489 /* "OSVersionEx", not on s3 */
3490 "DNSMachineName"
3492 int i;
3494 for (i=0; i < ARRAY_SIZE(list); i++) {
3495 enum winreg_Type type, type_ex;
3496 uint8_t *data, *data_ex;
3497 uint32_t needed, needed_ex;
3499 torture_assert(tctx, test_GetPrinterData(tctx, b, handle, list[i], &type, &data, &needed),
3500 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
3501 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
3502 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
3503 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
3504 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
3505 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3507 if (strequal(list[i], "Architecture")) {
3508 if (architecture) {
3509 DATA_BLOB blob = data_blob_const(data, needed);
3510 *architecture = reg_val_data_string(tctx, lp_iconv_convenience(tctx->lp_ctx), REG_SZ, blob);
3515 return true;
3518 static bool test_EnumPrinterData(struct torture_context *tctx,
3519 struct dcerpc_pipe *p,
3520 struct policy_handle *handle,
3521 uint32_t enum_index,
3522 uint32_t value_offered,
3523 uint32_t data_offered,
3524 enum winreg_Type *type_p,
3525 uint32_t *value_needed_p,
3526 uint32_t *data_needed_p,
3527 const char **value_name_p,
3528 uint8_t **data_p,
3529 WERROR *result_p)
3531 struct spoolss_EnumPrinterData r;
3532 uint32_t data_needed;
3533 uint32_t value_needed;
3534 enum winreg_Type type;
3535 struct dcerpc_binding_handle *b = p->binding_handle;
3537 r.in.handle = handle;
3538 r.in.enum_index = enum_index;
3539 r.in.value_offered = value_offered;
3540 r.in.data_offered = data_offered;
3541 r.out.data_needed = &data_needed;
3542 r.out.value_needed = &value_needed;
3543 r.out.type = &type;
3544 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3545 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3547 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3549 torture_assert_ntstatus_ok(tctx,
3550 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
3551 "EnumPrinterData failed");
3553 if (type_p) {
3554 *type_p = type;
3556 if (value_needed_p) {
3557 *value_needed_p = value_needed;
3559 if (data_needed_p) {
3560 *data_needed_p = data_needed;
3562 if (value_name_p) {
3563 *value_name_p = r.out.value_name;
3565 if (data_p) {
3566 *data_p = r.out.data;
3568 if (result_p) {
3569 *result_p = r.out.result;
3572 return true;
3576 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3577 struct dcerpc_pipe *p,
3578 struct policy_handle *handle)
3580 uint32_t enum_index = 0;
3581 enum winreg_Type type;
3582 uint32_t value_needed;
3583 uint32_t data_needed;
3584 uint8_t *data;
3585 const char *value_name;
3586 WERROR result;
3588 torture_comment(tctx, "Testing EnumPrinterData\n");
3590 do {
3591 torture_assert(tctx,
3592 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3593 &type, &value_needed, &data_needed,
3594 &value_name, &data, &result),
3595 "EnumPrinterData failed");
3597 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3598 break;
3601 torture_assert(tctx,
3602 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3603 &type, &value_needed, &data_needed,
3604 &value_name, &data, &result),
3605 "EnumPrinterData failed");
3607 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3608 break;
3611 enum_index++;
3613 } while (W_ERROR_IS_OK(result));
3615 torture_comment(tctx, "EnumPrinterData test succeeded\n");
3617 return true;
3620 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3621 struct dcerpc_binding_handle *b,
3622 struct policy_handle *handle,
3623 const char *key_name,
3624 uint32_t *count_p,
3625 struct spoolss_PrinterEnumValues **info_p)
3627 struct spoolss_EnumPrinterDataEx r;
3628 struct spoolss_PrinterEnumValues *info;
3629 uint32_t needed;
3630 uint32_t count;
3632 r.in.handle = handle;
3633 r.in.key_name = key_name;
3634 r.in.offered = 0;
3635 r.out.needed = &needed;
3636 r.out.count = &count;
3637 r.out.info = &info;
3639 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3641 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3642 "EnumPrinterDataEx failed");
3643 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3644 r.in.offered = needed;
3645 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3646 "EnumPrinterDataEx failed");
3649 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3651 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3653 if (count_p) {
3654 *count_p = count;
3656 if (info_p) {
3657 *info_p = info;
3660 return true;
3663 static bool test_SetPrinterData(struct torture_context *tctx,
3664 struct dcerpc_binding_handle *b,
3665 struct policy_handle *handle,
3666 const char *value_name,
3667 enum winreg_Type type,
3668 uint8_t *data,
3669 uint32_t offered);
3670 static bool test_DeletePrinterData(struct torture_context *tctx,
3671 struct dcerpc_binding_handle *b,
3672 struct policy_handle *handle,
3673 const char *value_name);
3675 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3676 struct dcerpc_pipe *p,
3677 struct policy_handle *handle)
3679 uint32_t count;
3680 struct spoolss_PrinterEnumValues *info;
3681 int i;
3682 uint32_t value_needed, data_needed;
3683 uint32_t value_offered, data_offered;
3684 WERROR result;
3685 struct dcerpc_binding_handle *b = p->binding_handle;
3687 enum winreg_Type type;
3688 DATA_BLOB blob;
3690 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3692 torture_assert(tctx,
3693 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3694 "REG_SZ", "torture_data1", &type, &blob), "");
3696 torture_assert(tctx,
3697 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
3698 "SetPrinterData failed");
3700 blob = data_blob_string_const("torture_data2");
3702 torture_assert(tctx,
3703 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3704 "SetPrinterData failed");
3706 blob = data_blob_talloc(tctx, NULL, 4);
3707 SIVAL(blob.data, 0, 0x11223344);
3709 torture_assert(tctx,
3710 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
3711 "SetPrinterData failed");
3713 torture_assert(tctx,
3714 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
3715 "failed to call EnumPrinterDataEx");
3717 /* get the max sizes for value and data */
3719 torture_assert(tctx,
3720 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3721 NULL, &value_needed, &data_needed,
3722 NULL, NULL, &result),
3723 "EnumPrinterData failed");
3724 torture_assert_werr_ok(tctx, result, "unexpected result");
3726 /* check if the reply from the EnumPrinterData really matches max values */
3728 for (i=0; i < count; i++) {
3729 if (info[i].value_name_len > value_needed) {
3730 torture_fail(tctx,
3731 talloc_asprintf(tctx,
3732 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3733 info[i].value_name_len, value_needed));
3735 if (info[i].data_length > data_needed) {
3736 torture_fail(tctx,
3737 talloc_asprintf(tctx,
3738 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3739 info[i].data_length, data_needed));
3743 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3744 * sort or not sort the replies by value name, we should be able to do
3745 * the following entry comparison */
3747 data_offered = data_needed;
3748 value_offered = value_needed;
3750 for (i=0; i < count; i++) {
3752 const char *value_name;
3753 uint8_t *data;
3755 torture_assert(tctx,
3756 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3757 &type, &value_needed, &data_needed,
3758 &value_name, &data, &result),
3759 "EnumPrinterData failed");
3761 if (i -1 == count) {
3762 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3763 "unexpected result");
3764 break;
3765 } else {
3766 torture_assert_werr_ok(tctx, result, "unexpected result");
3769 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3770 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3771 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
3772 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
3773 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
3776 torture_assert(tctx,
3777 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
3778 "DeletePrinterData failed");
3779 torture_assert(tctx,
3780 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
3781 "DeletePrinterData failed");
3782 torture_assert(tctx,
3783 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
3784 "DeletePrinterData failed");
3786 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
3788 return true;
3791 static bool test_DeletePrinterData(struct torture_context *tctx,
3792 struct dcerpc_binding_handle *b,
3793 struct policy_handle *handle,
3794 const char *value_name)
3796 NTSTATUS status;
3797 struct spoolss_DeletePrinterData r;
3799 r.in.handle = handle;
3800 r.in.value_name = value_name;
3802 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
3803 r.in.value_name);
3805 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
3807 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
3808 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
3810 return true;
3813 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
3814 struct dcerpc_binding_handle *b,
3815 struct policy_handle *handle,
3816 const char *key_name,
3817 const char *value_name)
3819 struct spoolss_DeletePrinterDataEx r;
3821 r.in.handle = handle;
3822 r.in.key_name = key_name;
3823 r.in.value_name = value_name;
3825 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
3826 r.in.key_name, r.in.value_name);
3828 torture_assert_ntstatus_ok(tctx,
3829 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
3830 "DeletePrinterDataEx failed");
3831 torture_assert_werr_ok(tctx, r.out.result,
3832 "DeletePrinterDataEx failed");
3834 return true;
3837 static bool test_DeletePrinterKey(struct torture_context *tctx,
3838 struct dcerpc_binding_handle *b,
3839 struct policy_handle *handle,
3840 const char *key_name)
3842 struct spoolss_DeletePrinterKey r;
3844 r.in.handle = handle;
3845 r.in.key_name = key_name;
3847 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
3849 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
3850 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
3851 return true;
3854 torture_assert_ntstatus_ok(tctx,
3855 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
3856 "DeletePrinterKey failed");
3857 torture_assert_werr_ok(tctx, r.out.result,
3858 "DeletePrinterKey failed");
3860 return true;
3863 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
3864 struct dcerpc_binding_handle *b,
3865 struct policy_handle *handle)
3867 struct winreg_OpenHKLM r;
3869 r.in.system_name = NULL;
3870 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3871 r.out.handle = handle;
3873 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
3875 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
3876 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
3878 return true;
3881 static void init_winreg_String(struct winreg_String *name, const char *s)
3883 name->name = s;
3884 if (s) {
3885 name->name_len = 2 * (strlen_m(s) + 1);
3886 name->name_size = name->name_len;
3887 } else {
3888 name->name_len = 0;
3889 name->name_size = 0;
3893 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
3894 struct dcerpc_binding_handle *b,
3895 struct policy_handle *hive_handle,
3896 const char *keyname,
3897 uint32_t options,
3898 struct policy_handle *key_handle)
3900 struct winreg_OpenKey r;
3902 r.in.parent_handle = hive_handle;
3903 init_winreg_String(&r.in.keyname, keyname);
3904 r.in.options = options;
3905 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3906 r.out.handle = key_handle;
3908 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
3910 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
3911 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
3913 return true;
3916 static bool test_winreg_OpenKey(struct torture_context *tctx,
3917 struct dcerpc_binding_handle *b,
3918 struct policy_handle *hive_handle,
3919 const char *keyname,
3920 struct policy_handle *key_handle)
3922 return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
3923 REG_OPTION_NON_VOLATILE, key_handle);
3926 static bool test_winreg_CloseKey(struct torture_context *tctx,
3927 struct dcerpc_binding_handle *b,
3928 struct policy_handle *handle)
3930 struct winreg_CloseKey r;
3932 r.in.handle = handle;
3933 r.out.handle = handle;
3935 torture_comment(tctx, "Testing winreg_CloseKey\n");
3937 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
3938 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
3940 return true;
3943 bool test_winreg_QueryValue(struct torture_context *tctx,
3944 struct dcerpc_binding_handle *b,
3945 struct policy_handle *handle,
3946 const char *value_name,
3947 enum winreg_Type *type_p,
3948 uint32_t *data_size_p,
3949 uint32_t *data_length_p,
3950 uint8_t **data_p)
3952 struct winreg_QueryValue r;
3953 enum winreg_Type type = REG_NONE;
3954 uint32_t data_size = 0;
3955 uint32_t data_length = 0;
3956 struct winreg_String valuename;
3957 uint8_t *data = NULL;
3959 init_winreg_String(&valuename, value_name);
3961 data = talloc_zero_array(tctx, uint8_t, 0);
3963 r.in.handle = handle;
3964 r.in.value_name = &valuename;
3965 r.in.type = &type;
3966 r.in.data_size = &data_size;
3967 r.in.data_length = &data_length;
3968 r.in.data = data;
3969 r.out.type = &type;
3970 r.out.data = data;
3971 r.out.data_size = &data_size;
3972 r.out.data_length = &data_length;
3974 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
3976 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
3977 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3978 *r.in.data_size = *r.out.data_size;
3979 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
3980 r.in.data = data;
3981 r.out.data = data;
3982 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
3984 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
3986 if (type_p) {
3987 *type_p = *r.out.type;
3989 if (data_size_p) {
3990 *data_size_p = *r.out.data_size;
3992 if (data_length_p) {
3993 *data_length_p = *r.out.data_length;
3995 if (data_p) {
3996 *data_p = r.out.data;
3999 return true;
4002 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4003 struct dcerpc_binding_handle *b,
4004 struct policy_handle *handle,
4005 const char *printer_name,
4006 const char *key_name,
4007 const char *value_name,
4008 enum winreg_Type *w_type,
4009 uint32_t *w_size,
4010 uint32_t *w_length,
4011 uint8_t **w_data)
4013 const char *printer_key;
4014 struct policy_handle key_handle;
4016 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4017 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4019 torture_assert(tctx,
4020 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4022 torture_assert(tctx,
4023 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4025 torture_assert(tctx,
4026 test_winreg_CloseKey(tctx, b, &key_handle), "");
4028 return true;
4031 static bool test_GetForm_winreg(struct torture_context *tctx,
4032 struct dcerpc_binding_handle *b,
4033 struct policy_handle *handle,
4034 const char *key_name,
4035 const char *form_name,
4036 enum winreg_Type *w_type,
4037 uint32_t *w_size,
4038 uint32_t *w_length,
4039 uint8_t **w_data)
4041 struct policy_handle key_handle;
4043 torture_assert(tctx,
4044 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4046 torture_assert(tctx,
4047 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4049 torture_assert(tctx,
4050 test_winreg_CloseKey(tctx, b, &key_handle), "");
4052 return true;
4055 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4056 struct dcerpc_binding_handle *b,
4057 struct policy_handle *handle,
4058 const char *symlink_keyname,
4059 const char *symlink_destination)
4061 /* check if the first key is a symlink to the second key */
4063 enum winreg_Type w_type;
4064 uint32_t w_size;
4065 uint32_t w_length;
4066 uint8_t *w_data;
4067 struct policy_handle key_handle;
4068 DATA_BLOB blob;
4069 const char *str;
4071 if (torture_setting_bool(tctx, "samba3", false)) {
4072 torture_skip(tctx, "skip winreg symlink test against samba");
4075 torture_assert(tctx,
4076 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4077 "failed to open key link");
4079 torture_assert(tctx,
4080 test_winreg_QueryValue(tctx, b, &key_handle,
4081 "SymbolicLinkValue",
4082 &w_type, &w_size, &w_length, &w_data),
4083 "failed to query for 'SymbolicLinkValue' attribute");
4085 torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4087 blob = data_blob(w_data, w_size);
4088 str = reg_val_data_string(tctx, lp_iconv_convenience(tctx->lp_ctx), REG_SZ, blob);
4090 torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4092 torture_assert(tctx,
4093 test_winreg_CloseKey(tctx, b, &key_handle),
4094 "failed to close key link");
4096 return true;
4099 static const char *strip_unc(const char *unc)
4101 char *name;
4103 if (!unc) {
4104 return NULL;
4107 if (unc[0] == '\\' && unc[1] == '\\') {
4108 unc +=2;
4111 name = strchr(unc, '\\');
4112 if (name) {
4113 return name+1;
4116 return unc;
4119 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4120 struct dcerpc_binding_handle *b,
4121 struct policy_handle *handle,
4122 const char *printer_name,
4123 struct dcerpc_binding_handle *winreg_handle,
4124 struct policy_handle *hive_handle)
4126 union spoolss_PrinterInfo info;
4127 const char *keys[] = {
4128 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4129 TOP_LEVEL_PRINT_PRINTERS_KEY
4131 int i;
4132 const char *printername, *sharename;
4134 torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4136 torture_assert(tctx,
4137 test_GetPrinter_level(tctx, b, handle, 2, &info),
4138 "failed to get printer info level 2");
4140 printername = strip_unc(info.info2.printername);
4141 sharename = strip_unc(info.info2.sharename);
4143 #define test_sz(wname, iname) \
4144 do {\
4145 DATA_BLOB blob;\
4146 const char *str;\
4147 enum winreg_Type w_type;\
4148 uint32_t w_size;\
4149 uint32_t w_length;\
4150 uint8_t *w_data;\
4151 torture_assert(tctx,\
4152 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4153 &w_type, &w_size, &w_length, &w_data),\
4154 "failed to query winreg");\
4155 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4156 blob = data_blob(w_data, w_size);\
4157 str = reg_val_data_string(tctx, lp_iconv_convenience(tctx->lp_ctx), REG_SZ, blob);\
4158 if (w_size == 2 && iname == NULL) {\
4159 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4160 } else {\
4161 torture_assert_str_equal(tctx, str, iname,\
4162 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4164 } while(0);
4166 #define test_dword(wname, iname) \
4167 do {\
4168 uint32_t value;\
4169 enum winreg_Type w_type;\
4170 uint32_t w_size;\
4171 uint32_t w_length;\
4172 uint8_t *w_data;\
4173 torture_assert(tctx,\
4174 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4175 &w_type, &w_size, &w_length, &w_data),\
4176 "failed to query winreg");\
4177 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4178 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4179 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4180 value = IVAL(w_data, 0);\
4181 torture_assert_int_equal(tctx, value, iname,\
4182 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4183 } while(0);
4185 #define test_dm(wname, iname) \
4186 do {\
4187 DATA_BLOB blob;\
4188 struct spoolss_DeviceMode dm;\
4189 enum ndr_err_code ndr_err;\
4190 enum winreg_Type w_type;\
4191 uint32_t w_size;\
4192 uint32_t w_length;\
4193 uint8_t *w_data;\
4194 torture_assert(tctx,\
4195 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4196 &w_type, &w_size, &w_length, &w_data),\
4197 "failed to query winreg");\
4198 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4199 blob = data_blob(w_data, w_size);\
4200 ndr_err = ndr_pull_struct_blob(&blob, tctx, lp_iconv_convenience(tctx->lp_ctx), &dm,\
4201 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4202 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4203 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4204 "dm unequal");\
4205 } while(0);
4207 #define test_sd(wname, iname) \
4208 do {\
4209 DATA_BLOB blob;\
4210 struct security_descriptor sd;\
4211 enum ndr_err_code ndr_err;\
4212 enum winreg_Type w_type;\
4213 uint32_t w_size;\
4214 uint32_t w_length;\
4215 uint8_t *w_data;\
4216 torture_assert(tctx,\
4217 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4218 &w_type, &w_size, &w_length, &w_data),\
4219 "failed to query winreg");\
4220 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4221 blob = data_blob(w_data, w_size);\
4222 ndr_err = ndr_pull_struct_blob(&blob, tctx, lp_iconv_convenience(tctx->lp_ctx), &sd,\
4223 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4224 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4225 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4226 "sd unequal");\
4227 } while(0);
4229 #define test_multi_sz(wname, iname) \
4230 do {\
4231 DATA_BLOB blob;\
4232 const char **array;\
4233 enum winreg_Type w_type;\
4234 uint32_t w_size;\
4235 uint32_t w_length;\
4236 uint8_t *w_data;\
4237 int i;\
4238 torture_assert(tctx,\
4239 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4240 &w_type, &w_size, &w_length, &w_data),\
4241 "failed to query winreg");\
4242 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4243 blob = data_blob(w_data, w_size);\
4244 torture_assert(tctx, \
4245 pull_reg_multi_sz(tctx, lp_iconv_convenience(tctx->lp_ctx), &blob, &array),\
4246 "failed to pull multi sz");\
4247 for (i=0; array[i] != NULL; i++) {\
4248 torture_assert_str_equal(tctx, array[i], iname[i],\
4249 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4251 } while(0);
4254 if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4255 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4256 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4258 torture_warning(tctx, "failed to check for winreg symlink");
4262 for (i=0; i < ARRAY_SIZE(keys); i++) {
4264 const char *printer_key;
4265 struct policy_handle key_handle;
4267 printer_key = talloc_asprintf(tctx, "%s\\%s",
4268 keys[i], printer_name);
4270 torture_assert(tctx,
4271 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4273 test_sz("Name", printername);
4274 test_sz("Share Name", sharename);
4275 test_sz("Port", info.info2.portname);
4276 test_sz("Printer Driver", info.info2.drivername);
4277 test_sz("Description", info.info2.comment);
4278 test_sz("Location", info.info2.location);
4279 test_sz("Separator File", info.info2.sepfile);
4280 test_sz("Print Processor", info.info2.printprocessor);
4281 test_sz("Datatype", info.info2.datatype);
4282 test_sz("Parameters", info.info2.parameters);
4283 /* winreg: 0, spoolss not */
4284 /* test_dword("Attributes", info.info2.attributes); */
4285 test_dword("Priority", info.info2.priority);
4286 test_dword("Default Priority", info.info2.defaultpriority);
4287 /* winreg: 60, spoolss: 0 */
4288 /* test_dword("StartTime", info.info2.starttime); */
4289 /* test_dword("UntilTime", info.info2.untiltime); */
4290 /* winreg != spoolss */
4291 /* test_dword("Status", info.info2.status); */
4292 test_dm("Default DevMode", info.info2.devmode);
4293 test_sd("Security", info.info2.secdesc);
4295 torture_assert(tctx,
4296 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4299 #undef test_dm
4300 #undef test_sd
4302 torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4304 return true;
4307 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4308 struct dcerpc_binding_handle *b,
4309 struct policy_handle *handle,
4310 const char *driver_name,
4311 const char *architecture,
4312 uint32_t level,
4313 uint32_t client_major_version,
4314 uint32_t client_minor_version,
4315 union spoolss_DriverInfo *info_p,
4316 WERROR *result);
4318 static const char *strip_path(const char *path)
4320 char *p;
4322 if (path == NULL) {
4323 return NULL;
4326 p = strrchr(path, '\\');
4327 if (p) {
4328 return p+1;
4331 return path;
4334 static const char **strip_paths(const char **path_array)
4336 int i;
4338 if (path_array == NULL) {
4339 return NULL;
4342 for (i=0; path_array[i] != NULL; i++) {
4343 path_array[i] = strip_path(path_array[i]);
4346 return path_array;
4349 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4351 time_t t;
4352 struct tm *tm;
4353 t = nt_time_to_unix(nt);
4354 tm = localtime(&t);
4356 return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4357 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4360 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4362 return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4363 (unsigned)((v >> 48) & 0xFFFF),
4364 (unsigned)((v >> 32) & 0xFFFF),
4365 (unsigned)((v >> 16) & 0xFFFF),
4366 (unsigned)(v & 0xFFFF));
4369 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4370 struct dcerpc_binding_handle *b,
4371 struct policy_handle *handle,
4372 const char *printer_name,
4373 const char *driver_name,
4374 const char *environment,
4375 struct dcerpc_binding_handle *winreg_handle,
4376 struct policy_handle *hive_handle)
4378 WERROR result;
4379 union spoolss_DriverInfo info;
4380 const char *driver_key;
4381 struct policy_handle key_handle;
4383 const char *driver_path;
4384 const char *data_file;
4385 const char *config_file;
4386 const char *help_file;
4387 const char **dependent_files;
4389 const char *driver_date;
4390 const char *inbox_driver_date;
4392 const char *driver_version;
4393 const char *inbox_driver_version;
4395 torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4397 driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4398 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4399 environment,
4401 driver_name);
4403 torture_assert(tctx,
4404 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4405 "failed to open driver key");
4407 if (torture_setting_bool(tctx, "samba3", false)) {
4408 goto try_level3;
4411 torture_assert(tctx,
4412 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, 3, 0, &info, &result),
4413 "failed to get driver info level 8");
4415 if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4416 goto try_level6;
4419 driver_path = strip_path(info.info8.driver_path);
4420 data_file = strip_path(info.info8.data_file);
4421 config_file = strip_path(info.info8.config_file);
4422 help_file = strip_path(info.info8.help_file);
4423 dependent_files = strip_paths(info.info8.dependent_files);
4425 driver_date = driver_winreg_date(tctx, info.info8.driver_date);
4426 inbox_driver_date = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
4428 driver_version = driver_winreg_version(tctx, info.info8.driver_version);
4429 inbox_driver_version = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
4431 test_sz("Configuration File", config_file);
4432 test_sz("Data File", data_file);
4433 test_sz("Datatype", info.info8.default_datatype);
4434 test_sz("Driver", driver_path);
4435 test_sz("DriverDate", driver_date);
4436 test_sz("DriverVersion", driver_version);
4437 test_sz("HardwareID", info.info8.hardware_id);
4438 test_sz("Help File", help_file);
4439 test_sz("InfPath", info.info8.inf_path);
4440 test_sz("Manufacturer", info.info8.manufacturer_name);
4441 test_sz("MinInboxDriverVerDate", inbox_driver_date);
4442 test_sz("MinInboxDriverVerVersion", inbox_driver_version);
4443 test_sz("Monitor", info.info8.monitor_name);
4444 test_sz("OEM URL", info.info8.manufacturer_url);
4445 test_sz("Print Processor", info.info8.print_processor);
4446 test_sz("Provider", info.info8.provider);
4447 test_sz("VendorSetup", info.info8.vendor_setup);
4448 test_multi_sz("ColorProfiles", info.info8.color_profiles);
4449 test_multi_sz("Dependent Files", dependent_files);
4450 test_multi_sz("CoreDependencies", info.info8.core_driver_dependencies);
4451 test_multi_sz("Previous Names", info.info8.previous_names);
4452 /* test_dword("Attributes", ?); */
4453 test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
4454 test_dword("Version", info.info8.version);
4455 /* test_dword("TempDir", ?); */
4457 try_level6:
4459 torture_assert(tctx,
4460 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, 3, 0, &info, &result),
4461 "failed to get driver info level 6");
4463 driver_path = strip_path(info.info6.driver_path);
4464 data_file = strip_path(info.info6.data_file);
4465 config_file = strip_path(info.info6.config_file);
4466 help_file = strip_path(info.info6.help_file);
4467 dependent_files = strip_paths(info.info6.dependent_files);
4469 driver_date = driver_winreg_date(tctx, info.info6.driver_date);
4471 driver_version = driver_winreg_version(tctx, info.info6.driver_version);
4473 test_sz("Configuration File", config_file);
4474 test_sz("Data File", data_file);
4475 test_sz("Datatype", info.info6.default_datatype);
4476 test_sz("Driver", driver_path);
4477 test_sz("DriverDate", driver_date);
4478 test_sz("DriverVersion", driver_version);
4479 test_sz("HardwareID", info.info6.hardware_id);
4480 test_sz("Help File", help_file);
4481 test_sz("Manufacturer", info.info6.manufacturer_name);
4482 test_sz("Monitor", info.info6.monitor_name);
4483 test_sz("OEM URL", info.info6.manufacturer_url);
4484 test_sz("Provider", info.info6.provider);
4485 test_multi_sz("Dependent Files", dependent_files);
4486 test_multi_sz("Previous Names", info.info6.previous_names);
4487 /* test_dword("Attributes", ?); */
4488 test_dword("Version", info.info6.version);
4489 /* test_dword("TempDir", ?); */
4491 try_level3:
4493 torture_assert(tctx,
4494 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, 3, 0, &info, &result),
4495 "failed to get driver info level 3");
4497 driver_path = strip_path(info.info3.driver_path);
4498 data_file = strip_path(info.info3.data_file);
4499 config_file = strip_path(info.info3.config_file);
4500 help_file = strip_path(info.info3.help_file);
4501 dependent_files = strip_paths(info.info3.dependent_files);
4503 test_sz("Configuration File", config_file);
4504 test_sz("Data File", data_file);
4505 test_sz("Datatype", info.info3.default_datatype);
4506 test_sz("Driver", driver_path);
4507 test_sz("Help File", help_file);
4508 test_sz("Monitor", info.info3.monitor_name);
4509 test_multi_sz("Dependent Files", dependent_files);
4510 /* test_dword("Attributes", ?); */
4511 test_dword("Version", info.info3.version);
4512 /* test_dword("TempDir", ?); */
4515 torture_assert(tctx,
4516 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4518 torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
4520 return true;
4523 #undef test_sz
4524 #undef test_dword
4526 static bool test_SetPrinterData(struct torture_context *tctx,
4527 struct dcerpc_binding_handle *b,
4528 struct policy_handle *handle,
4529 const char *value_name,
4530 enum winreg_Type type,
4531 uint8_t *data,
4532 uint32_t offered)
4534 struct spoolss_SetPrinterData r;
4536 r.in.handle = handle;
4537 r.in.value_name = value_name;
4538 r.in.type = type;
4539 r.in.data = data;
4540 r.in.offered = offered;
4542 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
4543 r.in.value_name);
4545 torture_assert_ntstatus_ok(tctx,
4546 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
4547 "SetPrinterData failed");
4548 torture_assert_werr_ok(tctx, r.out.result,
4549 "SetPrinterData failed");
4551 return true;
4554 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
4555 struct dcerpc_binding_handle *b,
4556 struct policy_handle *handle,
4557 const char *printer_name,
4558 struct dcerpc_binding_handle *winreg_handle,
4559 struct policy_handle *hive_handle)
4561 const char *values[] = {
4562 "spootyfoot",
4563 "spooty\\foot",
4564 #if 0
4565 /* FIXME: not working with s3 atm. */
4566 "spooty,foot",
4567 "spooty,fo,ot",
4568 #endif
4569 "spooty foot",
4570 #if 0
4571 /* FIXME: not working with s3 atm. */
4572 "spooty\\fo,ot",
4573 "spooty,fo\\ot"
4574 #endif
4576 int i;
4578 for (i=0; i < ARRAY_SIZE(values); i++) {
4580 enum winreg_Type type;
4581 DATA_BLOB blob;
4582 uint8_t *data;
4583 uint32_t needed;
4585 torture_assert(tctx,
4586 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
4587 "REG_SZ", "dog", &type, &blob), "");
4589 torture_assert(tctx,
4590 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
4591 "SetPrinterData failed");
4593 torture_assert(tctx,
4594 test_GetPrinterData(tctx, b, handle, values[i], &type, &data, &needed),
4595 "GetPrinterData failed");
4597 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
4598 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
4599 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
4601 if (winreg_handle && hive_handle) {
4603 enum winreg_Type w_type;
4604 uint32_t w_size;
4605 uint32_t w_length;
4606 uint8_t *w_data;
4608 torture_assert(tctx,
4609 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4610 printer_name, "PrinterDriverData", values[i],
4611 &w_type, &w_size, &w_length, &w_data), "");
4613 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
4614 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
4615 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
4616 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
4619 torture_assert(tctx,
4620 test_DeletePrinterData(tctx, b, handle, values[i]),
4621 "DeletePrinterData failed");
4624 return true;
4628 static bool test_EnumPrinterKey(struct torture_context *tctx,
4629 struct dcerpc_binding_handle *b,
4630 struct policy_handle *handle,
4631 const char *key_name,
4632 const char ***array);
4634 static bool test_SetPrinterDataEx(struct torture_context *tctx,
4635 struct dcerpc_binding_handle *b,
4636 struct policy_handle *handle,
4637 const char *key_name,
4638 const char *value_name,
4639 enum winreg_Type type,
4640 uint8_t *data,
4641 uint32_t offered)
4643 NTSTATUS status;
4644 struct spoolss_SetPrinterDataEx r;
4646 r.in.handle = handle;
4647 r.in.key_name = key_name;
4648 r.in.value_name = value_name;
4649 r.in.type = type;
4650 r.in.data = data;
4651 r.in.offered = offered;
4653 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
4654 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
4656 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
4658 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
4659 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
4661 return true;
4664 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
4665 struct dcerpc_pipe *p,
4666 struct policy_handle *handle,
4667 const char *printername,
4668 struct dcerpc_binding_handle *winreg_handle,
4669 struct policy_handle *hive_handle)
4671 struct dcerpc_binding_handle *b = p->binding_handle;
4672 const char *value_name = "dog";
4673 const char *keys[] = {
4674 "torturedataex",
4675 "torture data ex",
4676 #if 0
4677 /* FIXME: not working with s3 atm. */
4678 "torturedataex_with_subkey\\subkey",
4679 "torturedataex_with_subkey\\subkey:0",
4680 "torturedataex_with_subkey\\subkey:1",
4681 "torturedataex_with_subkey\\subkey\\subsubkey",
4682 "torturedataex_with_subkey\\subkey\\subsubkey:0",
4683 "torturedataex_with_subkey\\subkey\\subsubkey:1",
4684 #endif
4685 "torture,data",
4686 #if 0
4687 /* FIXME: not working with s3 atm. */
4689 "torture,data,ex",
4690 "torture,data\\ex",
4691 "torture\\data,ex"
4692 #endif
4694 enum winreg_Type types[] = {
4695 REG_SZ,
4696 REG_MULTI_SZ,
4697 REG_DWORD,
4698 REG_BINARY
4700 const char *str = "abcdefghijklmnopqrstuvwxzy";
4701 int i, t, s;
4704 for (i=0; i < ARRAY_SIZE(keys); i++) {
4705 for (t=0; t < ARRAY_SIZE(types); t++) {
4706 for (s=0; s < strlen(str); s++) {
4708 char *c;
4709 const char *key;
4710 enum winreg_Type type;
4711 const char *string = talloc_strndup(tctx, str, s);
4712 DATA_BLOB blob = data_blob_string_const(string);
4713 const char **subkeys;
4714 DATA_BLOB data;
4715 uint8_t *data_out;
4716 uint32_t needed, offered = 0;
4717 uint32_t ecount;
4718 struct spoolss_PrinterEnumValues *einfo;
4720 if (types[t] == REG_DWORD) {
4721 s = 0xffff;
4724 if (torture_setting_bool(tctx, "samba3", false)) {
4725 if ((types[t] == REG_MULTI_SZ) && s == 0) {
4726 torture_warning(tctx, "samba3 does not handle 4 byte emtpy REG_MULTI_SZ buffers");
4727 continue;
4731 switch (types[t]) {
4732 case REG_BINARY:
4733 data = blob;
4734 offered = blob.length;
4735 break;
4736 case REG_DWORD:
4737 data = data_blob_talloc(tctx, NULL, 4);
4738 SIVAL(data.data, 0, 0x12345678);
4739 offered = 4;
4740 break;
4741 case REG_SZ:
4742 torture_assert(tctx,
4743 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
4744 "REG_SZ", string, &type, &data), "");
4745 offered = data.length;
4746 /*strlen_m_term(data.string)*2;*/
4747 break;
4748 case REG_MULTI_SZ:
4749 torture_assert(tctx,
4750 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
4751 "REG_SZ", string, &type, &data), "");
4752 torture_assert(tctx, data_blob_realloc(tctx, &data, data.length + 2), "");
4753 memset(&data.data[data.length - 2], '\0', 2);
4754 offered = data.length;
4755 break;
4756 default:
4757 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
4760 torture_assert(tctx,
4761 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, types[t], data.data, offered),
4762 "failed to call SetPrinterDataEx");
4764 torture_assert(tctx,
4765 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &data_out, &needed),
4766 "failed to call GetPrinterDataEx");
4768 torture_assert(tctx,
4769 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
4770 "failed to call EnumPrinterDataEx");
4772 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
4773 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
4774 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
4776 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
4777 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
4778 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
4779 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
4780 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
4781 if (einfo[0].data_length > 0) {
4782 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
4785 if (winreg_handle && hive_handle) {
4786 enum winreg_Type w_type;
4787 uint32_t w_size;
4788 uint32_t w_length;
4789 uint8_t *w_data;
4791 torture_assert(tctx,
4792 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4793 printername, keys[i], value_name,
4794 &w_type, &w_size, &w_length, &w_data), "");
4796 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
4797 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
4798 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
4799 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
4802 key = talloc_strdup(tctx, keys[i]);
4804 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
4805 return false;
4808 c = strchr(key, '\\');
4809 if (c) {
4810 int k;
4812 /* we have subkeys */
4814 *c = 0;
4816 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
4817 return false;
4820 for (k=0; subkeys && subkeys[k]; k++) {
4822 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
4824 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
4825 return false;
4829 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4830 return false;
4833 } else {
4834 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4835 return false;
4842 return true;
4845 static bool test_PrinterData_winreg(struct torture_context *tctx,
4846 struct dcerpc_pipe *p,
4847 struct policy_handle *handle,
4848 const char *printer_name)
4850 struct dcerpc_binding_handle *b = p->binding_handle;
4851 struct dcerpc_pipe *p2;
4852 bool ret = true;
4853 struct policy_handle hive_handle;
4854 struct dcerpc_binding_handle *b2;
4856 torture_assert_ntstatus_ok(tctx,
4857 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4858 "could not open winreg pipe");
4859 b2 = p2->binding_handle;
4861 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4863 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
4864 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
4866 test_winreg_CloseKey(tctx, b2, &hive_handle);
4868 talloc_free(p2);
4870 return ret;
4873 static bool test_Forms_winreg(struct torture_context *tctx,
4874 struct dcerpc_binding_handle *b,
4875 struct policy_handle *handle,
4876 bool print_server,
4877 const char *printer_name)
4879 struct dcerpc_pipe *p2;
4880 bool ret = true;
4881 struct policy_handle hive_handle;
4882 struct dcerpc_binding_handle *b2;
4884 torture_assert_ntstatus_ok(tctx,
4885 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4886 "could not open winreg pipe");
4887 b2 = p2->binding_handle;
4889 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4891 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
4893 test_winreg_CloseKey(tctx, b2, &hive_handle);
4895 talloc_free(p2);
4897 return ret;
4900 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
4901 struct dcerpc_pipe *p,
4902 struct policy_handle *handle,
4903 const char *printer_name)
4905 struct dcerpc_binding_handle *b = p->binding_handle;
4906 struct dcerpc_pipe *p2;
4907 bool ret = true;
4908 struct policy_handle hive_handle;
4909 struct dcerpc_binding_handle *b2;
4911 torture_assert_ntstatus_ok(tctx,
4912 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4913 "could not open winreg pipe");
4914 b2 = p2->binding_handle;
4916 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4918 ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
4920 test_winreg_CloseKey(tctx, b2, &hive_handle);
4922 talloc_free(p2);
4924 return ret;
4927 static bool test_DriverInfo_winreg(struct torture_context *tctx,
4928 struct dcerpc_pipe *p,
4929 struct policy_handle *handle,
4930 const char *printer_name,
4931 const char *driver_name,
4932 const char *environment)
4934 struct dcerpc_binding_handle *b = p->binding_handle;
4935 struct dcerpc_pipe *p2;
4936 bool ret = true;
4937 struct policy_handle hive_handle;
4938 struct dcerpc_binding_handle *b2;
4940 torture_assert_ntstatus_ok(tctx,
4941 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4942 "could not open winreg pipe");
4943 b2 = p2->binding_handle;
4945 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4947 ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, b2, &hive_handle);
4949 test_winreg_CloseKey(tctx, b2, &hive_handle);
4951 talloc_free(p2);
4953 return ret;
4956 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
4957 struct dcerpc_binding_handle *b,
4958 struct policy_handle *handle,
4959 uint32_t *change_id)
4961 enum winreg_Type type;
4962 uint8_t *data;
4963 uint32_t needed;
4965 torture_assert(tctx,
4966 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
4967 "failed to call GetPrinterData");
4969 torture_assert(tctx, type == REG_DWORD, "unexpected type");
4970 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
4972 *change_id = IVAL(data, 0);
4974 return true;
4977 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
4978 struct dcerpc_pipe *p,
4979 struct policy_handle *handle,
4980 uint32_t *change_id)
4982 enum winreg_Type type;
4983 uint8_t *data;
4984 uint32_t needed;
4986 torture_assert(tctx,
4987 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
4988 "failed to call GetPrinterData");
4990 torture_assert(tctx, type == REG_DWORD, "unexpected type");
4991 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
4993 *change_id = IVAL(data, 0);
4995 return true;
4998 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
4999 struct dcerpc_binding_handle *b,
5000 struct policy_handle *handle,
5001 uint32_t *change_id)
5003 union spoolss_PrinterInfo info;
5005 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5006 "failed to query Printer level 0");
5008 *change_id = info.info0.change_id;
5010 return true;
5013 static bool test_ChangeID(struct torture_context *tctx,
5014 struct dcerpc_pipe *p,
5015 struct policy_handle *handle)
5017 uint32_t change_id, change_id_ex, change_id_info;
5018 uint32_t change_id2, change_id_ex2, change_id_info2;
5019 union spoolss_PrinterInfo info;
5020 const char *comment;
5021 struct dcerpc_binding_handle *b = p->binding_handle;
5023 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5025 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5026 "failed to query for ChangeID");
5027 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5028 "failed to query for ChangeID");
5029 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5030 "failed to query for ChangeID");
5032 torture_assert_int_equal(tctx, change_id, change_id_ex,
5033 "change_ids should all be equal");
5034 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5035 "change_ids should all be equal");
5038 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
5040 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5041 "failed to query for ChangeID");
5042 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5043 "failed to query Printer level 2");
5044 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5045 "failed to query for ChangeID");
5046 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5047 "failed to query for ChangeID");
5048 torture_assert_int_equal(tctx, change_id, change_id_ex,
5049 "change_id should not have changed");
5050 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5051 "change_id should not have changed");
5054 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
5056 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5057 "failed to query for ChangeID");
5058 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5059 "failed to query for ChangeID");
5060 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5061 "failed to query for ChangeID");
5062 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5063 "failed to query Printer level 2");
5064 comment = talloc_strdup(tctx, info.info2.comment);
5067 struct spoolss_SetPrinterInfoCtr info_ctr;
5068 struct spoolss_DevmodeContainer devmode_ctr;
5069 struct sec_desc_buf secdesc_ctr;
5070 union spoolss_SetPrinterInfo sinfo;
5072 ZERO_STRUCT(info_ctr);
5073 ZERO_STRUCT(devmode_ctr);
5074 ZERO_STRUCT(secdesc_ctr);
5077 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5078 sinfo.info2->comment = "torture_comment";
5080 info_ctr.level = 2;
5081 info_ctr.info = sinfo;
5083 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5084 "failed to call SetPrinter");
5086 sinfo.info2->comment = comment;
5088 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5089 "failed to call SetPrinter");
5093 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5094 "failed to query for ChangeID");
5095 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5096 "failed to query for ChangeID");
5097 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5098 "failed to query for ChangeID");
5100 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5101 "change_ids should all be equal");
5102 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5103 "change_ids should all be equal");
5105 torture_assert(tctx, (change_id < change_id2),
5106 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5107 change_id2, change_id));
5108 torture_assert(tctx, (change_id_ex < change_id_ex2),
5109 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5110 change_id_ex2, change_id_ex));
5111 torture_assert(tctx, (change_id_info < change_id_info2),
5112 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5113 change_id_info2, change_id_info));
5115 torture_comment(tctx, "ChangeID tests succeeded\n\n");
5117 return true;
5120 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5121 struct dcerpc_pipe *p,
5122 struct policy_handle *handle)
5124 NTSTATUS status;
5125 struct dcerpc_binding *b;
5126 struct dcerpc_pipe *p2;
5127 struct spoolss_ClosePrinter cp;
5129 /* only makes sense on SMB */
5130 if (p->conn->transport.transport != NCACN_NP) {
5131 return true;
5134 torture_comment(tctx, "Testing close on secondary pipe\n");
5136 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
5137 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
5139 status = dcerpc_secondary_connection(p, &p2, b);
5140 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
5142 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
5143 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
5145 cp.in.handle = handle;
5146 cp.out.handle = handle;
5148 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
5149 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
5150 "ERROR: Allowed close on secondary connection");
5152 talloc_free(p2);
5154 return true;
5157 static bool test_OpenPrinter_badname(struct torture_context *tctx,
5158 struct dcerpc_binding_handle *b, const char *name)
5160 NTSTATUS status;
5161 struct spoolss_OpenPrinter op;
5162 struct spoolss_OpenPrinterEx opEx;
5163 struct policy_handle handle;
5164 bool ret = true;
5166 op.in.printername = name;
5167 op.in.datatype = NULL;
5168 op.in.devmode_ctr.devmode= NULL;
5169 op.in.access_mask = 0;
5170 op.out.handle = &handle;
5172 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
5174 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
5175 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5176 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
5177 "unexpected result");
5179 if (W_ERROR_IS_OK(op.out.result)) {
5180 ret &=test_ClosePrinter(tctx, b, &handle);
5183 opEx.in.printername = name;
5184 opEx.in.datatype = NULL;
5185 opEx.in.devmode_ctr.devmode = NULL;
5186 opEx.in.access_mask = 0;
5187 opEx.in.level = 1;
5188 opEx.in.userlevel.level1 = NULL;
5189 opEx.out.handle = &handle;
5191 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
5193 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
5194 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5195 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
5196 "unexpected result");
5198 if (W_ERROR_IS_OK(opEx.out.result)) {
5199 ret &=test_ClosePrinter(tctx, b, &handle);
5202 return ret;
5205 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
5206 struct dcerpc_binding_handle *b,
5207 const char *server_name)
5209 const char *badnames[] = {
5210 "__INVALID_PRINTER__",
5211 "\\\\__INVALID_HOST__",
5213 "\\\\\\",
5214 "\\\\\\__INVALID_PRINTER__"
5216 const char *badname;
5217 int i;
5219 for (i=0; i < ARRAY_SIZE(badnames); i++) {
5220 torture_assert(tctx,
5221 test_OpenPrinter_badname(tctx, b, badnames[i]),
5222 "");
5225 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
5226 torture_assert(tctx,
5227 test_OpenPrinter_badname(tctx, b, badname),
5228 "");
5230 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
5231 torture_assert(tctx,
5232 test_OpenPrinter_badname(tctx, b, badname),
5233 "");
5235 return true;
5238 static bool test_OpenPrinter(struct torture_context *tctx,
5239 struct dcerpc_pipe *p,
5240 const char *name,
5241 const char *environment)
5243 NTSTATUS status;
5244 struct spoolss_OpenPrinter r;
5245 struct policy_handle handle;
5246 bool ret = true;
5247 struct dcerpc_binding_handle *b = p->binding_handle;
5249 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
5250 r.in.datatype = NULL;
5251 r.in.devmode_ctr.devmode= NULL;
5252 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5253 r.out.handle = &handle;
5255 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5257 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5259 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5261 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5263 if (!test_GetPrinter(tctx, b, &handle, environment)) {
5264 ret = false;
5267 if (!torture_setting_bool(tctx, "samba3", false)) {
5268 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5269 ret = false;
5273 if (!test_ClosePrinter(tctx, b, &handle)) {
5274 ret = false;
5277 return ret;
5280 static bool call_OpenPrinterEx(struct torture_context *tctx,
5281 struct dcerpc_pipe *p,
5282 const char *name,
5283 struct spoolss_DeviceMode *devmode,
5284 struct policy_handle *handle)
5286 struct spoolss_OpenPrinterEx r;
5287 struct spoolss_UserLevel1 userlevel1;
5288 NTSTATUS status;
5289 struct dcerpc_binding_handle *b = p->binding_handle;
5291 if (name && name[0]) {
5292 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
5293 dcerpc_server_name(p), name);
5294 } else {
5295 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
5296 dcerpc_server_name(p));
5299 r.in.datatype = NULL;
5300 r.in.devmode_ctr.devmode= devmode;
5301 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5302 r.in.level = 1;
5303 r.in.userlevel.level1 = &userlevel1;
5304 r.out.handle = handle;
5306 userlevel1.size = 1234;
5307 userlevel1.client = "hello";
5308 userlevel1.user = "spottyfoot!";
5309 userlevel1.build = 1;
5310 userlevel1.major = 2;
5311 userlevel1.minor = 3;
5312 userlevel1.processor = 4;
5314 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5316 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r);
5318 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5320 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
5322 return true;
5325 static bool test_printer_rename(struct torture_context *tctx,
5326 struct dcerpc_pipe *p,
5327 struct policy_handle *handle,
5328 const char *name)
5330 bool ret = true;
5331 union spoolss_PrinterInfo info;
5332 union spoolss_SetPrinterInfo sinfo;
5333 struct spoolss_SetPrinterInfoCtr info_ctr;
5334 struct spoolss_DevmodeContainer devmode_ctr;
5335 struct sec_desc_buf secdesc_ctr;
5336 const char *printer_name;
5337 const char *printer_name_orig;
5338 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5339 struct policy_handle new_handle;
5340 const char *q;
5341 struct dcerpc_binding_handle *b = p->binding_handle;
5343 ZERO_STRUCT(devmode_ctr);
5344 ZERO_STRUCT(secdesc_ctr);
5346 torture_comment(tctx, "Testing Printer rename operations\n");
5348 torture_assert(tctx,
5349 test_GetPrinter_level(tctx, b, handle, 2, &info),
5350 "failed to call GetPrinter level 2");
5352 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5354 q = strrchr(info.info2.printername, '\\');
5355 if (q) {
5356 torture_warning(tctx,
5357 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5360 torture_assert(tctx,
5361 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5363 sinfo.info2->printername = printer_name_new;
5365 info_ctr.level = 2;
5366 info_ctr.info = sinfo;
5368 torture_assert(tctx,
5369 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5370 "failed to call SetPrinter level 2");
5372 torture_assert(tctx,
5373 test_GetPrinter_level(tctx, b, handle, 2, &info),
5374 "failed to call GetPrinter level 2");
5376 printer_name = talloc_strdup(tctx, info.info2.printername);
5378 q = strrchr(info.info2.printername, '\\');
5379 if (q) {
5380 torture_warning(tctx,
5381 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5382 q++;
5383 printer_name = q;
5386 torture_assert_str_equal(tctx, printer_name, printer_name_new,
5387 "new printer name was not set");
5389 /* samba currently cannot fully rename printers */
5390 if (!torture_setting_bool(tctx, "samba3", false)) {
5391 torture_assert(tctx,
5392 test_OpenPrinter_badname(tctx, b, printer_name_orig),
5393 "still can open printer with oldname after rename");
5394 } else {
5395 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
5398 torture_assert(tctx,
5399 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
5400 "failed to open printer with new name");
5402 torture_assert(tctx,
5403 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
5404 "failed to call GetPrinter level 2");
5406 /* FIXME: we openend with servername! */
5407 printer_name = talloc_asprintf(tctx, "\\\\%s\\%s",
5408 dcerpc_server_name(p), printer_name_new);
5410 torture_assert_str_equal(tctx, info.info2.printername, printer_name,
5411 "new printer name was not set");
5413 torture_assert(tctx,
5414 test_ClosePrinter(tctx, b, &new_handle),
5415 "failed to close printer");
5417 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
5419 return ret;
5423 static bool test_OpenPrinterEx(struct torture_context *tctx,
5424 struct dcerpc_pipe *p,
5425 const char *name,
5426 const char *environment)
5428 struct policy_handle handle;
5429 bool ret = true;
5430 struct dcerpc_binding_handle *b = p->binding_handle;
5432 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
5433 return false;
5436 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
5437 ret = false;
5440 if (!test_GetPrinter(tctx, b, &handle, environment)) {
5441 ret = false;
5444 if (!test_EnumForms_all(tctx, b, &handle, false)) {
5445 ret = false;
5448 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
5449 ret = false;
5452 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
5453 ret = false;
5456 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
5457 ret = false;
5460 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
5461 ret = false;
5464 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
5465 ret = false;
5468 if (!test_printer_keys(tctx, b, &handle)) {
5469 ret = false;
5472 if (!test_PausePrinter(tctx, b, &handle)) {
5473 ret = false;
5476 if (!test_DoPrintTest(tctx, b, &handle)) {
5477 ret = false;
5480 if (!test_ResumePrinter(tctx, b, &handle)) {
5481 ret = false;
5484 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
5485 ret = false;
5488 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
5489 ret = false;
5492 if (!torture_setting_bool(tctx, "samba3", false)) {
5493 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5494 ret = false;
5498 if (!test_ClosePrinter(tctx, b, &handle)) {
5499 ret = false;
5502 return ret;
5505 static bool test_EnumPrinters_old(struct torture_context *tctx,
5506 struct dcerpc_pipe *p,
5507 const char *environment)
5509 struct spoolss_EnumPrinters r;
5510 NTSTATUS status;
5511 uint16_t levels[] = {1, 2, 4, 5};
5512 int i;
5513 bool ret = true;
5514 struct dcerpc_binding_handle *b = p->binding_handle;
5516 for (i=0;i<ARRAY_SIZE(levels);i++) {
5517 union spoolss_PrinterInfo *info;
5518 int j;
5519 uint32_t needed;
5520 uint32_t count;
5522 r.in.flags = PRINTER_ENUM_LOCAL;
5523 r.in.server = "";
5524 r.in.level = levels[i];
5525 r.in.buffer = NULL;
5526 r.in.offered = 0;
5527 r.out.needed = &needed;
5528 r.out.count = &count;
5529 r.out.info = &info;
5531 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
5533 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
5534 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
5536 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5537 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5538 r.in.buffer = &blob;
5539 r.in.offered = needed;
5540 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
5543 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
5545 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
5547 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
5549 if (!info) {
5550 torture_comment(tctx, "No printers returned\n");
5551 return true;
5554 for (j=0;j<count;j++) {
5555 if (r.in.level == 1) {
5556 char *unc = talloc_strdup(tctx, info[j].info1.name);
5557 char *slash, *name;
5558 name = unc;
5559 if (unc[0] == '\\' && unc[1] == '\\') {
5560 unc +=2;
5562 slash = strchr(unc, '\\');
5563 if (slash) {
5564 slash++;
5565 name = slash;
5567 if (!test_OpenPrinter(tctx, p, name, environment)) {
5568 ret = false;
5570 if (!test_OpenPrinterEx(tctx, p, name, environment)) {
5571 ret = false;
5577 return ret;
5580 static bool test_GetPrinterDriver(struct torture_context *tctx,
5581 struct dcerpc_binding_handle *b,
5582 struct policy_handle *handle,
5583 const char *driver_name)
5585 struct spoolss_GetPrinterDriver r;
5586 uint32_t needed;
5588 r.in.handle = handle;
5589 r.in.architecture = "W32X86";
5590 r.in.level = 1;
5591 r.in.buffer = NULL;
5592 r.in.offered = 0;
5593 r.out.needed = &needed;
5595 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
5597 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
5598 "failed to call GetPrinterDriver");
5599 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5600 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5601 r.in.buffer = &blob;
5602 r.in.offered = needed;
5603 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
5604 "failed to call GetPrinterDriver");
5607 torture_assert_werr_ok(tctx, r.out.result,
5608 "failed to call GetPrinterDriver");
5610 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
5612 return true;
5615 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
5616 struct dcerpc_binding_handle *b,
5617 struct policy_handle *handle,
5618 const char *driver_name,
5619 const char *architecture,
5620 uint32_t level,
5621 uint32_t client_major_version,
5622 uint32_t client_minor_version,
5623 union spoolss_DriverInfo *info_p,
5624 WERROR *result_p)
5627 struct spoolss_GetPrinterDriver2 r;
5628 uint32_t needed;
5629 uint32_t server_major_version;
5630 uint32_t server_minor_version;
5632 r.in.handle = handle;
5633 r.in.architecture = architecture;
5634 r.in.client_major_version = client_major_version;
5635 r.in.client_minor_version = client_minor_version;
5636 r.in.buffer = NULL;
5637 r.in.offered = 0;
5638 r.in.level = level;
5639 r.out.needed = &needed;
5640 r.out.server_major_version = &server_major_version;
5641 r.out.server_minor_version = &server_minor_version;
5643 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
5644 driver_name, r.in.level);
5646 torture_assert_ntstatus_ok(tctx,
5647 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
5648 "failed to call GetPrinterDriver2");
5649 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
5650 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5651 r.in.buffer = &blob;
5652 r.in.offered = needed;
5653 torture_assert_ntstatus_ok(tctx,
5654 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
5655 "failed to call GetPrinterDriver2");
5658 if (result_p) {
5659 *result_p = r.out.result;
5662 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
5663 switch (r.in.level) {
5664 case 101:
5665 case 8:
5666 torture_comment(tctx,
5667 "level %d not implemented, not considering as an error\n",
5668 r.in.level);
5669 return true;
5670 default:
5671 break;
5675 torture_assert_werr_ok(tctx, r.out.result,
5676 "failed to call GetPrinterDriver2");
5678 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
5680 if (info_p) {
5681 *info_p = *r.out.info;
5684 return true;
5687 static bool test_GetPrinterDriver2(struct torture_context *tctx,
5688 struct dcerpc_binding_handle *b,
5689 struct policy_handle *handle,
5690 const char *driver_name,
5691 const char *architecture)
5693 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
5694 int i;
5697 for (i=0;i<ARRAY_SIZE(levels);i++) {
5699 torture_assert(tctx,
5700 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
5701 "");
5704 return true;
5707 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
5708 struct dcerpc_pipe *p,
5709 const char *environment)
5711 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
5712 int i;
5713 struct dcerpc_binding_handle *b = p->binding_handle;
5714 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
5716 for (i=0;i<ARRAY_SIZE(levels);i++) {
5718 uint32_t count;
5719 union spoolss_DriverInfo *info;
5721 torture_assert(tctx,
5722 test_EnumPrinterDrivers_args(tctx, b, server_name, environment, levels[i], &count, &info),
5723 "failed to enumerate drivers");
5725 if (!info) {
5726 torture_comment(tctx, "No printer drivers returned\n");
5727 break;
5731 return true;
5734 static bool test_DeletePrinter(struct torture_context *tctx,
5735 struct dcerpc_binding_handle *b,
5736 struct policy_handle *handle)
5738 struct spoolss_DeletePrinter r;
5740 torture_comment(tctx, "Testing DeletePrinter\n");
5742 r.in.handle = handle;
5744 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
5745 "failed to delete printer");
5746 torture_assert_werr_ok(tctx, r.out.result,
5747 "failed to delete printer");
5749 return true;
5752 static bool test_EnumPrinters_findname(struct torture_context *tctx,
5753 struct dcerpc_binding_handle *b,
5754 uint32_t flags,
5755 uint32_t level,
5756 const char *name,
5757 bool *found)
5759 struct spoolss_EnumPrinters e;
5760 uint32_t count;
5761 union spoolss_PrinterInfo *info;
5762 uint32_t needed;
5763 int i;
5765 *found = false;
5767 e.in.flags = flags;
5768 e.in.server = NULL;
5769 e.in.level = level;
5770 e.in.buffer = NULL;
5771 e.in.offered = 0;
5772 e.out.count = &count;
5773 e.out.info = &info;
5774 e.out.needed = &needed;
5776 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
5777 "failed to enum printers");
5779 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
5780 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
5781 e.in.buffer = &blob;
5782 e.in.offered = needed;
5784 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
5785 "failed to enum printers");
5788 torture_assert_werr_ok(tctx, e.out.result,
5789 "failed to enum printers");
5791 for (i=0; i < count; i++) {
5793 const char *current = NULL;
5794 const char *q;
5796 switch (level) {
5797 case 1:
5798 current = info[i].info1.name;
5799 break;
5802 if (strequal(current, name)) {
5803 *found = true;
5804 break;
5807 q = strrchr(current, '\\');
5808 if (q) {
5809 if (!e.in.server) {
5810 torture_warning(tctx,
5811 "server returns printername %s incl. servername although we did not set servername", current);
5813 q++;
5814 if (strequal(q, name)) {
5815 *found = true;
5816 break;
5821 return true;
5824 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
5825 struct dcerpc_pipe *p,
5826 const char *printername,
5827 bool ex)
5829 WERROR result;
5830 struct spoolss_AddPrinter r;
5831 struct spoolss_AddPrinterEx rex;
5832 struct spoolss_SetPrinterInfoCtr info_ctr;
5833 struct spoolss_SetPrinterInfo1 info1;
5834 struct spoolss_DevmodeContainer devmode_ctr;
5835 struct sec_desc_buf secdesc_ctr;
5836 struct spoolss_UserLevelCtr userlevel_ctr;
5837 struct policy_handle handle;
5838 bool found = false;
5839 struct dcerpc_binding_handle *b = p->binding_handle;
5841 ZERO_STRUCT(devmode_ctr);
5842 ZERO_STRUCT(secdesc_ctr);
5843 ZERO_STRUCT(userlevel_ctr);
5844 ZERO_STRUCT(info1);
5846 torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
5848 /* try to add printer to wellknown printer list (level 1) */
5850 userlevel_ctr.level = 1;
5852 info_ctr.info.info1 = &info1;
5853 info_ctr.level = 1;
5855 rex.in.server = NULL;
5856 rex.in.info_ctr = &info_ctr;
5857 rex.in.devmode_ctr = &devmode_ctr;
5858 rex.in.secdesc_ctr = &secdesc_ctr;
5859 rex.in.userlevel_ctr = &userlevel_ctr;
5860 rex.out.handle = &handle;
5862 r.in.server = NULL;
5863 r.in.info_ctr = &info_ctr;
5864 r.in.devmode_ctr = &devmode_ctr;
5865 r.in.secdesc_ctr = &secdesc_ctr;
5866 r.out.handle = &handle;
5868 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5869 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5870 "failed to add printer");
5871 result = ex ? rex.out.result : r.out.result;
5872 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
5873 "unexpected result code");
5875 info1.name = printername;
5876 info1.flags = PRINTER_ATTRIBUTE_SHARED;
5878 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5879 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5880 "failed to add printer");
5881 result = ex ? rex.out.result : r.out.result;
5882 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
5883 "unexpected result code");
5885 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
5886 better do a real check to see the printer is really there */
5888 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
5889 PRINTER_ENUM_NETWORK, 1,
5890 printername,
5891 &found),
5892 "failed to enum printers");
5894 torture_assert(tctx, found, "failed to find newly added printer");
5896 info1.flags = 0;
5898 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5899 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5900 "failed to add printer");
5901 result = ex ? rex.out.result : r.out.result;
5902 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
5903 "unexpected result code");
5905 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
5906 better do a real check to see the printer has really been removed
5907 from the well known printer list */
5909 found = false;
5911 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
5912 PRINTER_ENUM_NETWORK, 1,
5913 printername,
5914 &found),
5915 "failed to enum printers");
5916 #if 0
5917 torture_assert(tctx, !found, "printer still in well known printer list");
5918 #endif
5919 return true;
5922 static bool test_AddPrinter_normal(struct torture_context *tctx,
5923 struct dcerpc_pipe *p,
5924 struct policy_handle *handle_p,
5925 const char *printername,
5926 const char *drivername,
5927 const char *portname,
5928 bool ex)
5930 WERROR result;
5931 struct spoolss_AddPrinter r;
5932 struct spoolss_AddPrinterEx rex;
5933 struct spoolss_SetPrinterInfoCtr info_ctr;
5934 struct spoolss_SetPrinterInfo2 info2;
5935 struct spoolss_DevmodeContainer devmode_ctr;
5936 struct sec_desc_buf secdesc_ctr;
5937 struct spoolss_UserLevelCtr userlevel_ctr;
5938 struct policy_handle handle;
5939 bool found = false;
5940 bool existing_printer_deleted = false;
5941 struct dcerpc_binding_handle *b = p->binding_handle;
5943 ZERO_STRUCT(devmode_ctr);
5944 ZERO_STRUCT(secdesc_ctr);
5945 ZERO_STRUCT(userlevel_ctr);
5947 torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
5949 userlevel_ctr.level = 1;
5951 rex.in.server = NULL;
5952 rex.in.info_ctr = &info_ctr;
5953 rex.in.devmode_ctr = &devmode_ctr;
5954 rex.in.secdesc_ctr = &secdesc_ctr;
5955 rex.in.userlevel_ctr = &userlevel_ctr;
5956 rex.out.handle = &handle;
5958 r.in.server = NULL;
5959 r.in.info_ctr = &info_ctr;
5960 r.in.devmode_ctr = &devmode_ctr;
5961 r.in.secdesc_ctr = &secdesc_ctr;
5962 r.out.handle = &handle;
5964 again:
5966 /* try to add printer to printer list (level 2) */
5968 ZERO_STRUCT(info2);
5970 info_ctr.info.info2 = &info2;
5971 info_ctr.level = 2;
5973 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5974 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5975 "failed to add printer");
5976 result = ex ? rex.out.result : r.out.result;
5977 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
5978 "unexpected result code");
5980 info2.printername = printername;
5982 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5983 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5984 "failed to add printer");
5985 result = ex ? rex.out.result : r.out.result;
5987 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
5988 struct policy_handle printer_handle;
5990 if (existing_printer_deleted) {
5991 torture_fail(tctx, "already deleted printer still existing?");
5994 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
5995 "failed to open printer handle");
5997 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
5998 "failed to delete printer");
6000 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
6001 "failed to close server handle");
6003 existing_printer_deleted = true;
6005 goto again;
6008 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
6009 "unexpected result code");
6011 info2.portname = portname;
6013 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6014 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6015 "failed to add printer");
6016 result = ex ? rex.out.result : r.out.result;
6017 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
6018 "unexpected result code");
6020 info2.drivername = drivername;
6022 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6023 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6024 "failed to add printer");
6025 result = ex ? rex.out.result : r.out.result;
6027 /* w2k8r2 allows to add printer w/o defining printprocessor */
6029 if (!W_ERROR_IS_OK(result)) {
6030 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
6031 "unexpected result code");
6033 info2.printprocessor = "winprint";
6035 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6036 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6037 "failed to add printer");
6038 result = ex ? rex.out.result : r.out.result;
6039 torture_assert_werr_ok(tctx, result,
6040 "failed to add printer");
6043 *handle_p = handle;
6045 /* we are paranoid, really check if the printer is there now */
6047 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6048 PRINTER_ENUM_LOCAL, 1,
6049 printername,
6050 &found),
6051 "failed to enum printers");
6052 torture_assert(tctx, found, "failed to find newly added printer");
6054 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6055 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6056 "failed to add printer");
6057 result = ex ? rex.out.result : r.out.result;
6058 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6059 "unexpected result code");
6061 return true;
6064 static bool test_printer_info(struct torture_context *tctx,
6065 struct dcerpc_binding_handle *b,
6066 struct policy_handle *handle)
6068 bool ret = true;
6070 if (torture_setting_bool(tctx, "samba3", false)) {
6071 torture_skip(tctx, "skipping printer info cross tests against samba 3");
6074 if (!test_PrinterInfo(tctx, b, handle)) {
6075 ret = false;
6078 if (!test_SetPrinter_errors(tctx, b, handle)) {
6079 ret = false;
6082 return ret;
6085 static bool test_EnumPrinterKey(struct torture_context *tctx,
6086 struct dcerpc_binding_handle *b,
6087 struct policy_handle *handle,
6088 const char *key_name,
6089 const char ***array)
6091 struct spoolss_EnumPrinterKey r;
6092 uint32_t needed = 0;
6093 union spoolss_KeyNames key_buffer;
6094 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
6095 uint32_t _ndr_size;
6096 int i;
6098 r.in.handle = handle;
6099 r.in.key_name = key_name;
6100 r.out.key_buffer = &key_buffer;
6101 r.out.needed = &needed;
6102 r.out._ndr_size = &_ndr_size;
6104 for (i=0; i < ARRAY_SIZE(offered); i++) {
6106 if (offered[i] < 0 && needed) {
6107 if (needed <= 4) {
6108 continue;
6110 r.in.offered = needed + offered[i];
6111 } else {
6112 r.in.offered = offered[i];
6115 ZERO_STRUCT(key_buffer);
6117 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
6119 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
6120 "failed to call EnumPrinterKey");
6121 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
6123 torture_assert(tctx, (_ndr_size == r.in.offered/2),
6124 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
6125 _ndr_size, r.in.offered/2));
6127 r.in.offered = needed;
6128 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
6129 "failed to call EnumPrinterKey");
6132 if (offered[i] > 0) {
6133 torture_assert_werr_ok(tctx, r.out.result,
6134 "failed to call EnumPrinterKey");
6137 torture_assert(tctx, (_ndr_size == r.in.offered/2),
6138 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
6139 _ndr_size, r.in.offered/2));
6141 torture_assert(tctx, (*r.out.needed <= r.in.offered),
6142 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
6144 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
6145 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
6147 if (key_buffer.string_array) {
6148 uint32_t calc_needed = 0;
6149 int s;
6150 for (s=0; key_buffer.string_array[s]; s++) {
6151 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
6153 if (!key_buffer.string_array[0]) {
6154 calc_needed += 2;
6156 calc_needed += 2;
6158 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
6159 "EnumPrinterKey unexpected size");
6163 if (array) {
6164 *array = key_buffer.string_array;
6167 return true;
6170 bool test_printer_keys(struct torture_context *tctx,
6171 struct dcerpc_binding_handle *b,
6172 struct policy_handle *handle)
6174 const char **key_array = NULL;
6175 int i;
6177 torture_comment(tctx, "Testing Printer Keys\n");
6179 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
6180 "failed to call test_EnumPrinterKey");
6182 for (i=0; key_array && key_array[i]; i++) {
6183 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
6184 "failed to call test_EnumPrinterKey");
6186 for (i=0; key_array && key_array[i]; i++) {
6187 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
6188 "failed to call test_EnumPrinterDataEx");
6191 torture_comment(tctx, "Printer Keys test succeeded\n\n");
6193 return true;
6196 static bool test_one_printer(struct torture_context *tctx,
6197 struct dcerpc_pipe *p,
6198 struct policy_handle *handle,
6199 const char *name,
6200 const char *drivername,
6201 const char *environment,
6202 bool have_driver)
6204 bool ret = true;
6205 struct dcerpc_binding_handle *b = p->binding_handle;
6207 if (!test_PausePrinter(tctx, b, handle)) {
6208 ret = false;
6211 if (!test_DoPrintTest(tctx, b, handle)) {
6212 ret = false;
6215 if (!test_ResumePrinter(tctx, b, handle)) {
6216 ret = false;
6219 if (!test_printer_info(tctx, b, handle)) {
6220 ret = false;
6223 if (!test_PrinterInfo_SD(tctx, b, handle)) {
6224 ret = false;
6227 if (!test_PrinterInfo_DevMode(tctx, p, handle, name)) {
6228 ret = false;
6231 if (!test_PrinterInfo_winreg(tctx, p, handle, name)) {
6232 ret = false;
6235 if (!test_ChangeID(tctx, p, handle)) {
6236 ret = false;
6239 if (!test_printer_keys(tctx, b, handle)) {
6240 ret = false;
6243 if (!test_EnumPrinterData_consistency(tctx, p, handle)) {
6244 ret = false;
6247 if (!test_SetPrinterDataEx_matrix(tctx, p, handle, name, NULL, NULL)) {
6248 ret = false;
6251 if (!test_PrinterData_winreg(tctx, p, handle, name)) {
6252 ret = false;
6255 if (have_driver) {
6256 if (!test_DriverInfo_winreg(tctx, p, handle, name, drivername, environment)) {
6257 ret = false;
6261 if (!test_printer_rename(tctx, p, handle, name)) {
6262 ret = false;
6265 return ret;
6268 static bool test_csetprinter(struct torture_context *tctx,
6269 struct dcerpc_pipe *p,
6270 struct policy_handle *handle,
6271 const char *printername,
6272 const char *drivername,
6273 const char *portname)
6275 union spoolss_PrinterInfo info;
6276 struct policy_handle new_handle, new_handle2;
6277 struct dcerpc_binding_handle *b = p->binding_handle;
6279 torture_comment(tctx, "Testing c_setprinter\n");
6281 torture_assert(tctx,
6282 test_GetPrinter_level(tctx, b, handle, 0, &info),
6283 "failed to get level 0 printer info");
6284 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
6285 info.info0.c_setprinter);
6287 /* check if c_setprinter on 1st handle increases after a printer has
6288 * been added */
6290 torture_assert(tctx,
6291 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, false),
6292 "failed to add new printer");
6293 torture_assert(tctx,
6294 test_GetPrinter_level(tctx, b, handle, 0, &info),
6295 "failed to get level 0 printer info");
6296 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
6297 info.info0.c_setprinter);
6299 /* check if c_setprinter on new handle increases after a printer has
6300 * been added */
6302 torture_assert(tctx,
6303 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
6304 "failed to get level 0 printer info");
6305 torture_comment(tctx, "csetprinter on created handle: %d\n",
6306 info.info0.c_setprinter);
6308 /* open the new printer and check if c_setprinter increases */
6310 torture_assert(tctx,
6311 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
6312 "failed to open created printer");
6313 torture_assert(tctx,
6314 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
6315 "failed to get level 0 printer info");
6316 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
6317 info.info0.c_setprinter);
6319 /* cleanup */
6321 torture_assert(tctx,
6322 test_ClosePrinter(tctx, b, &new_handle2),
6323 "failed to close printer");
6324 torture_assert(tctx,
6325 test_DeletePrinter(tctx, b, &new_handle),
6326 "failed to delete new printer");
6328 return true;
6331 static bool test_add_printer_args_with_driver(struct torture_context *tctx,
6332 struct dcerpc_pipe *p,
6333 struct torture_printer_context *t)
6335 bool ret = true;
6336 struct policy_handle handle;
6337 bool found = false;
6338 struct dcerpc_binding_handle *b = p->binding_handle;
6339 const char *printer_name = t->info2.printername;
6340 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
6341 const char *port_name = t->info2.portname;
6342 const char *printer_name2 = talloc_asprintf(tctx, "%s2", printer_name);
6344 if (t->wellknown) {
6345 torture_assert(tctx,
6346 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
6347 "failed to add wellknown printer");
6348 } else {
6349 torture_assert(tctx,
6350 test_AddPrinter_normal(tctx, p, &handle, printer_name, driver_name, port_name, t->ex),
6351 "failed to add printer");
6354 if (!test_csetprinter(tctx, p, &handle, printer_name2, driver_name, port_name)) {
6355 ret = false;
6358 if (!test_one_printer(tctx, p, &handle, printer_name, driver_name, t->driver.remote.environment, t->have_driver)) {
6359 ret = false;
6362 if (!test_DeletePrinter(tctx, b, &handle)) {
6363 ret = false;
6366 if (!test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
6367 printer_name, &found)) {
6368 ret = false;
6371 torture_assert(tctx, !found, "deleted printer still there");
6373 return ret;
6376 static bool compose_local_driver_directory(struct torture_context *tctx,
6377 const char *environment,
6378 const char *local_dir,
6379 const char **path)
6381 char *p;
6383 p = strrchr(local_dir, '/');
6384 if (!p) {
6385 return NULL;
6387 p++;
6389 if (strequal(environment, "Windows x64")) {
6390 if (!strequal(p, "x64")) {
6391 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
6393 } else if (strequal(environment, "Windows NT x86")) {
6394 if (!strequal(p, "i386")) {
6395 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
6397 } else {
6398 torture_assert(tctx, "unknown environment: '%s'\n", environment);
6401 return true;
6404 static bool test_add_printer_args(struct torture_context *tctx,
6405 struct dcerpc_pipe *p,
6406 struct torture_printer_context *t)
6408 bool ret = true;
6409 struct dcerpc_binding_handle *b = p->binding_handle;
6410 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6412 if (t->wellknown && torture_setting_bool(tctx, "samba3", false)) {
6413 torture_skip(tctx, "skipping AddPrinter level 1 against samba");
6416 torture_assert(tctx,
6417 fillup_printserver_info(tctx, p, &t->driver),
6418 "failed to fillup printserver info");
6420 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
6422 torture_assert(tctx,
6423 compose_local_driver_directory(tctx, t->driver.remote.environment,
6424 t->driver.local.driver_directory,
6425 &t->driver.local.driver_directory),
6426 "failed to compose local driver directory");
6428 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername)) {
6429 t->have_driver = true;
6430 goto try_run;
6433 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
6434 t->info2.drivername, t->driver.remote.environment);
6435 torture_comment(tctx, "trying to upload own driver\n");
6437 if (!directory_exist(t->driver.local.driver_directory)) {
6438 torture_warning(tctx, "no local driver is available!");
6439 t->have_driver = false;
6440 goto try_run;
6443 torture_assert(tctx,
6444 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
6445 "failed to upload printer driver");
6447 torture_assert(tctx,
6448 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false),
6449 "failed to add driver");
6451 t->added_driver = true;
6452 t->have_driver = true;
6454 try_run:
6455 ret = test_add_printer_args_with_driver(tctx, p, t);
6457 if (t->added_driver) {
6458 torture_assert(tctx,
6459 remove_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
6460 "failed to remove printer driver");
6463 return ret;
6466 static bool test_add_printer(struct torture_context *tctx,
6467 struct dcerpc_pipe *p,
6468 void *private_data)
6470 struct torture_printer_context *t =
6471 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6473 t->ex = false;
6474 t->wellknown = false;
6475 t->info2.printername = TORTURE_PRINTER;
6477 return test_add_printer_args(tctx, p, t);
6480 static bool test_add_printer_wellknown(struct torture_context *tctx,
6481 struct dcerpc_pipe *p,
6482 void *private_data)
6484 struct torture_printer_context *t =
6485 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6487 t->ex = false;
6488 t->wellknown = true;
6489 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
6491 return test_add_printer_args(tctx, p, t);
6494 static bool test_add_printer_ex(struct torture_context *tctx,
6495 struct dcerpc_pipe *p,
6496 void *private_data)
6498 struct torture_printer_context *t =
6499 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6501 t->ex = true;
6502 t->wellknown = false;
6503 t->info2.printername = TORTURE_PRINTER_EX;
6505 return test_add_printer_args(tctx, p, t);
6508 static bool test_add_printer_ex_wellknown(struct torture_context *tctx,
6509 struct dcerpc_pipe *p,
6510 void *private_data)
6512 struct torture_printer_context *t =
6513 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6515 t->ex = true;
6516 t->wellknown = true;
6517 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
6519 return test_add_printer_args(tctx, p, t);
6522 static bool test_architecture_buffer(struct torture_context *tctx,
6523 struct dcerpc_pipe *p)
6525 struct spoolss_OpenPrinterEx r;
6526 struct spoolss_UserLevel1 u1;
6527 struct policy_handle handle;
6528 uint32_t architectures[] = {
6529 PROCESSOR_ARCHITECTURE_INTEL,
6530 PROCESSOR_ARCHITECTURE_IA64,
6531 PROCESSOR_ARCHITECTURE_AMD64
6533 uint32_t needed[3];
6534 int i;
6535 struct dcerpc_binding_handle *b = p->binding_handle;
6537 for (i=0; i < ARRAY_SIZE(architectures); i++) {
6539 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
6541 u1.size = 0;
6542 u1.client = NULL;
6543 u1.user = NULL;
6544 u1.build = 0;
6545 u1.major = 3;
6546 u1.minor = 0;
6547 u1.processor = architectures[i];
6549 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6550 r.in.datatype = NULL;
6551 r.in.devmode_ctr.devmode= NULL;
6552 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6553 r.in.level = 1;
6554 r.in.userlevel.level1 = &u1;
6555 r.out.handle = &handle;
6557 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
6558 torture_assert_werr_ok(tctx, r.out.result, "");
6561 struct spoolss_EnumPrinters e;
6562 uint32_t count;
6563 union spoolss_PrinterInfo *info;
6565 e.in.flags = PRINTER_ENUM_LOCAL;
6566 e.in.server = NULL;
6567 e.in.level = 2;
6568 e.in.buffer = NULL;
6569 e.in.offered = 0;
6570 e.out.count = &count;
6571 e.out.info = &info;
6572 e.out.needed = &needed[i];
6574 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
6575 #if 0
6576 torture_comment(tctx, "needed was %d\n", needed[i]);
6577 #endif
6580 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
6583 for (i=1; i < ARRAY_SIZE(architectures); i++) {
6584 if (needed[i-1] != needed[i]) {
6585 torture_fail(tctx,
6586 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
6587 needed[i-1], architectures[i-1], needed[i], architectures[i]));
6591 return true;
6594 bool torture_rpc_spoolss(struct torture_context *torture)
6596 NTSTATUS status;
6597 struct dcerpc_pipe *p;
6598 struct dcerpc_binding_handle *b;
6599 bool ret = true;
6600 struct test_spoolss_context *ctx;
6601 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
6603 status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
6604 if (!NT_STATUS_IS_OK(status)) {
6605 return false;
6607 b = p->binding_handle;
6609 ctx = talloc_zero(torture, struct test_spoolss_context);
6611 ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
6612 ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle, &environment);
6613 ret &= test_EnumForms_all(torture, b, &ctx->server_handle, true);
6614 ret &= test_Forms(torture, b, &ctx->server_handle, true, NULL, NULL, NULL);
6615 ret &= test_Forms_winreg(torture, b, &ctx->server_handle, true, NULL);
6616 ret &= test_EnumPorts(torture, b, ctx);
6617 ret &= test_GetPrinterDriverDirectory(torture, p, environment);
6618 ret &= test_GetPrintProcessorDirectory(torture, p, environment);
6619 ret &= test_EnumPrinterDrivers(torture, p, ctx, environment);
6620 ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
6621 ret &= test_EnumMonitors(torture, b, ctx);
6622 ret &= test_EnumPrintProcessors(torture, b, ctx, environment);
6623 ret &= test_EnumPrintProcDataTypes(torture, b);
6624 ret &= test_EnumPrinters(torture, b, ctx);
6625 ret &= test_OpenPrinter_badname_list(torture, b, dcerpc_server_name(p));
6627 ret &= test_AddPort(torture, p);
6628 ret &= test_EnumPorts_old(torture, p);
6629 ret &= test_EnumPrinters_old(torture, p, environment);
6630 ret &= test_EnumPrinterDrivers_old(torture, p, environment);
6631 ret &= test_architecture_buffer(torture, p);
6633 return ret;
6636 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
6638 struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
6640 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
6641 "printer", &ndr_table_spoolss);
6643 struct torture_printer_context *t;
6645 t = talloc_zero(mem_ctx, struct torture_printer_context);
6647 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
6648 t->driver.info8.driver_name = TORTURE_DRIVER;
6649 t->driver.info8.driver_path = "pscript5.dll";
6650 t->driver.info8.data_file = "cups6.ppd";
6651 t->driver.info8.config_file = "ps5ui.dll";
6652 t->driver.info8.help_file = "pscript.hlp";
6653 t->driver.info8.default_datatype = "RAW";
6654 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
6655 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
6656 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
6657 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
6658 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
6659 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
6660 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
6661 t->driver.info8.dependent_files->string[5] = "cups6.ini";
6662 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
6663 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
6665 t->driver.local.driver_directory= "/usr/share/cups/drivers";
6667 t->info2.drivername = "Microsoft XPS Document Writer";
6668 t->info2.portname = "LPT1:";
6670 torture_rpc_tcase_add_test_ex(tcase, "add_printer", test_add_printer, t);
6671 torture_rpc_tcase_add_test_ex(tcase, "add_printer_wellknown", test_add_printer_wellknown, t);
6672 torture_rpc_tcase_add_test_ex(tcase, "add_printer_ex", test_add_printer_ex, t);
6673 torture_rpc_tcase_add_test_ex(tcase, "add_printer_ex_wellknown", test_add_printer_ex_wellknown, t);
6675 return suite;
6678 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
6679 struct dcerpc_binding_handle *b,
6680 const char *server,
6681 const char *environment,
6682 const char **dir_p)
6684 struct spoolss_GetPrinterDriverDirectory r;
6685 uint32_t needed;
6687 r.in.server = server;
6688 r.in.environment = environment;
6689 r.in.level = 1;
6690 r.in.buffer = NULL;
6691 r.in.offered = 0;
6692 r.out.needed = &needed;
6694 torture_assert_ntstatus_ok(tctx,
6695 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
6696 "failed to query driver directory");
6698 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6699 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6700 r.in.buffer = &blob;
6701 r.in.offered = needed;
6703 torture_assert_ntstatus_ok(tctx,
6704 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
6705 "failed to query driver directory");
6708 torture_assert_werr_ok(tctx, r.out.result,
6709 "failed to query driver directory");
6711 if (dir_p) {
6712 *dir_p = r.out.info->info1.directory_name;
6715 return true;
6718 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
6720 if (info_ctr == NULL) {
6721 return NULL;
6724 switch (info_ctr->level) {
6725 case 1:
6726 return info_ctr->info.info1->driver_name;
6727 case 2:
6728 return info_ctr->info.info2->driver_name;
6729 case 3:
6730 return info_ctr->info.info3->driver_name;
6731 case 4:
6732 return info_ctr->info.info4->driver_name;
6733 case 6:
6734 return info_ctr->info.info6->driver_name;
6735 case 8:
6736 return info_ctr->info.info8->driver_name;
6737 default:
6738 return NULL;
6742 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
6744 if (info_ctr == NULL) {
6745 return NULL;
6748 switch (info_ctr->level) {
6749 case 2:
6750 return info_ctr->info.info2->architecture;
6751 case 3:
6752 return info_ctr->info.info3->architecture;
6753 case 4:
6754 return info_ctr->info.info4->architecture;
6755 case 6:
6756 return info_ctr->info.info6->architecture;
6757 case 8:
6758 return info_ctr->info.info8->architecture;
6759 default:
6760 return NULL;
6765 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
6766 struct dcerpc_binding_handle *b,
6767 const char *servername,
6768 struct spoolss_AddDriverInfoCtr *info_ctr,
6769 WERROR expected_result)
6771 struct spoolss_AddPrinterDriver r;
6772 const char *drivername = get_driver_from_info(info_ctr);
6773 const char *environment = get_environment_from_info(info_ctr);
6775 r.in.servername = servername;
6776 r.in.info_ctr = info_ctr;
6778 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
6779 drivername, info_ctr->level, environment);
6781 torture_assert_ntstatus_ok(tctx,
6782 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
6783 "spoolss_AddPrinterDriver failed");
6784 torture_assert_werr_equal(tctx, r.out.result, expected_result,
6785 "spoolss_AddPrinterDriver failed with unexpected result");
6787 return true;
6791 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
6792 struct dcerpc_binding_handle *b,
6793 const char *servername,
6794 struct spoolss_AddDriverInfoCtr *info_ctr,
6795 uint32_t flags,
6796 WERROR expected_result)
6798 struct spoolss_AddPrinterDriverEx r;
6799 const char *drivername = get_driver_from_info(info_ctr);
6800 const char *environment = get_environment_from_info(info_ctr);
6802 r.in.servername = servername;
6803 r.in.info_ctr = info_ctr;
6804 r.in.flags = flags;
6806 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
6807 drivername, info_ctr->level, environment);
6809 torture_assert_ntstatus_ok(tctx,
6810 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
6811 "AddPrinterDriverEx failed");
6812 torture_assert_werr_equal(tctx, r.out.result, expected_result,
6813 "AddPrinterDriverEx failed with unexpected result");
6815 return true;
6818 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
6819 struct dcerpc_binding_handle *b,
6820 const char *server_name,
6821 struct spoolss_AddDriverInfo8 *r,
6822 uint32_t flags,
6823 bool ex)
6825 struct spoolss_AddDriverInfoCtr info_ctr;
6826 struct spoolss_AddDriverInfo1 info1;
6828 ZERO_STRUCT(info1);
6830 info_ctr.level = 1;
6831 info_ctr.info.info1 = &info1;
6833 if (ex) {
6834 torture_assert(tctx,
6835 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
6836 "failed to test AddPrinterDriverEx level 1");
6837 } else {
6838 torture_assert(tctx,
6839 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
6840 "failed to test AddPrinterDriver level 1");
6843 info1.driver_name = r->driver_name;
6845 if (ex) {
6846 torture_assert(tctx,
6847 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
6848 "failed to test AddPrinterDriverEx level 1");
6849 } else {
6850 torture_assert(tctx,
6851 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
6852 "failed to test AddPrinterDriver level 1");
6855 return true;
6858 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
6859 struct dcerpc_binding_handle *b,
6860 const char *server_name,
6861 struct spoolss_AddDriverInfo8 *r,
6862 uint32_t flags,
6863 bool ex)
6865 struct spoolss_AddDriverInfoCtr info_ctr;
6866 struct spoolss_AddDriverInfo2 info2;
6868 ZERO_STRUCT(info2);
6870 info_ctr.level = 2;
6871 info_ctr.info.info2 = &info2;
6873 if (ex) {
6874 torture_assert(tctx,
6875 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
6876 "failed to test AddPrinterDriverEx level 2");
6877 } else {
6878 torture_assert(tctx,
6879 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
6880 "failed to test AddPrinterDriver level 2");
6883 info2.driver_name = r->driver_name;
6885 if (ex) {
6886 torture_assert(tctx,
6887 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
6888 "failed to test AddPrinterDriverEx level 2");
6889 } else {
6890 torture_assert(tctx,
6891 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
6892 "failed to test AddPrinterDriver level 2");
6895 info2.version = r->version;
6897 if (ex) {
6898 torture_assert(tctx,
6899 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
6900 "failed to test AddPrinterDriverEx level 2");
6901 } else {
6902 torture_assert(tctx,
6903 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
6904 "failed to test AddPrinterDriver level 2");
6907 info2.architecture = r->architecture;
6909 if (ex) {
6910 torture_assert(tctx,
6911 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
6912 "failed to test AddPrinterDriverEx level 2");
6913 } else {
6914 torture_assert(tctx,
6915 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
6916 "failed to test AddPrinterDriver level 2");
6919 info2.driver_path = r->driver_path;
6921 if (ex) {
6922 torture_assert(tctx,
6923 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
6924 "failed to test AddPrinterDriverEx level 2");
6925 } else {
6926 torture_assert(tctx,
6927 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
6928 "failed to test AddPrinterDriver level 2");
6931 info2.data_file = r->data_file;
6933 if (ex) {
6934 torture_assert(tctx,
6935 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
6936 "failed to test AddPrinterDriverEx level 2");
6937 } else {
6938 torture_assert(tctx,
6939 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
6940 "failed to test AddPrinterDriver level 2");
6943 info2.config_file = r->config_file;
6945 if (ex) {
6946 torture_assert(tctx,
6947 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
6948 "failed to test AddPrinterDriverEx");
6951 if (ex) {
6952 torture_assert(tctx,
6953 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
6954 "failed to test AddPrinterDriverEx level 2");
6955 } else {
6956 torture_assert(tctx,
6957 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
6958 "failed to test AddPrinterDriver level 2");
6961 torture_assert(tctx,
6962 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name),
6963 "failed to find added printer driver");
6965 return true;
6968 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
6969 struct dcerpc_binding_handle *b,
6970 const char *server_name,
6971 struct spoolss_AddDriverInfo8 *r,
6972 uint32_t flags,
6973 bool ex)
6975 struct spoolss_AddDriverInfoCtr info_ctr;
6976 struct spoolss_AddDriverInfo3 info3;
6978 info3.driver_name = r->driver_name;
6979 info3.version = r->version;
6980 info3.architecture = r->architecture;
6981 info3.driver_path = r->driver_path;
6982 info3.data_file = r->data_file;
6983 info3.config_file = r->config_file;
6984 info3.help_file = r->help_file;
6985 info3.monitor_name = r->monitor_name;
6986 info3.default_datatype = r->default_datatype;
6987 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
6988 info3.dependent_files = r->dependent_files;
6990 info_ctr.level = 3;
6991 info_ctr.info.info3 = &info3;
6993 if (ex) {
6994 torture_assert(tctx,
6995 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
6996 "failed to test AddPrinterDriverEx level 3");
6997 } else {
6998 torture_assert(tctx,
6999 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7000 "failed to test AddPrinterDriver level 3");
7003 torture_assert(tctx,
7004 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name),
7005 "failed to find added printer driver");
7007 return true;
7010 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
7011 struct dcerpc_binding_handle *b,
7012 const char *server_name,
7013 struct spoolss_AddDriverInfo8 *r,
7014 uint32_t flags,
7015 bool ex)
7017 struct spoolss_AddDriverInfoCtr info_ctr;
7018 struct spoolss_AddDriverInfo4 info4;
7020 info4.version = r->version;
7021 info4.driver_name = r->driver_name;
7022 info4.architecture = r->architecture;
7023 info4.driver_path = r->driver_path;
7024 info4.data_file = r->data_file;
7025 info4.config_file = r->config_file;
7026 info4.help_file = r->help_file;
7027 info4.monitor_name = r->monitor_name;
7028 info4.default_datatype = r->default_datatype;
7029 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7030 info4.dependent_files = r->dependent_files;
7031 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
7032 info4.previous_names = r->previous_names;
7034 info_ctr.level = 4;
7035 info_ctr.info.info4 = &info4;
7037 if (ex) {
7038 torture_assert(tctx,
7039 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7040 "failed to test AddPrinterDriverEx level 4");
7041 } else {
7042 torture_assert(tctx,
7043 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
7044 "failed to test AddPrinterDriver level 4");
7047 torture_assert(tctx,
7048 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name),
7049 "failed to find added printer driver");
7051 return true;
7054 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
7055 struct dcerpc_binding_handle *b,
7056 const char *server_name,
7057 struct spoolss_AddDriverInfo8 *r,
7058 uint32_t flags,
7059 bool ex)
7061 struct spoolss_AddDriverInfoCtr info_ctr;
7062 struct spoolss_AddDriverInfo6 info6;
7064 info6.version = r->version;
7065 info6.driver_name = r->driver_name;
7066 info6.architecture = r->architecture;
7067 info6.driver_path = r->driver_path;
7068 info6.data_file = r->data_file;
7069 info6.config_file = r->config_file;
7070 info6.help_file = r->help_file;
7071 info6.monitor_name = r->monitor_name;
7072 info6.default_datatype = r->default_datatype;
7073 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
7074 info6.dependent_files = r->dependent_files;
7075 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
7076 info6.previous_names = r->previous_names;
7077 info6.driver_date = r->driver_date;
7078 info6.driver_version = r->driver_version;
7079 info6.manufacturer_name = r->manufacturer_name;
7080 info6.manufacturer_url = r->manufacturer_url;
7081 info6.hardware_id = r->hardware_id;
7082 info6.provider = r->provider;
7084 info_ctr.level = 6;
7085 info_ctr.info.info6 = &info6;
7087 if (ex) {
7088 torture_assert(tctx,
7089 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7090 "failed to test AddPrinterDriverEx level 6");
7091 } else {
7092 torture_assert(tctx,
7093 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7094 "failed to test AddPrinterDriver level 6");
7097 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
7099 if (!ex) {
7100 return true;
7103 torture_assert(tctx,
7104 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name),
7105 "failed to find added printer driver");
7107 return true;
7110 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
7111 struct dcerpc_binding_handle *b,
7112 const char *server_name,
7113 struct spoolss_AddDriverInfo8 *r,
7114 uint32_t flags,
7115 bool ex)
7117 struct spoolss_AddDriverInfoCtr info_ctr;
7119 info_ctr.level = 8;
7120 info_ctr.info.info8 = r;
7122 if (ex) {
7123 torture_assert(tctx,
7124 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
7125 "failed to test AddPrinterDriverEx level 8");
7126 } else {
7127 torture_assert(tctx,
7128 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
7129 "failed to test AddPrinterDriver level 8");
7132 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
7134 if (!ex) {
7135 return true;
7138 torture_assert(tctx,
7139 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name),
7140 "failed to find added printer driver");
7142 return true;
7145 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
7146 struct dcerpc_binding_handle *b,
7147 const char *server,
7148 const char *driver,
7149 const char *environment,
7150 WERROR expected_result)
7152 struct spoolss_DeletePrinterDriver r;
7154 r.in.server = server;
7155 r.in.architecture = environment;
7156 r.in.driver = driver;
7158 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
7160 torture_assert_ntstatus_ok(tctx,
7161 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
7162 "DeletePrinterDriver failed");
7163 torture_assert_werr_equal(tctx, r.out.result, expected_result,
7164 "DeletePrinterDriver failed with unexpected result");
7166 return true;
7169 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
7170 struct dcerpc_binding_handle *b,
7171 const char *server,
7172 const char *driver,
7173 const char *environment,
7174 uint32_t delete_flags,
7175 uint32_t version,
7176 WERROR expected_result)
7178 struct spoolss_DeletePrinterDriverEx r;
7180 r.in.server = server;
7181 r.in.architecture = environment;
7182 r.in.driver = driver;
7183 r.in.delete_flags = delete_flags;
7184 r.in.version = version;
7186 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
7188 torture_assert_ntstatus_ok(tctx,
7189 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
7190 "DeletePrinterDriverEx failed");
7191 torture_assert_werr_equal(tctx, r.out.result, expected_result,
7192 "DeletePrinterDriverEx failed with unexpected result");
7194 return true;
7197 static bool test_DeletePrinterDriver(struct torture_context *tctx,
7198 struct dcerpc_binding_handle *b,
7199 const char *server_name,
7200 const char *driver,
7201 const char *environment)
7203 torture_assert(tctx,
7204 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
7205 "failed to delete driver");
7207 torture_assert(tctx,
7208 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
7209 "failed to delete driver");
7211 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
7212 torture_fail(tctx, "deleted driver still enumerated");
7215 torture_assert(tctx,
7216 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
7217 "2nd delete failed");
7219 return true;
7222 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
7223 struct dcerpc_binding_handle *b,
7224 const char *server_name,
7225 const char *driver,
7226 const char *environment,
7227 uint32_t delete_flags,
7228 uint32_t version)
7230 torture_assert(tctx,
7231 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
7232 "failed to delete driver");
7234 torture_assert(tctx,
7235 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
7236 "failed to delete driver");
7238 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
7239 torture_fail(tctx, "deleted driver still enumerated");
7242 torture_assert(tctx,
7243 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
7244 "2nd delete failed");
7246 return true;
7249 static bool test_PrinterDriver_args(struct torture_context *tctx,
7250 struct dcerpc_binding_handle *b,
7251 const char *server_name,
7252 uint32_t level,
7253 struct spoolss_AddDriverInfo8 *r,
7254 uint32_t add_flags,
7255 uint32_t delete_flags,
7256 uint32_t delete_version,
7257 bool ex)
7259 bool ret = true;
7261 switch (level) {
7262 case 1:
7263 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex);
7264 break;
7265 case 2:
7266 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex);
7267 break;
7268 case 3:
7269 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex);
7270 break;
7271 case 4:
7272 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex);
7273 break;
7274 case 6:
7275 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex);
7276 break;
7277 case 8:
7278 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex);
7279 break;
7280 default:
7281 return false;
7284 if (ret == false) {
7285 return ret;
7288 if (level == 1) {
7289 return ret;
7292 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
7294 if (!ex && (level == 6 || level == 8)) {
7295 return ret;
7298 if (ex) {
7299 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
7300 } else {
7301 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
7305 static bool fillup_printserver_info(struct torture_context *tctx,
7306 struct dcerpc_pipe *p,
7307 struct torture_driver_context *d)
7309 struct policy_handle server_handle;
7310 struct dcerpc_binding_handle *b = p->binding_handle;
7311 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7313 torture_assert(tctx,
7314 test_OpenPrinter_server(tctx, p, &server_handle),
7315 "failed to open printserver");
7316 torture_assert(tctx,
7317 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
7318 "failed to get environment");
7319 torture_assert(tctx,
7320 test_ClosePrinter(tctx, b, &server_handle),
7321 "failed to close printserver");
7323 torture_assert(tctx,
7324 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
7325 d->local.environment ? d->local.environment : d->remote.environment,
7326 &d->remote.driver_directory),
7327 "failed to get driver directory");
7329 return true;
7332 static const char *driver_directory_dir(const char *driver_directory)
7334 char *p;
7336 p = strrchr(driver_directory, '\\');
7337 if (p) {
7338 return p+1;
7341 return NULL;
7344 static const char *driver_directory_share(struct torture_context *tctx,
7345 const char *driver_directory)
7347 const char *p;
7348 char *tok;
7350 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
7351 driver_directory += 2;
7354 p = talloc_strdup(tctx, driver_directory);
7356 torture_assert(tctx,
7357 next_token_talloc(tctx, &p, &tok, "\\"),
7358 "cannot explode uri");
7359 torture_assert(tctx,
7360 next_token_talloc(tctx, &p, &tok, "\\"),
7361 "cannot explode uri");
7363 return tok;
7366 static bool upload_printer_driver_file(struct torture_context *tctx,
7367 struct smbcli_state *cli,
7368 struct torture_driver_context *d,
7369 const char *file_name)
7371 XFILE *f;
7372 int fnum;
7373 uint8_t *buf;
7374 int maxwrite = 64512;
7375 off_t nread = 0;
7376 size_t start = 0;
7377 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
7378 const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
7379 const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
7381 if (!file_name) {
7382 return true;
7385 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
7387 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
7388 if (fnum == -1) {
7389 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
7392 f = x_fopen(local_name, O_RDONLY, 0);
7393 if (f == NULL) {
7394 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
7397 buf = talloc_array(tctx, uint8_t, maxwrite);
7398 if (!buf) {
7399 return false;
7402 while (!x_feof(f)) {
7403 int n = maxwrite;
7404 int ret;
7406 if ((n = x_fread(buf, 1, n, f)) < 1) {
7407 if((n == 0) && x_feof(f))
7408 break; /* Empty local file. */
7410 torture_warning(tctx,
7411 "failed to read file: %s\n", strerror(errno));
7412 break;
7415 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
7417 if (n != ret) {
7418 torture_warning(tctx,
7419 "failed to write file: %s\n", smbcli_errstr(cli->tree));
7420 break;
7423 nread += n;
7426 x_fclose(f);
7428 torture_assert_ntstatus_ok(tctx,
7429 smbcli_close(cli->tree, fnum),
7430 "failed to close file");
7432 return true;
7435 static bool connect_printer_driver_share(struct torture_context *tctx,
7436 const char *server_name,
7437 const char *share_name,
7438 struct smbcli_state **cli)
7440 struct smbcli_options smb_options;
7441 struct smbcli_session_options smb_session_options;
7443 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
7444 share_name, server_name);
7446 lp_smbcli_options(tctx->lp_ctx, &smb_options);
7447 lp_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
7449 torture_assert_ntstatus_ok(tctx,
7450 smbcli_full_connection(tctx, cli, server_name,
7451 lp_smb_ports(tctx->lp_ctx),
7452 share_name, NULL,
7453 lp_socket_options(tctx->lp_ctx),
7454 cmdline_credentials,
7455 lp_resolve_context(tctx->lp_ctx),
7456 tctx->ev,
7457 &smb_options,
7458 &smb_session_options,
7459 lp_iconv_convenience(tctx->lp_ctx),
7460 lp_gensec_settings(tctx, tctx->lp_ctx)),
7461 "failed to open driver share");
7463 return true;
7466 static bool upload_printer_driver(struct torture_context *tctx,
7467 const char *server_name,
7468 struct torture_driver_context *d)
7470 struct smbcli_state *cli;
7471 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
7472 int i;
7474 torture_assert(tctx,
7475 connect_printer_driver_share(tctx, server_name, share_name, &cli),
7476 "failed to connect to driver share");
7478 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
7479 server_name, share_name);
7481 torture_assert(tctx,
7482 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
7483 "failed to upload driver_path");
7484 torture_assert(tctx,
7485 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
7486 "failed to upload data_file");
7487 torture_assert(tctx,
7488 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
7489 "failed to upload config_file");
7490 torture_assert(tctx,
7491 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
7492 "failed to upload help_file");
7493 if (d->info8.dependent_files) {
7494 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
7495 torture_assert(tctx,
7496 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
7497 "failed to upload dependent_files");
7501 talloc_free(cli);
7503 return true;
7506 static bool remove_printer_driver_file(struct torture_context *tctx,
7507 struct smbcli_state *cli,
7508 struct torture_driver_context *d,
7509 const char *file_name)
7511 const char *remote_name;
7512 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
7514 if (!file_name) {
7515 return true;
7518 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
7520 torture_comment(tctx, "Removing %s\n", remote_name);
7522 torture_assert_ntstatus_ok(tctx,
7523 smbcli_unlink(cli->tree, remote_name),
7524 "failed to unlink");
7526 return true;
7529 static bool remove_printer_driver(struct torture_context *tctx,
7530 const char *server_name,
7531 struct torture_driver_context *d)
7533 struct smbcli_state *cli;
7534 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
7535 int i;
7537 torture_assert(tctx,
7538 connect_printer_driver_share(tctx, server_name, share_name, &cli),
7539 "failed to connect to driver share");
7541 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
7542 server_name, share_name);
7544 torture_assert(tctx,
7545 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
7546 "failed to remove driver_path");
7547 torture_assert(tctx,
7548 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
7549 "failed to remove data_file");
7550 torture_assert(tctx,
7551 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
7552 "failed to remove config_file");
7553 torture_assert(tctx,
7554 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
7555 "failed to remove help_file");
7556 if (d->info8.dependent_files) {
7557 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
7558 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
7559 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
7560 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
7561 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
7562 continue;
7564 torture_assert(tctx,
7565 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
7566 "failed to remove dependent_files");
7570 talloc_free(cli);
7572 return true;
7576 static bool test_add_driver_arg(struct torture_context *tctx,
7577 struct dcerpc_pipe *p,
7578 struct torture_driver_context *d)
7580 bool ret = true;
7581 struct dcerpc_binding_handle *b = p->binding_handle;
7582 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7583 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
7584 int i;
7585 struct spoolss_AddDriverInfo8 info8;
7586 uint32_t add_flags = APD_COPY_NEW_FILES;
7587 uint32_t delete_flags = 0;
7589 ZERO_STRUCT(info8);
7591 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
7592 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
7594 torture_assert(tctx,
7595 fillup_printserver_info(tctx, p, d),
7596 "failed to fillup printserver info");
7598 if (!directory_exist(d->local.driver_directory)) {
7599 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
7602 torture_assert(tctx,
7603 upload_printer_driver(tctx, dcerpc_server_name(p), d),
7604 "failed to upload printer driver");
7606 info8.version = d->info8.version;
7607 info8.driver_name = d->info8.driver_name;
7608 info8.architecture = d->local.environment;
7609 info8.driver_path = d->info8.driver_path;
7610 info8.data_file = d->info8.data_file;
7611 info8.config_file = d->info8.config_file;
7613 for (i=0; i < ARRAY_SIZE(levels); i++) {
7615 if (torture_setting_bool(tctx, "samba3", false)) {
7616 switch (levels[i]) {
7617 case 2:
7618 case 4:
7619 case 8:
7620 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
7621 continue;
7622 default:
7623 break;
7627 torture_comment(tctx,
7628 "Testing PrinterDriver%s '%s' add & delete level %d\n",
7629 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
7631 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
7634 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
7635 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
7636 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
7638 for (i=0; i < ARRAY_SIZE(levels); i++) {
7640 if (torture_setting_bool(tctx, "samba3", false)) {
7641 switch (levels[i]) {
7642 case 2:
7643 case 4:
7644 case 8:
7645 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
7646 continue;
7647 default:
7648 break;
7653 torture_comment(tctx,
7654 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
7655 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
7657 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
7660 torture_assert(tctx,
7661 remove_printer_driver(tctx, dcerpc_server_name(p), d),
7662 "failed to remove printer driver");
7664 torture_comment(tctx, "\n");
7666 return ret;
7669 static bool test_add_driver_ex_64(struct torture_context *tctx,
7670 struct dcerpc_pipe *p,
7671 void *private_data)
7673 struct torture_driver_context *d =
7674 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
7676 d->local.environment = talloc_strdup(d, "Windows x64");
7677 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
7678 d->info8.driver_name = TORTURE_DRIVER_EX;
7679 d->ex = true;
7681 return test_add_driver_arg(tctx, p, d);
7684 static bool test_add_driver_ex_32(struct torture_context *tctx,
7685 struct dcerpc_pipe *p,
7686 void *private_data)
7688 struct torture_driver_context *d =
7689 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
7691 d->local.environment = talloc_strdup(d, "Windows NT x86");
7692 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
7693 d->info8.driver_name = TORTURE_DRIVER_EX;
7694 d->ex = true;
7696 return test_add_driver_arg(tctx, p, d);
7699 static bool test_add_driver_64(struct torture_context *tctx,
7700 struct dcerpc_pipe *p,
7701 void *private_data)
7703 struct torture_driver_context *d =
7704 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
7706 d->local.environment = talloc_strdup(d, "Windows x64");
7707 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
7708 d->info8.driver_name = TORTURE_DRIVER;
7709 d->ex = false;
7711 return test_add_driver_arg(tctx, p, d);
7714 static bool test_add_driver_32(struct torture_context *tctx,
7715 struct dcerpc_pipe *p,
7716 void *private_data)
7718 struct torture_driver_context *d =
7719 (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
7721 d->local.environment = talloc_strdup(d, "Windows NT x86");
7722 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
7723 d->info8.driver_name = TORTURE_DRIVER;
7724 d->ex = false;
7726 return test_add_driver_arg(tctx, p, d);
7729 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
7731 struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-DRIVER");
7733 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
7734 "driver", &ndr_table_spoolss);
7735 struct torture_driver_context *t;
7737 t = talloc_zero(mem_ctx, struct torture_driver_context);
7739 t->info8.version = SPOOLSS_DRIVER_VERSION_200X;
7740 t->info8.driver_name = NULL;
7741 t->info8.architecture = NULL;
7742 t->info8.driver_path = talloc_strdup(t, "pscript5.dll");
7743 t->info8.data_file = talloc_strdup(t, "cups6.ppd");
7744 t->info8.config_file = talloc_strdup(t, "cupsui6.dll");
7746 torture_rpc_tcase_add_test_ex(tcase, "add_driver_64", test_add_driver_64, t);
7747 torture_rpc_tcase_add_test_ex(tcase, "add_driver_ex_64", test_add_driver_ex_64, t);
7749 torture_rpc_tcase_add_test_ex(tcase, "add_driver_32", test_add_driver_32, t);
7750 torture_rpc_tcase_add_test_ex(tcase, "add_driver_ex_32", test_add_driver_ex_32, t);
7752 return suite;