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-2011
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/>.
25 #include "torture/torture.h"
26 #include "librpc/gen_ndr/ndr_misc.h"
27 #include "librpc/gen_ndr/ndr_spoolss.h"
28 #include "librpc/gen_ndr/ndr_spoolss_c.h"
29 #include "librpc/gen_ndr/ndr_winreg_c.h"
30 #include "librpc/gen_ndr/ndr_security.h"
31 #include "libcli/security/security.h"
32 #include "torture/rpc/torture_rpc.h"
33 #include "param/param.h"
34 #include "lib/registry/registry.h"
35 #include "libcli/libcli.h"
36 #include "libcli/raw/raw_proto.h"
37 #include "libcli/resolve/resolve.h"
38 #include "lib/cmdline/popt_common.h"
39 #include "system/filesys.h"
40 #include "torture/ndr/ndr.h"
42 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
43 #define TORTURE_PRINTER "torture_printer"
44 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
45 #define TORTURE_PRINTER_EX "torture_printer_ex"
46 #define TORTURE_DRIVER "torture_driver"
47 #define TORTURE_DRIVER_EX "torture_driver_ex"
48 #define TORTURE_DRIVER_ADOBE "torture_driver_adobe"
49 #define TORTURE_DRIVER_EX_ADOBE "torture_driver_ex_adobe"
50 #define TORTURE_DRIVER_ADOBE_CUPSADDSMB "torture_driver_adobe_cupsaddsmb"
51 #define TORTURE_DRIVER_TIMESTAMPS "torture_driver_timestamps"
53 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
54 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
55 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
56 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
57 #define TOP_LEVEL_CONTROL_PRINTERS_KEY TOP_LEVEL_CONTROL_KEY "\\Printers"
58 #define TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY TOP_LEVEL_CONTROL_KEY "\\Environments"
60 struct test_spoolss_context {
61 struct dcerpc_pipe *spoolss_pipe;
63 /* server environment */
64 const char *environment;
66 /* print server handle */
67 struct policy_handle server_handle;
70 uint32_t port_count[3];
71 union spoolss_PortInfo *ports[3];
73 /* for EnumPrinterDrivers */
74 uint32_t driver_count[8];
75 union spoolss_DriverInfo *drivers[8];
77 /* for EnumMonitors */
78 uint32_t monitor_count[3];
79 union spoolss_MonitorInfo *monitors[3];
81 /* for EnumPrintProcessors */
82 uint32_t print_processor_count[2];
83 union spoolss_PrintProcessorInfo *print_processors[2];
85 /* for EnumPrinters */
86 uint32_t printer_count[6];
87 union spoolss_PrinterInfo *printers[6];
90 struct torture_driver_context {
92 const char *driver_directory;
93 const char *environment;
96 const char *driver_directory;
97 const char *environment;
99 struct spoolss_AddDriverInfo8 info8;
103 struct torture_printer_context {
104 struct dcerpc_pipe *spoolss_pipe;
105 struct spoolss_SetPrinterInfo2 info2;
106 struct torture_driver_context driver;
111 struct spoolss_DeviceMode *devmode;
112 struct policy_handle handle;
115 static bool upload_printer_driver(struct torture_context *tctx,
116 const char *server_name,
117 struct torture_driver_context *d);
118 static bool remove_printer_driver(struct torture_context *tctx,
119 const char *server_name,
120 struct torture_driver_context *d);
121 static bool fillup_printserver_info(struct torture_context *tctx,
122 struct dcerpc_pipe *p,
123 struct torture_driver_context *d);
124 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
125 struct dcerpc_binding_handle *b,
126 const char *server_name,
127 struct spoolss_AddDriverInfo8 *r,
130 const char *remote_driver_dir);
132 #define COMPARE_STRING(tctx, c,r,e) \
133 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
135 /* not every compiler supports __typeof__() */
137 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
138 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
139 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
141 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
142 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
146 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
149 #define COMPARE_UINT32(tctx, c, r, e) do {\
150 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
151 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
154 #define COMPARE_UINT64(tctx, c, r, e) do {\
155 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
156 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
160 #define COMPARE_NTTIME(tctx, c, r, e) do {\
161 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
162 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
165 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
167 if (!c.e && !r.e) { \
171 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
174 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
176 for (__i=0;c.e[__i] != NULL; __i++) { \
177 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
181 #define CHECK_ALIGN(size, n) do {\
183 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
184 size, n, size + n - (size % n));\
188 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
190 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, needed, align) do { \
191 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
192 uint32_t size = ndr_size_##fn##_info(tctx, level, count, info);\
193 uint32_t round_size = DO_ROUND(size, align);\
194 if (round_size != needed) {\
195 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
196 CHECK_ALIGN(size, align);\
201 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, needed, align) do { \
202 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
203 uint32_t size = ndr_size_##fn##_info(tctx, count, info);\
204 uint32_t round_size = DO_ROUND(size, align);\
205 if (round_size != needed) {\
206 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
207 CHECK_ALIGN(size, align);\
212 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, needed, align) do { \
213 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
214 uint32_t size = ndr_size_##fn(info, level, 0);\
215 uint32_t round_size = DO_ROUND(size, align);\
216 if (round_size != needed) {\
217 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
218 CHECK_ALIGN(size, align);\
223 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context *tctx,
224 const union spoolss_PrinterInfo *i,
226 union spoolss_SetPrinterInfo *s)
230 s->info0 = talloc(tctx, struct spoolss_SetPrinterInfo0);
233 s->info2 = talloc(tctx, struct spoolss_SetPrinterInfo2);
234 s->info2->servername = i->info2.servername;
235 s->info2->printername = i->info2.printername;
236 s->info2->sharename = i->info2.sharename;
237 s->info2->portname = i->info2.portname;
238 s->info2->drivername = i->info2.drivername;
239 s->info2->comment = i->info2.comment;
240 s->info2->location = i->info2.location;
241 s->info2->devmode_ptr = 0;
242 s->info2->sepfile = i->info2.sepfile;
243 s->info2->printprocessor = i->info2.printprocessor;
244 s->info2->datatype = i->info2.datatype;
245 s->info2->parameters = i->info2.parameters;
246 s->info2->secdesc_ptr = 0;
247 s->info2->attributes = i->info2.attributes;
248 s->info2->priority = i->info2.priority;
249 s->info2->defaultpriority = i->info2.defaultpriority;
250 s->info2->starttime = i->info2.starttime;
251 s->info2->untiltime = i->info2.untiltime;
252 s->info2->status = i->info2.status;
253 s->info2->cjobs = i->info2.cjobs;
254 s->info2->averageppm = i->info2.averageppm;
270 static bool test_OpenPrinter_server(struct torture_context *tctx,
271 struct dcerpc_pipe *p,
272 struct policy_handle *server_handle)
275 struct spoolss_OpenPrinter op;
276 struct dcerpc_binding_handle *b = p->binding_handle;
278 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
279 op.in.datatype = NULL;
280 op.in.devmode_ctr.devmode= NULL;
281 op.in.access_mask = 0;
282 op.out.handle = server_handle;
284 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
286 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
287 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
288 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
293 static bool test_EnumPorts(struct torture_context *tctx,
296 struct test_spoolss_context *ctx =
297 talloc_get_type_abort(private_data, struct test_spoolss_context);
298 struct dcerpc_pipe *p = ctx->spoolss_pipe;
299 struct dcerpc_binding_handle *b = p->binding_handle;
301 struct spoolss_EnumPorts r;
302 uint16_t levels[] = { 1, 2 };
305 for (i=0;i<ARRAY_SIZE(levels);i++) {
306 int level = levels[i];
310 union spoolss_PortInfo *info;
312 r.in.servername = "";
316 r.out.needed = &needed;
317 r.out.count = &count;
320 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
322 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
323 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
324 if (W_ERROR_IS_OK(r.out.result)) {
325 /* TODO: do some more checks here */
328 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
329 "EnumPorts unexpected return code");
331 blob = data_blob_talloc_zero(ctx, needed);
333 r.in.offered = needed;
335 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
336 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
338 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
340 torture_assert(tctx, info, "EnumPorts returned no info");
342 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, needed, 4);
344 ctx->port_count[level] = count;
345 ctx->ports[level] = info;
348 for (i=1;i<ARRAY_SIZE(levels);i++) {
349 int level = levels[i];
350 int old_level = levels[i-1];
351 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
352 "EnumPorts invalid value");
354 /* if the array sizes are not the same we would maybe segfault in the following code */
356 for (i=0;i<ARRAY_SIZE(levels);i++) {
357 int level = levels[i];
358 for (j=0;j<ctx->port_count[level];j++) {
359 union spoolss_PortInfo *cur = &ctx->ports[level][j];
360 union spoolss_PortInfo *ref = &ctx->ports[2][j];
363 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
366 /* level 2 is our reference, and it makes no sense to compare it to itself */
375 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
378 struct test_spoolss_context *ctx =
379 talloc_get_type_abort(private_data, struct test_spoolss_context);
382 struct dcerpc_pipe *p = ctx->spoolss_pipe;
383 struct dcerpc_binding_handle *b = p->binding_handle;
384 struct spoolss_GetPrintProcessorDirectory r;
399 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
402 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
408 for (i=0;i<ARRAY_SIZE(levels);i++) {
409 int level = levels[i].level;
412 r.in.server = levels[i].server;
413 r.in.environment = ctx->environment;
417 r.out.needed = &needed;
419 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
421 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
422 torture_assert_ntstatus_ok(tctx, status,
423 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
424 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
425 "GetPrintProcessorDirectory unexpected return code");
427 blob = data_blob_talloc_zero(tctx, needed);
429 r.in.offered = needed;
431 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
432 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
434 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
436 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, needed, 2);
443 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
446 struct test_spoolss_context *ctx =
447 talloc_get_type_abort(private_data, struct test_spoolss_context);
450 struct dcerpc_pipe *p = ctx->spoolss_pipe;
451 struct dcerpc_binding_handle *b = p->binding_handle;
452 struct spoolss_GetPrinterDriverDirectory r;
467 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
470 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
476 for (i=0;i<ARRAY_SIZE(levels);i++) {
477 int level = levels[i].level;
480 r.in.server = levels[i].server;
481 r.in.environment = ctx->environment;
485 r.out.needed = &needed;
487 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
489 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
490 torture_assert_ntstatus_ok(tctx, status,
491 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
492 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
493 "GetPrinterDriverDirectory unexpected return code");
495 blob = data_blob_talloc_zero(tctx, needed);
497 r.in.offered = needed;
499 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
500 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
502 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
504 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, needed, 2);
510 static bool test_EnumPrinterDrivers_args(struct torture_context *tctx,
511 struct dcerpc_binding_handle *b,
512 const char *server_name,
513 const char *environment,
516 union spoolss_DriverInfo **info_p)
518 struct spoolss_EnumPrinterDrivers r;
521 union spoolss_DriverInfo *info;
523 r.in.server = server_name;
524 r.in.environment = environment;
528 r.out.needed = &needed;
529 r.out.count = &count;
532 torture_comment(tctx, "Testing EnumPrinterDrivers(%s) level %u\n",
533 r.in.environment, r.in.level);
535 torture_assert_ntstatus_ok(tctx,
536 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
537 "EnumPrinterDrivers failed");
538 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
539 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
541 r.in.offered = needed;
543 torture_assert_ntstatus_ok(tctx,
544 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
545 "EnumPrinterDrivers failed");
548 torture_assert_werr_ok(tctx, r.out.result,
549 "EnumPrinterDrivers failed");
558 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, needed, 4);
564 static bool test_EnumPrinterDrivers_findone(struct torture_context *tctx,
565 struct dcerpc_binding_handle *b,
566 const char *server_name,
567 const char *environment,
569 const char *driver_name,
570 union spoolss_DriverInfo *info_p)
573 union spoolss_DriverInfo *info;
575 const char *environment_ret = NULL;
578 test_EnumPrinterDrivers_args(tctx, b, server_name, environment, level, &count, &info),
579 "failed to enumerate printer drivers");
581 for (i=0; i < count; i++) {
582 const char *driver_name_ret;
585 driver_name_ret = info[i].info1.driver_name;
588 driver_name_ret = info[i].info2.driver_name;
589 environment_ret = info[i].info2.architecture;
592 driver_name_ret = info[i].info3.driver_name;
593 environment_ret = info[i].info3.architecture;
596 driver_name_ret = info[i].info4.driver_name;
597 environment_ret = info[i].info4.architecture;
600 driver_name_ret = info[i].info5.driver_name;
601 environment_ret = info[i].info5.architecture;
604 driver_name_ret = info[i].info6.driver_name;
605 environment_ret = info[i].info6.architecture;
608 driver_name_ret = info[i].info7.driver_name;
611 driver_name_ret = info[i].info8.driver_name;
612 environment_ret = info[i].info8.architecture;
617 if (environment_ret) {
618 torture_assert_str_equal(tctx, environment, environment_ret, "architecture mismatch");
620 if (strequal(driver_name, driver_name_ret)) {
631 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
634 struct test_spoolss_context *ctx =
635 talloc_get_type_abort(private_data, struct test_spoolss_context);
636 struct dcerpc_pipe *p = ctx->spoolss_pipe;
637 struct dcerpc_binding_handle *b = p->binding_handle;
638 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
641 /* FIXME: gd, come back and fix "" as server, and handle
642 * priority of returned error codes in torture test and samba 3
644 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
645 const char *environments[2];
647 environments[0] = SPOOLSS_ARCHITECTURE_ALL;
648 environments[1] = ctx->environment;
650 for (a=0;a<ARRAY_SIZE(environments);a++) {
652 for (i=0;i<ARRAY_SIZE(levels);i++) {
653 int level = levels[i];
655 union spoolss_DriverInfo *info;
658 test_EnumPrinterDrivers_args(tctx, b, server_name, environments[a], level, &count, &info),
659 "failed to enumerate drivers");
661 ctx->driver_count[level] = count;
662 ctx->drivers[level] = info;
665 for (i=1;i<ARRAY_SIZE(levels);i++) {
666 int level = levels[i];
667 int old_level = levels[i-1];
669 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
670 "EnumPrinterDrivers invalid value");
673 for (i=0;i<ARRAY_SIZE(levels);i++) {
674 int level = levels[i];
676 for (j=0;j<ctx->driver_count[level];j++) {
677 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
678 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
682 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
685 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
686 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
687 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
688 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
689 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
690 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
693 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
694 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
695 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
696 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
697 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
698 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
699 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
700 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
701 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
702 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
705 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
706 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
707 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
708 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
709 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
710 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
711 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
712 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
713 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
714 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
715 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
718 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
719 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
720 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
721 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
722 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
723 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
724 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
725 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
726 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
729 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
730 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
731 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
732 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
733 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
734 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
735 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
736 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
737 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
738 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
739 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
740 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
741 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
742 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
743 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
744 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
745 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
748 /* level 8 is our reference, and it makes no sense to compare it to itself */
758 static bool test_EnumMonitors(struct torture_context *tctx,
761 struct test_spoolss_context *ctx =
762 talloc_get_type_abort(private_data, struct test_spoolss_context);
763 struct dcerpc_pipe *p = ctx->spoolss_pipe;
764 struct dcerpc_binding_handle *b = p->binding_handle;
766 struct spoolss_EnumMonitors r;
767 uint16_t levels[] = { 1, 2 };
770 for (i=0;i<ARRAY_SIZE(levels);i++) {
771 int level = levels[i];
775 union spoolss_MonitorInfo *info;
777 r.in.servername = "";
781 r.out.needed = &needed;
782 r.out.count = &count;
785 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
787 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
788 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
789 if (W_ERROR_IS_OK(r.out.result)) {
790 /* TODO: do some more checks here */
793 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
794 "EnumMonitors failed");
796 blob = data_blob_talloc_zero(ctx, needed);
798 r.in.offered = needed;
800 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
801 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
803 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
805 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, needed, 4);
807 ctx->monitor_count[level] = count;
808 ctx->monitors[level] = info;
811 for (i=1;i<ARRAY_SIZE(levels);i++) {
812 int level = levels[i];
813 int old_level = levels[i-1];
814 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
815 "EnumMonitors invalid value");
818 for (i=0;i<ARRAY_SIZE(levels);i++) {
819 int level = levels[i];
820 for (j=0;j<ctx->monitor_count[level];j++) {
821 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
822 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
825 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
828 /* level 2 is our reference, and it makes no sense to compare it to itself */
837 static bool test_EnumPrintProcessors_level(struct torture_context *tctx,
838 struct dcerpc_binding_handle *b,
839 const char *environment,
842 union spoolss_PrintProcessorInfo **info_p,
843 WERROR expected_result)
845 struct spoolss_EnumPrintProcessors r;
849 union spoolss_PrintProcessorInfo *info;
851 r.in.servername = "";
852 r.in.environment = environment;
856 r.out.needed = &needed;
857 r.out.count = &count;
860 torture_comment(tctx, "Testing EnumPrintProcessors(%s) level %u\n",
861 r.in.environment, r.in.level);
863 torture_assert_ntstatus_ok(tctx,
864 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
865 "EnumPrintProcessors failed");
866 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
867 blob = data_blob_talloc_zero(tctx, needed);
869 r.in.offered = needed;
870 torture_assert_ntstatus_ok(tctx,
871 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
872 "EnumPrintProcessors failed");
874 torture_assert_werr_equal(tctx, r.out.result, expected_result,
875 "EnumPrintProcessors failed");
877 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, level, count, needed, 4);
889 static bool test_EnumPrintProcessors(struct torture_context *tctx,
892 struct test_spoolss_context *ctx =
893 talloc_get_type_abort(private_data, struct test_spoolss_context);
895 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
896 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
898 struct dcerpc_pipe *p = ctx->spoolss_pipe;
899 struct dcerpc_binding_handle *b = p->binding_handle;
902 test_EnumPrintProcessors_level(tctx, b, "phantasy", 1, NULL, NULL, WERR_INVALID_ENVIRONMENT),
903 "test_EnumPrintProcessors_level failed");
905 for (i=0;i<ARRAY_SIZE(levels);i++) {
906 union spoolss_PrintProcessorInfo *info;
908 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
911 test_EnumPrintProcessors_level(tctx, b, ctx->environment, levels[i], &count, &info, expected_result),
912 "test_EnumPrintProcessors_level failed");
918 static bool test_EnumPrintProcDataTypes_level(struct torture_context *tctx,
919 struct dcerpc_binding_handle *b,
920 const char *print_processor_name,
923 union spoolss_PrintProcDataTypesInfo **info_p,
924 WERROR expected_result)
926 struct spoolss_EnumPrintProcDataTypes r;
930 union spoolss_PrintProcDataTypesInfo *info;
932 r.in.servername = "";
933 r.in.print_processor_name = print_processor_name;
937 r.out.needed = &needed;
938 r.out.count = &count;
941 torture_comment(tctx, "Testing EnumPrintProcDataTypes(%s) level %u\n",
942 r.in.print_processor_name, r.in.level);
944 torture_assert_ntstatus_ok(tctx,
945 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
946 "EnumPrintProcDataTypes failed");
947 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
948 blob = data_blob_talloc_zero(tctx, needed);
950 r.in.offered = needed;
951 torture_assert_ntstatus_ok(tctx,
952 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
953 "EnumPrintProcDataTypes failed");
955 torture_assert_werr_equal(tctx, r.out.result, expected_result,
956 "EnumPrintProcDataTypes failed");
958 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, level, count, needed, 4);
970 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
973 struct test_spoolss_context *ctx =
974 talloc_get_type_abort(private_data, struct test_spoolss_context);
976 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
977 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
979 struct dcerpc_pipe *p = ctx->spoolss_pipe;
980 struct dcerpc_binding_handle *b = p->binding_handle;
983 test_EnumPrintProcDataTypes_level(tctx, b, NULL, 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
984 "test_EnumPrintProcDataTypes_level failed");
987 test_EnumPrintProcDataTypes_level(tctx, b, "nonexisting", 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
988 "test_EnumPrintProcDataTypes_level failed");
990 for (i=0;i<ARRAY_SIZE(levels);i++) {
991 int level = levels[i];
993 union spoolss_PrintProcDataTypesInfo *info;
994 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
997 test_EnumPrintProcDataTypes_level(tctx, b, "winprint", level, &count, &info, expected_result),
998 "test_EnumPrintProcDataTypes_level failed");
1002 union spoolss_PrintProcessorInfo *info;
1005 torture_assert(tctx,
1006 test_EnumPrintProcessors_level(tctx, b, ctx->environment, 1, &count, &info, WERR_OK),
1007 "test_EnumPrintProcessors_level failed");
1009 for (i=0; i < count; i++) {
1010 torture_assert(tctx,
1011 test_EnumPrintProcDataTypes_level(tctx, b, info[i].info1.print_processor_name, 1, NULL, NULL, WERR_OK),
1012 "test_EnumPrintProcDataTypes_level failed");
1020 static bool test_EnumPrinters(struct torture_context *tctx,
1023 struct test_spoolss_context *ctx =
1024 talloc_get_type_abort(private_data, struct test_spoolss_context);
1025 struct dcerpc_pipe *p = ctx->spoolss_pipe;
1026 struct dcerpc_binding_handle *b = p->binding_handle;
1027 struct spoolss_EnumPrinters r;
1029 uint16_t levels[] = { 0, 1, 2, 4, 5 };
1032 for (i=0;i<ARRAY_SIZE(levels);i++) {
1033 int level = levels[i];
1037 union spoolss_PrinterInfo *info;
1039 r.in.flags = PRINTER_ENUM_LOCAL;
1044 r.out.needed = &needed;
1045 r.out.count = &count;
1048 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1050 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1051 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1052 if (W_ERROR_IS_OK(r.out.result)) {
1053 /* TODO: do some more checks here */
1056 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
1057 "EnumPrinters unexpected return code");
1059 blob = data_blob_talloc_zero(ctx, needed);
1060 r.in.buffer = &blob;
1061 r.in.offered = needed;
1063 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1064 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1066 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1068 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
1070 ctx->printer_count[level] = count;
1071 ctx->printers[level] = info;
1074 for (i=1;i<ARRAY_SIZE(levels);i++) {
1075 int level = levels[i];
1076 int old_level = levels[i-1];
1077 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
1078 "EnumPrinters invalid value");
1081 for (i=0;i<ARRAY_SIZE(levels);i++) {
1082 int level = levels[i];
1083 for (j=0;j<ctx->printer_count[level];j++) {
1084 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
1085 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
1088 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
1089 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
1090 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
1091 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
1092 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
1093 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
1094 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
1095 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
1096 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
1097 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
1098 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
1099 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
1100 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
1101 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
1102 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
1103 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
1104 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
1105 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
1106 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
1107 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
1108 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
1109 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
1110 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
1111 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
1112 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
1113 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
1114 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
1115 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
1116 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
1119 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
1120 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
1121 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
1122 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
1125 /* level 2 is our reference, and it makes no sense to compare it to itself */
1128 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
1129 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
1130 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
1133 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
1134 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
1135 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
1136 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
1137 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
1144 * - verify that the port of a printer was in the list returned by EnumPorts
1150 static bool test_GetPrinterDriver2(struct torture_context *tctx,
1151 struct dcerpc_binding_handle *b,
1152 struct policy_handle *handle,
1153 const char *driver_name,
1154 const char *environment);
1156 bool test_GetPrinter_level(struct torture_context *tctx,
1157 struct dcerpc_binding_handle *b,
1158 struct policy_handle *handle,
1160 union spoolss_PrinterInfo *info)
1162 struct spoolss_GetPrinter r;
1165 r.in.handle = handle;
1169 r.out.needed = &needed;
1171 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
1173 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1174 "GetPrinter failed");
1176 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1177 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
1178 r.in.buffer = &blob;
1179 r.in.offered = needed;
1181 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1182 "GetPrinter failed");
1185 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
1187 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, needed, 4);
1189 if (info && r.out.info) {
1190 *info = *r.out.info;
1197 static bool test_GetPrinter(struct torture_context *tctx,
1198 struct dcerpc_binding_handle *b,
1199 struct policy_handle *handle,
1200 const char *environment)
1202 uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1205 for (i=0;i<ARRAY_SIZE(levels);i++) {
1207 union spoolss_PrinterInfo info;
1211 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
1212 "failed to call GetPrinter");
1214 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
1215 torture_assert(tctx,
1216 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
1217 "failed to call test_GetPrinterDriver2");
1224 static bool test_SetPrinter(struct torture_context *tctx,
1225 struct dcerpc_binding_handle *b,
1226 struct policy_handle *handle,
1227 struct spoolss_SetPrinterInfoCtr *info_ctr,
1228 struct spoolss_DevmodeContainer *devmode_ctr,
1229 struct sec_desc_buf *secdesc_ctr,
1230 enum spoolss_PrinterControl command)
1232 struct spoolss_SetPrinter r;
1234 r.in.handle = handle;
1235 r.in.info_ctr = info_ctr;
1236 r.in.devmode_ctr = devmode_ctr;
1237 r.in.secdesc_ctr = secdesc_ctr;
1238 r.in.command = command;
1240 torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1242 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1243 "failed to call SetPrinter");
1244 torture_assert_werr_ok(tctx, r.out.result,
1245 "failed to call SetPrinter");
1250 static bool test_SetPrinter_errors(struct torture_context *tctx,
1251 struct dcerpc_binding_handle *b,
1252 struct policy_handle *handle)
1254 struct spoolss_SetPrinter r;
1255 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1258 struct spoolss_SetPrinterInfoCtr info_ctr;
1259 struct spoolss_DevmodeContainer devmode_ctr;
1260 struct sec_desc_buf secdesc_ctr;
1263 info_ctr.info.info0 = NULL;
1265 ZERO_STRUCT(devmode_ctr);
1266 ZERO_STRUCT(secdesc_ctr);
1268 r.in.handle = handle;
1269 r.in.info_ctr = &info_ctr;
1270 r.in.devmode_ctr = &devmode_ctr;
1271 r.in.secdesc_ctr = &secdesc_ctr;
1274 torture_comment(tctx, "Testing SetPrinter all zero\n");
1276 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1277 "failed to call SetPrinter");
1278 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1279 "failed to call SetPrinter");
1282 for (i=0; i < ARRAY_SIZE(levels); i++) {
1284 struct spoolss_SetPrinterInfo0 info0;
1285 struct spoolss_SetPrinterInfo1 info1;
1286 struct spoolss_SetPrinterInfo2 info2;
1287 struct spoolss_SetPrinterInfo3 info3;
1288 struct spoolss_SetPrinterInfo4 info4;
1289 struct spoolss_SetPrinterInfo5 info5;
1290 struct spoolss_SetPrinterInfo6 info6;
1291 struct spoolss_SetPrinterInfo7 info7;
1292 struct spoolss_SetPrinterInfo8 info8;
1293 struct spoolss_SetPrinterInfo9 info9;
1296 info_ctr.level = levels[i];
1297 switch (levels[i]) {
1300 info_ctr.info.info0 = &info0;
1304 info_ctr.info.info1 = &info1;
1308 info_ctr.info.info2 = &info2;
1312 info_ctr.info.info3 = &info3;
1316 info_ctr.info.info4 = &info4;
1320 info_ctr.info.info5 = &info5;
1324 info_ctr.info.info6 = &info6;
1328 info_ctr.info.info7 = &info7;
1332 info_ctr.info.info8 = &info8;
1336 info_ctr.info.info9 = &info9;
1340 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1341 info_ctr.level, r.in.command);
1343 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1344 "failed to call SetPrinter");
1346 switch (r.in.command) {
1347 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1348 /* is ignored for all levels other then 0 */
1349 if (info_ctr.level > 0) {
1353 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1354 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1355 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1356 if (info_ctr.level > 0) {
1357 /* is invalid for all levels other then 0 */
1358 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1359 "unexpected error code returned");
1362 torture_assert_werr_ok(tctx, r.out.result,
1363 "failed to call SetPrinter with non 0 command");
1368 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1369 /* FIXME: gd needs further investigation */
1371 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1372 "unexpected error code returned");
1376 switch (info_ctr.level) {
1378 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1379 "unexpected error code returned");
1382 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1383 "unexpected error code returned");
1389 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1390 "unexpected error code returned");
1393 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1394 "unexpected error code returned");
1397 torture_assert_werr_ok(tctx, r.out.result,
1398 "failed to call SetPrinter");
1403 if (r.in.command < 5) {
1411 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1413 if ((r->level == 2) && (r->info.info2)) {
1414 r->info.info2->secdesc_ptr = 0;
1415 r->info.info2->devmode_ptr = 0;
1419 static bool test_PrinterInfo(struct torture_context *tctx,
1420 struct dcerpc_binding_handle *b,
1421 struct policy_handle *handle)
1424 struct spoolss_SetPrinter s;
1425 struct spoolss_GetPrinter q;
1426 struct spoolss_GetPrinter q0;
1427 struct spoolss_SetPrinterInfoCtr info_ctr;
1428 union spoolss_PrinterInfo info;
1429 struct spoolss_DevmodeContainer devmode_ctr;
1430 struct sec_desc_buf secdesc_ctr;
1435 torture_skip(tctx, "Printer Info test is currently broken, skipping");
1437 uint32_t status_list[] = {
1438 /* these do not stick
1439 PRINTER_STATUS_PAUSED,
1440 PRINTER_STATUS_ERROR,
1441 PRINTER_STATUS_PENDING_DELETION, */
1442 PRINTER_STATUS_PAPER_JAM,
1443 PRINTER_STATUS_PAPER_OUT,
1444 PRINTER_STATUS_MANUAL_FEED,
1445 PRINTER_STATUS_PAPER_PROBLEM,
1446 PRINTER_STATUS_OFFLINE,
1447 PRINTER_STATUS_IO_ACTIVE,
1448 PRINTER_STATUS_BUSY,
1449 PRINTER_STATUS_PRINTING,
1450 PRINTER_STATUS_OUTPUT_BIN_FULL,
1451 PRINTER_STATUS_NOT_AVAILABLE,
1452 PRINTER_STATUS_WAITING,
1453 PRINTER_STATUS_PROCESSING,
1454 PRINTER_STATUS_INITIALIZING,
1455 PRINTER_STATUS_WARMING_UP,
1456 PRINTER_STATUS_TONER_LOW,
1457 PRINTER_STATUS_NO_TONER,
1458 PRINTER_STATUS_PAGE_PUNT,
1459 PRINTER_STATUS_USER_INTERVENTION,
1460 PRINTER_STATUS_OUT_OF_MEMORY,
1461 PRINTER_STATUS_DOOR_OPEN,
1462 PRINTER_STATUS_SERVER_UNKNOWN,
1463 PRINTER_STATUS_POWER_SAVE,
1464 /* these do not stick
1473 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1474 uint32_t attribute_list[] = {
1475 PRINTER_ATTRIBUTE_QUEUED,
1476 /* fails with WERR_INVALID_DATATYPE:
1477 PRINTER_ATTRIBUTE_DIRECT, */
1479 PRINTER_ATTRIBUTE_DEFAULT, */
1480 PRINTER_ATTRIBUTE_SHARED,
1482 PRINTER_ATTRIBUTE_NETWORK, */
1483 PRINTER_ATTRIBUTE_HIDDEN,
1484 PRINTER_ATTRIBUTE_LOCAL,
1485 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1486 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1487 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1488 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1490 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1491 /* fails with WERR_INVALID_DATATYPE:
1492 PRINTER_ATTRIBUTE_RAW_ONLY, */
1493 /* these do not stick
1494 PRINTER_ATTRIBUTE_PUBLISHED,
1495 PRINTER_ATTRIBUTE_FAX,
1496 PRINTER_ATTRIBUTE_TS,
1515 ZERO_STRUCT(devmode_ctr);
1516 ZERO_STRUCT(secdesc_ctr);
1518 s.in.handle = handle;
1520 s.in.info_ctr = &info_ctr;
1521 s.in.devmode_ctr = &devmode_ctr;
1522 s.in.secdesc_ctr = &secdesc_ctr;
1524 q.in.handle = handle;
1528 #define TESTGETCALL(call, r) \
1529 r.in.buffer = NULL; \
1531 r.out.needed = &needed; \
1532 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1533 if (!NT_STATUS_IS_OK(status)) { \
1534 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1535 r.in.level, nt_errstr(status), __location__); \
1539 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1540 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1541 r.in.buffer = &blob; \
1542 r.in.offered = needed; \
1544 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1545 if (!NT_STATUS_IS_OK(status)) { \
1546 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1547 r.in.level, nt_errstr(status), __location__); \
1551 if (!W_ERROR_IS_OK(r.out.result)) { \
1552 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1553 r.in.level, win_errstr(r.out.result), __location__); \
1559 #define TESTSETCALL_EXP(call, r, err) \
1560 clear_info2(&info_ctr);\
1561 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1562 if (!NT_STATUS_IS_OK(status)) { \
1563 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1564 r.in.info_ctr->level, nt_errstr(status), __location__); \
1568 if (!W_ERROR_IS_OK(err)) { \
1569 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1570 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1571 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1576 if (!W_ERROR_IS_OK(r.out.result)) { \
1577 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1578 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1583 #define TESTSETCALL(call, r) \
1584 TESTSETCALL_EXP(call, r, WERR_OK)
1586 #define STRING_EQUAL(s1, s2, field) \
1587 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1588 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1589 #field, s2, __location__); \
1594 #define MEM_EQUAL(s1, s2, length, field) \
1595 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1596 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1597 #field, (const char *)s2, __location__); \
1602 #define INT_EQUAL(i1, i2, field) \
1604 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1605 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1610 #define SD_EQUAL(sd1, sd2, field) \
1611 if (!security_descriptor_equal(sd1, sd2)) { \
1612 torture_comment(tctx, "Failed to set %s (%s)\n", \
1613 #field, __location__); \
1618 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1619 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1620 q.in.level = lvl1; \
1621 TESTGETCALL(GetPrinter, q) \
1622 info_ctr.level = lvl1; \
1623 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1624 info_ctr.info.info ## lvl1->field1 = value;\
1625 TESTSETCALL_EXP(SetPrinter, s, err) \
1626 info_ctr.info.info ## lvl1->field1 = ""; \
1627 TESTGETCALL(GetPrinter, q) \
1628 info_ctr.info.info ## lvl1->field1 = value; \
1629 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1630 q.in.level = lvl2; \
1631 TESTGETCALL(GetPrinter, q) \
1632 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1633 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1636 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1637 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1640 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1641 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1642 q.in.level = lvl1; \
1643 TESTGETCALL(GetPrinter, q) \
1644 info_ctr.level = lvl1; \
1645 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1646 info_ctr.info.info ## lvl1->field1 = value; \
1647 TESTSETCALL(SetPrinter, s) \
1648 info_ctr.info.info ## lvl1->field1 = 0; \
1649 TESTGETCALL(GetPrinter, q) \
1650 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1651 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1652 q.in.level = lvl2; \
1653 TESTGETCALL(GetPrinter, q) \
1654 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1655 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1658 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1659 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1663 do { TESTGETCALL(GetPrinter, q0) } while (0);
1665 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1666 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1668 /* level 0 printername does not stick */
1669 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1670 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1671 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1672 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1673 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1674 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1675 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1676 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1677 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1678 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1679 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1680 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1681 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1682 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1683 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1685 /* servername can be set but does not stick
1686 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1687 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1688 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1691 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1692 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1693 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1694 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1695 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1697 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1698 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1699 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1700 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1701 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1702 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1703 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1704 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1705 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1706 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1708 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1709 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1711 (attribute_list[i] | default_attribute)
1713 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1715 (attribute_list[i] | default_attribute)
1717 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1719 (attribute_list[i] | default_attribute)
1721 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1723 (attribute_list[i] | default_attribute)
1725 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1727 (attribute_list[i] | default_attribute)
1729 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1731 (attribute_list[i] | default_attribute)
1733 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1735 (attribute_list[i] | default_attribute)
1737 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1739 (attribute_list[i] | default_attribute)
1741 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1743 (attribute_list[i] | default_attribute)
1745 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1747 (attribute_list[i] | default_attribute)
1749 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1751 (attribute_list[i] | default_attribute)
1753 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1755 (attribute_list[i] | default_attribute)
1759 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1760 /* level 2 sets do not stick
1761 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1762 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1763 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1764 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1765 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1766 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1769 /* priorities need to be between 0 and 99
1770 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1771 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1772 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1773 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1774 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1775 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1776 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1777 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1778 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1780 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1781 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1784 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1785 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1788 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1789 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1791 /* FIXME: gd also test devmode and secdesc behavior */
1794 /* verify composition of level 1 description field */
1795 const char *description;
1799 do { TESTGETCALL(GetPrinter, q0) } while (0);
1801 description = talloc_strdup(tctx, q0.out.info->info1.description);
1804 do { TESTGETCALL(GetPrinter, q0) } while (0);
1806 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1807 q0.out.info->info2.printername,
1808 q0.out.info->info2.drivername,
1809 q0.out.info->info2.location);
1811 do { STRING_EQUAL(description, tmp, "description")} while (0);
1817 static bool test_security_descriptor_equal(struct torture_context *tctx,
1818 const struct security_descriptor *sd1,
1819 const struct security_descriptor *sd2)
1826 torture_comment(tctx, "%s\n", __location__);
1830 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1831 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1833 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1834 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1836 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1837 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1838 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1839 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1842 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1843 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1844 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1845 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1852 static bool test_sd_set_level(struct torture_context *tctx,
1853 struct dcerpc_binding_handle *b,
1854 struct policy_handle *handle,
1856 struct security_descriptor *sd)
1858 struct spoolss_SetPrinterInfoCtr info_ctr;
1859 struct spoolss_DevmodeContainer devmode_ctr;
1860 struct sec_desc_buf secdesc_ctr;
1861 union spoolss_SetPrinterInfo sinfo;
1863 ZERO_STRUCT(devmode_ctr);
1864 ZERO_STRUCT(secdesc_ctr);
1868 union spoolss_PrinterInfo info;
1869 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1870 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1873 info_ctr.info = sinfo;
1878 struct spoolss_SetPrinterInfo3 info3;
1880 info3.sec_desc_ptr = 0;
1883 info_ctr.info.info3 = &info3;
1891 secdesc_ctr.sd = sd;
1893 torture_assert(tctx,
1894 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1899 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1900 struct dcerpc_binding_handle *b,
1901 struct policy_handle *handle)
1903 union spoolss_PrinterInfo info;
1904 struct security_descriptor *sd1, *sd2;
1907 /* just compare level 2 and level 3 */
1909 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1911 sd1 = info.info2.secdesc;
1913 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1915 sd2 = info.info3.secdesc;
1917 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1918 "SD level 2 != SD level 3");
1921 /* query level 2, set level 2, query level 2 */
1923 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1925 sd1 = info.info2.secdesc;
1927 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1929 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1931 sd2 = info.info2.secdesc;
1932 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1933 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1934 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1937 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1938 "SD level 2 != SD level 2 after SD has been set via level 2");
1941 /* query level 2, set level 3, query level 2 */
1943 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1945 sd1 = info.info2.secdesc;
1947 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1949 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1951 sd2 = info.info2.secdesc;
1953 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1954 "SD level 2 != SD level 2 after SD has been set via level 3");
1956 /* set modified sd level 3, query level 2 */
1958 for (i=0; i < 93; i++) {
1959 struct security_ace a;
1960 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1961 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1963 a.size = 0; /* autogenerated */
1965 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1966 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1969 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1971 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1972 sd2 = info.info2.secdesc;
1974 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1975 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1976 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1979 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1980 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1987 * wrapper call that saves original sd, runs tests, and restores sd
1990 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1991 struct dcerpc_binding_handle *b,
1992 struct policy_handle *handle)
1994 union spoolss_PrinterInfo info;
1995 struct security_descriptor *sd;
1998 torture_comment(tctx, "Testing Printer Security Descriptors\n");
2000 /* save original sd */
2002 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
2003 "failed to get initial security descriptor");
2005 sd = security_descriptor_copy(tctx, info.info2.secdesc);
2009 ret = test_PrinterInfo_SDs(tctx, b, handle);
2011 /* restore original sd */
2013 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
2014 "failed to restore initial security descriptor");
2016 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
2017 ret ? "succeeded" : "failed");
2023 static bool test_devmode_set_level(struct torture_context *tctx,
2024 struct dcerpc_binding_handle *b,
2025 struct policy_handle *handle,
2027 struct spoolss_DeviceMode *devmode)
2029 struct spoolss_SetPrinterInfoCtr info_ctr;
2030 struct spoolss_DevmodeContainer devmode_ctr;
2031 struct sec_desc_buf secdesc_ctr;
2032 union spoolss_SetPrinterInfo sinfo;
2034 ZERO_STRUCT(devmode_ctr);
2035 ZERO_STRUCT(secdesc_ctr);
2039 union spoolss_PrinterInfo info;
2040 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2041 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
2044 info_ctr.info = sinfo;
2049 struct spoolss_SetPrinterInfo8 info8;
2051 info8.devmode_ptr = 0;
2054 info_ctr.info.info8 = &info8;
2062 devmode_ctr.devmode = devmode;
2064 torture_assert(tctx,
2065 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
2071 static bool test_devicemode_equal(struct torture_context *tctx,
2072 const struct spoolss_DeviceMode *d1,
2073 const struct spoolss_DeviceMode *d2)
2080 torture_comment(tctx, "%s\n", __location__);
2083 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
2084 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
2085 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
2086 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
2087 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
2088 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
2089 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
2090 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
2091 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
2092 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
2093 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
2094 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
2095 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
2096 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2097 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2098 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2099 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2100 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2101 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2102 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2103 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2104 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2105 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2106 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2107 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2108 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2109 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2110 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2111 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2112 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2113 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2114 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2115 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2116 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2117 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2122 static bool test_devicemode_full(struct torture_context *tctx,
2123 struct dcerpc_binding_handle *b,
2124 struct policy_handle *handle)
2126 struct spoolss_SetPrinter s;
2127 struct spoolss_GetPrinter q;
2128 struct spoolss_GetPrinter q0;
2129 struct spoolss_SetPrinterInfoCtr info_ctr;
2130 struct spoolss_SetPrinterInfo8 info8;
2131 union spoolss_PrinterInfo info;
2132 struct spoolss_DevmodeContainer devmode_ctr;
2133 struct sec_desc_buf secdesc_ctr;
2138 #define TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, exp_value, expected_result) do { \
2139 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2140 q.in.level = lvl1; \
2141 TESTGETCALL(GetPrinter, q) \
2142 info_ctr.level = lvl1; \
2144 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
2145 } else if (lvl1 == 8) {\
2146 info_ctr.info.info ## lvl1 = &info8; \
2148 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2149 devmode_ctr.devmode->field1 = value; \
2150 TESTSETCALL_EXP(SetPrinter, s, expected_result) \
2151 if (W_ERROR_IS_OK(expected_result)) { \
2152 TESTGETCALL(GetPrinter, q) \
2153 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2154 q.in.level = lvl2; \
2155 TESTGETCALL(GetPrinter, q) \
2156 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2160 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, expected_result) do { \
2161 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, expected_result); \
2164 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2165 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, WERR_OK); \
2168 ZERO_STRUCT(devmode_ctr);
2169 ZERO_STRUCT(secdesc_ctr);
2172 s.in.handle = handle;
2174 s.in.info_ctr = &info_ctr;
2175 s.in.devmode_ctr = &devmode_ctr;
2176 s.in.secdesc_ctr = &secdesc_ctr;
2178 q.in.handle = handle;
2183 const char *devicename;/* [charset(UTF16)] */
2184 enum spoolss_DeviceModeSpecVersion specversion;
2185 uint16_t driverversion;
2186 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2190 TEST_DEVMODE_INT_EXP(8, size, 8, size, __LINE__, WERR_INVALID_PARAM);
2191 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0, WERR_INVALID_PARAM);
2192 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0xffff, WERR_INVALID_PARAM);
2193 TEST_DEVMODE_INT_EXP(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), WERR_INVALID_PARAM);
2194 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2195 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
2196 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
2197 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
2198 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
2199 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
2200 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
2201 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
2202 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
2203 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
2204 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
2205 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
2206 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
2207 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
2209 const char *formname;/* [charset(UTF16)] */
2211 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
2212 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
2213 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
2214 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
2215 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
2216 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
2217 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
2218 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
2219 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
2220 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
2221 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
2222 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
2223 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
2224 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
2229 static bool call_OpenPrinterEx(struct torture_context *tctx,
2230 struct dcerpc_pipe *p,
2232 struct spoolss_DeviceMode *devmode,
2233 struct policy_handle *handle);
2235 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2236 struct dcerpc_pipe *p,
2237 struct policy_handle *handle,
2240 union spoolss_PrinterInfo info;
2241 struct spoolss_DeviceMode *devmode;
2242 struct spoolss_DeviceMode *devmode2;
2243 struct policy_handle handle_devmode;
2244 struct dcerpc_binding_handle *b = p->binding_handle;
2246 /* simply compare level8 and level2 devmode */
2248 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2250 devmode = info.info8.devmode;
2252 if (devmode && devmode->size == 0) {
2254 "devmode of zero size!");
2257 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2259 devmode2 = info.info2.devmode;
2261 if (devmode2 && devmode2->size == 0) {
2263 "devmode of zero size!");
2266 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2267 "DM level 8 != DM level 2");
2270 /* set devicemode level 8 and see if it persists */
2272 devmode->copies = 93;
2273 devmode->formname = talloc_strdup(tctx, "Legal");
2275 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2277 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2279 devmode2 = info.info8.devmode;
2281 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2282 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2284 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2286 devmode2 = info.info2.devmode;
2288 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2289 "modified DM level 8 != DM level 2");
2292 /* set devicemode level 2 and see if it persists */
2294 devmode->copies = 39;
2295 devmode->formname = talloc_strdup(tctx, "Executive");
2297 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2299 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2301 devmode2 = info.info8.devmode;
2303 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2304 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2306 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2308 devmode2 = info.info2.devmode;
2310 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2311 "modified DM level 8 != DM level 2");
2314 /* check every single bit in public part of devicemode */
2316 torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2317 "failed to set every single devicemode component");
2320 /* change formname upon open and see if it persists in getprinter calls */
2322 devmode->formname = talloc_strdup(tctx, "A4");
2323 devmode->copies = 42;
2325 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2326 "failed to open printer handle");
2328 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2330 devmode2 = info.info8.devmode;
2332 if (strequal(devmode->devicename, devmode2->devicename)) {
2333 torture_warning(tctx, "devicenames are the same\n");
2335 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2336 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2339 if (strequal(devmode->formname, devmode2->formname)) {
2340 torture_warning(tctx, "formname are the same\n");
2342 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2343 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2346 if (devmode->copies == devmode2->copies) {
2347 torture_warning(tctx, "copies are the same\n");
2349 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2350 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2353 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2355 devmode2 = info.info2.devmode;
2357 if (strequal(devmode->devicename, devmode2->devicename)) {
2358 torture_warning(tctx, "devicenames are the same\n");
2360 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2361 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2364 if (strequal(devmode->formname, devmode2->formname)) {
2365 torture_warning(tctx, "formname is the same\n");
2367 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2368 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2371 if (devmode->copies == devmode2->copies) {
2372 torture_warning(tctx, "copies are the same\n");
2374 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2375 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2378 test_ClosePrinter(tctx, b, &handle_devmode);
2384 * wrapper call that saves original devmode, runs tests, and restores devmode
2387 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2388 struct dcerpc_pipe *p,
2389 struct policy_handle *handle,
2391 struct spoolss_DeviceMode *addprinter_devmode)
2393 union spoolss_PrinterInfo info;
2394 struct spoolss_DeviceMode *devmode;
2396 struct dcerpc_binding_handle *b = p->binding_handle;
2398 torture_comment(tctx, "Testing Printer Devicemodes\n");
2400 /* save original devmode */
2402 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2403 "failed to get initial global devicemode");
2405 devmode = info.info8.devmode;
2407 if (devmode && devmode->size == 0) {
2409 "devmode of zero size!");
2412 if (addprinter_devmode) {
2413 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
2414 torture_warning(tctx, "current global DM is != DM provided in addprinter");
2420 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2422 /* restore original devmode */
2424 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2425 "failed to restore initial global device mode");
2427 torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2428 ret ? "succeeded" : "failed");
2434 bool test_ClosePrinter(struct torture_context *tctx,
2435 struct dcerpc_binding_handle *b,
2436 struct policy_handle *handle)
2439 struct spoolss_ClosePrinter r;
2441 r.in.handle = handle;
2442 r.out.handle = handle;
2444 torture_comment(tctx, "Testing ClosePrinter\n");
2446 status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2447 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2448 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2453 static bool test_GetForm_args(struct torture_context *tctx,
2454 struct dcerpc_binding_handle *b,
2455 struct policy_handle *handle,
2456 const char *form_name,
2458 union spoolss_FormInfo *info_p)
2461 struct spoolss_GetForm r;
2464 r.in.handle = handle;
2465 r.in.form_name = form_name;
2469 r.out.needed = &needed;
2471 torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2473 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2474 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2476 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2477 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2478 r.in.buffer = &blob;
2479 r.in.offered = needed;
2480 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2481 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2483 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2485 torture_assert(tctx, r.out.info, "No form info returned");
2488 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2490 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
2493 *info_p = *r.out.info;
2499 static bool test_GetForm(struct torture_context *tctx,
2500 struct dcerpc_binding_handle *b,
2501 struct policy_handle *handle,
2502 const char *form_name,
2505 return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2508 static bool test_EnumForms(struct torture_context *tctx,
2509 struct dcerpc_binding_handle *b,
2510 struct policy_handle *handle,
2514 union spoolss_FormInfo **info_p)
2516 struct spoolss_EnumForms r;
2519 union spoolss_FormInfo *info;
2521 r.in.handle = handle;
2525 r.out.needed = &needed;
2526 r.out.count = &count;
2529 torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2531 torture_assert_ntstatus_ok(tctx,
2532 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2533 "EnumForms failed");
2535 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2536 torture_skip(tctx, "EnumForms level 2 not supported");
2539 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2540 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2543 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2544 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2545 r.in.buffer = &blob;
2546 r.in.offered = needed;
2548 torture_assert_ntstatus_ok(tctx,
2549 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2550 "EnumForms failed");
2552 torture_assert(tctx, info, "No forms returned");
2555 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2557 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
2569 static bool test_EnumForms_all(struct torture_context *tctx,
2570 struct dcerpc_binding_handle *b,
2571 struct policy_handle *handle,
2574 uint32_t levels[] = { 1, 2 };
2577 for (i=0; i<ARRAY_SIZE(levels); i++) {
2580 union spoolss_FormInfo *info = NULL;
2582 torture_assert(tctx,
2583 test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2584 "failed to enum forms");
2586 for (j = 0; j < count; j++) {
2587 if (!print_server) {
2588 torture_assert(tctx,
2589 test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2590 "failed to get form");
2598 static bool test_EnumForms_find_one(struct torture_context *tctx,
2599 struct dcerpc_binding_handle *b,
2600 struct policy_handle *handle,
2602 const char *form_name)
2604 union spoolss_FormInfo *info;
2609 torture_assert(tctx,
2610 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2611 "failed to enumerate forms");
2613 for (i=0; i<count; i++) {
2614 if (strequal(form_name, info[i].info1.form_name)) {
2623 static bool test_DeleteForm(struct torture_context *tctx,
2624 struct dcerpc_binding_handle *b,
2625 struct policy_handle *handle,
2626 const char *form_name,
2627 WERROR expected_result)
2629 struct spoolss_DeleteForm r;
2631 r.in.handle = handle;
2632 r.in.form_name = form_name;
2634 torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2636 torture_assert_ntstatus_ok(tctx,
2637 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2638 "DeleteForm failed");
2639 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2640 "DeleteForm gave unexpected result");
2641 if (W_ERROR_IS_OK(r.out.result)) {
2642 torture_assert_ntstatus_ok(tctx,
2643 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2644 "2nd DeleteForm failed");
2645 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2646 "2nd DeleteForm failed");
2652 static bool test_AddForm(struct torture_context *tctx,
2653 struct dcerpc_binding_handle *b,
2654 struct policy_handle *handle,
2656 union spoolss_AddFormInfo *info,
2657 WERROR expected_result)
2659 struct spoolss_AddForm r;
2662 torture_skip(tctx, "only level 1 supported");
2665 r.in.handle = handle;
2669 torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2670 r.in.info.info1->form_name, r.in.level,
2671 r.in.info.info1->flags);
2673 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2675 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2676 "AddForm gave unexpected result");
2678 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2679 "2nd AddForm failed");
2680 if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2681 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2682 "2nd AddForm gave unexpected result");
2684 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2685 "2nd AddForm gave unexpected result");
2691 static bool test_SetForm(struct torture_context *tctx,
2692 struct dcerpc_binding_handle *b,
2693 struct policy_handle *handle,
2694 const char *form_name,
2696 union spoolss_AddFormInfo *info)
2698 struct spoolss_SetForm r;
2700 r.in.handle = handle;
2701 r.in.form_name = form_name;
2705 torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2706 form_name, r.in.level);
2708 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2711 torture_assert_werr_ok(tctx, r.out.result,
2717 static bool test_GetForm_winreg(struct torture_context *tctx,
2718 struct dcerpc_binding_handle *b,
2719 struct policy_handle *handle,
2720 const char *key_name,
2721 const char *form_name,
2722 enum winreg_Type *w_type,
2727 static bool test_Forms_args(struct torture_context *tctx,
2728 struct dcerpc_binding_handle *b,
2729 struct policy_handle *handle,
2731 const char *printer_name,
2732 struct dcerpc_binding_handle *winreg_handle,
2733 struct policy_handle *hive_handle,
2734 const char *form_name,
2735 struct spoolss_AddFormInfo1 *info1,
2736 WERROR expected_add_result,
2737 WERROR expected_delete_result)
2739 union spoolss_FormInfo info;
2740 union spoolss_AddFormInfo add_info;
2742 enum winreg_Type w_type;
2747 add_info.info1 = info1;
2749 torture_assert(tctx,
2750 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2751 "failed to add form");
2753 if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2755 struct spoolss_FormInfo1 i1;
2757 torture_assert(tctx,
2758 test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2759 "failed to get form via winreg");
2761 i1.size.width = IVAL(w_data, 0);
2762 i1.size.height = IVAL(w_data, 4);
2763 i1.area.left = IVAL(w_data, 8);
2764 i1.area.top = IVAL(w_data, 12);
2765 i1.area.right = IVAL(w_data, 16);
2766 i1.area.bottom = IVAL(w_data, 20);
2767 /* skip index here */
2768 i1.flags = IVAL(w_data, 28);
2770 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2771 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2772 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2773 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
2774 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
2775 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
2776 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
2777 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
2778 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2779 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
2782 if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2783 torture_assert(tctx,
2784 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2785 "failed to get added form");
2787 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2788 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2789 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2790 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2791 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2792 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2793 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2795 if (winreg_handle && hive_handle) {
2797 struct spoolss_FormInfo1 i1;
2799 i1.size.width = IVAL(w_data, 0);
2800 i1.size.height = IVAL(w_data, 4);
2801 i1.area.left = IVAL(w_data, 8);
2802 i1.area.top = IVAL(w_data, 12);
2803 i1.area.right = IVAL(w_data, 16);
2804 i1.area.bottom = IVAL(w_data, 20);
2805 /* skip index here */
2806 i1.flags = IVAL(w_data, 28);
2808 torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
2809 torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
2810 torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
2811 torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
2812 torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
2813 torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
2814 torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
2817 add_info.info1->size.width = 1234;
2819 torture_assert(tctx,
2820 test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2821 "failed to set form");
2822 torture_assert(tctx,
2823 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2824 "failed to get setted form");
2826 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2829 if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2830 torture_assert(tctx,
2831 test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2832 "Newly added form not found in enum call");
2835 torture_assert(tctx,
2836 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2837 "failed to delete form");
2842 static bool test_Forms(struct torture_context *tctx,
2843 struct dcerpc_binding_handle *b,
2844 struct policy_handle *handle,
2846 const char *printer_name,
2847 struct dcerpc_binding_handle *winreg_handle,
2848 struct policy_handle *hive_handle)
2850 const struct spoolss_FormSize size = {
2854 const struct spoolss_FormArea area = {
2863 struct spoolss_AddFormInfo1 info1;
2864 WERROR expected_add_result;
2865 WERROR expected_delete_result;
2869 .flags = SPOOLSS_FORM_USER,
2870 .form_name = "testform_user",
2874 .expected_add_result = WERR_OK,
2875 .expected_delete_result = WERR_OK
2878 weird, we can add a builtin form but we can never remove it
2883 .flags = SPOOLSS_FORM_BUILTIN,
2884 .form_name = "testform_builtin",
2888 .expected_add_result = WERR_OK,
2889 .expected_delete_result = WERR_INVALID_PARAM,
2894 .flags = SPOOLSS_FORM_PRINTER,
2895 .form_name = "testform_printer",
2899 .expected_add_result = WERR_OK,
2900 .expected_delete_result = WERR_OK
2904 .flags = SPOOLSS_FORM_USER,
2905 .form_name = "Letter",
2909 .expected_add_result = WERR_FILE_EXISTS,
2910 .expected_delete_result = WERR_INVALID_PARAM
2914 .flags = SPOOLSS_FORM_BUILTIN,
2915 .form_name = "Letter",
2919 .expected_add_result = WERR_FILE_EXISTS,
2920 .expected_delete_result = WERR_INVALID_PARAM
2924 .flags = SPOOLSS_FORM_PRINTER,
2925 .form_name = "Letter",
2929 .expected_add_result = WERR_FILE_EXISTS,
2930 .expected_delete_result = WERR_INVALID_PARAM
2935 .form_name = "invalid_flags",
2939 .expected_add_result = WERR_INVALID_PARAM,
2940 .expected_delete_result = WERR_INVALID_FORM_NAME
2945 for (i=0; i < ARRAY_SIZE(forms); i++) {
2946 torture_assert(tctx,
2947 test_Forms_args(tctx, b, handle, print_server, printer_name,
2948 winreg_handle, hive_handle,
2949 forms[i].info1.form_name,
2951 forms[i].expected_add_result,
2952 forms[i].expected_delete_result),
2953 talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2959 static bool test_EnumPorts_old(struct torture_context *tctx,
2962 struct test_spoolss_context *ctx =
2963 talloc_get_type_abort(private_data, struct test_spoolss_context);
2966 struct spoolss_EnumPorts r;
2969 union spoolss_PortInfo *info;
2970 struct dcerpc_pipe *p = ctx->spoolss_pipe;
2971 struct dcerpc_binding_handle *b = p->binding_handle;
2973 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2974 dcerpc_server_name(p));
2978 r.out.needed = &needed;
2979 r.out.count = &count;
2982 torture_comment(tctx, "Testing EnumPorts\n");
2984 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2986 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2988 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2989 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2990 r.in.buffer = &blob;
2991 r.in.offered = needed;
2993 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2994 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2995 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2997 torture_assert(tctx, info, "No ports returned");
3000 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3002 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
3007 static bool test_AddPort(struct torture_context *tctx,
3010 struct test_spoolss_context *ctx =
3011 talloc_get_type_abort(private_data, struct test_spoolss_context);
3014 struct spoolss_AddPort r;
3015 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3016 struct dcerpc_binding_handle *b = p->binding_handle;
3018 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
3019 dcerpc_server_name(p));
3021 r.in.monitor_name = "foo";
3023 torture_comment(tctx, "Testing AddPort\n");
3025 status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
3027 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
3029 /* win2k3 returns WERR_NOT_SUPPORTED */
3033 if (!W_ERROR_IS_OK(r.out.result)) {
3034 printf("AddPort failed - %s\n", win_errstr(r.out.result));
3043 static bool test_GetJob_args(struct torture_context *tctx,
3044 struct dcerpc_binding_handle *b,
3045 struct policy_handle *handle,
3048 union spoolss_JobInfo *info_p)
3051 struct spoolss_GetJob r;
3052 union spoolss_JobInfo info;
3055 r.in.handle = handle;
3056 r.in.job_id = job_id;
3060 r.out.needed = &needed;
3063 torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
3065 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3066 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3068 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
3071 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3072 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3073 r.in.buffer = &blob;
3074 r.in.offered = needed;
3076 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3077 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3080 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
3081 torture_assert(tctx, r.out.info, "No job info returned");
3083 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
3086 *info_p = *r.out.info;
3092 static bool test_GetJob(struct torture_context *tctx,
3093 struct dcerpc_binding_handle *b,
3094 struct policy_handle *handle,
3097 uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
3100 for (i=0; i < ARRAY_SIZE(levels); i++) {
3101 torture_assert(tctx,
3102 test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
3109 static bool test_SetJob(struct torture_context *tctx,
3110 struct dcerpc_binding_handle *b,
3111 struct policy_handle *handle,
3113 struct spoolss_JobInfoContainer *ctr,
3114 enum spoolss_JobControl command)
3117 struct spoolss_SetJob r;
3119 r.in.handle = handle;
3120 r.in.job_id = job_id;
3122 r.in.command = command;
3125 case SPOOLSS_JOB_CONTROL_PAUSE:
3126 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3128 case SPOOLSS_JOB_CONTROL_RESUME:
3129 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3131 case SPOOLSS_JOB_CONTROL_CANCEL:
3132 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3134 case SPOOLSS_JOB_CONTROL_RESTART:
3135 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3137 case SPOOLSS_JOB_CONTROL_DELETE:
3138 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3140 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3141 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3143 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3144 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3146 case SPOOLSS_JOB_CONTROL_RETAIN:
3147 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3149 case SPOOLSS_JOB_CONTROL_RELEASE:
3150 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3153 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3157 status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3158 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3159 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3164 static bool test_AddJob(struct torture_context *tctx,
3165 struct dcerpc_binding_handle *b,
3166 struct policy_handle *handle)
3169 struct spoolss_AddJob r;
3173 r.in.handle = handle;
3175 r.out.needed = &needed;
3176 r.in.buffer = r.out.buffer = NULL;
3178 torture_comment(tctx, "Testing AddJob\n");
3180 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3181 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3185 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3186 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3192 static bool test_EnumJobs_args(struct torture_context *tctx,
3193 struct dcerpc_binding_handle *b,
3194 struct policy_handle *handle,
3197 union spoolss_JobInfo **info_p)
3200 struct spoolss_EnumJobs r;
3203 union spoolss_JobInfo *info;
3205 r.in.handle = handle;
3207 r.in.numjobs = 0xffffffff;
3211 r.out.needed = &needed;
3212 r.out.count = &count;
3215 torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3217 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3219 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3221 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3222 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3223 r.in.buffer = &blob;
3224 r.in.offered = needed;
3226 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3228 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3229 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3230 torture_assert(tctx, info, "No jobs returned");
3232 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3235 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3248 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3249 struct dcerpc_binding_handle *b,
3250 struct policy_handle *handle,
3254 struct spoolss_StartDocPrinter s;
3255 struct spoolss_DocumentInfo1 info1;
3256 struct spoolss_StartPagePrinter sp;
3257 struct spoolss_WritePrinter w;
3258 struct spoolss_EndPagePrinter ep;
3259 struct spoolss_EndDocPrinter e;
3261 uint32_t num_written;
3263 torture_comment(tctx, "Testing StartDocPrinter\n");
3265 s.in.handle = handle;
3267 s.in.info.info1 = &info1;
3268 s.out.job_id = job_id;
3269 info1.document_name = "TorturePrintJob";
3270 info1.output_file = NULL;
3271 info1.datatype = "RAW";
3273 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3274 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3275 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3277 for (i=1; i < 4; i++) {
3278 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3280 sp.in.handle = handle;
3282 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3283 torture_assert_ntstatus_ok(tctx, status,
3284 "dcerpc_spoolss_StartPagePrinter failed");
3285 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3287 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3289 w.in.handle = handle;
3290 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3291 w.out.num_written = &num_written;
3293 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3294 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3295 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3297 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3299 ep.in.handle = handle;
3301 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3302 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3303 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3306 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3308 e.in.handle = handle;
3310 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3311 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3312 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3317 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3318 struct dcerpc_binding_handle *b,
3319 struct policy_handle *handle,
3324 union spoolss_JobInfo *info = NULL;
3327 torture_assert(tctx,
3328 test_AddJob(tctx, b, handle),
3331 torture_assert(tctx,
3332 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3333 "EnumJobs level 1 failed");
3335 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3337 for (i=0; i < num_jobs; i++) {
3338 union spoolss_JobInfo ginfo;
3339 const char *document_name;
3340 const char *new_document_name = "any_other_docname";
3341 struct spoolss_JobInfoContainer ctr;
3342 struct spoolss_SetJobInfo1 info1;
3344 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3346 torture_assert(tctx,
3347 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3348 "failed to call test_GetJob");
3350 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3352 document_name = ginfo.info1.document_name;
3354 info1.job_id = ginfo.info1.job_id;
3355 info1.printer_name = ginfo.info1.printer_name;
3356 info1.server_name = ginfo.info1.server_name;
3357 info1.user_name = ginfo.info1.user_name;
3358 info1.document_name = new_document_name;
3359 info1.data_type = ginfo.info1.data_type;
3360 info1.text_status = ginfo.info1.text_status;
3361 info1.status = ginfo.info1.status;
3362 info1.priority = ginfo.info1.priority;
3363 info1.position = ginfo.info1.position;
3364 info1.total_pages = ginfo.info1.total_pages;
3365 info1.pages_printed = ginfo.info1.pages_printed;
3366 info1.submitted = ginfo.info1.submitted;
3369 ctr.info.info1 = &info1;
3371 torture_assert(tctx,
3372 test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3373 "failed to call test_SetJob level 1");
3375 torture_assert(tctx,
3376 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3377 "failed to call test_GetJob");
3379 if (strequal(ginfo.info1.document_name, document_name)) {
3380 torture_warning(tctx,
3381 "document_name did *NOT* change from '%s' to '%s'\n",
3382 document_name, new_document_name);
3386 for (i=0; i < num_jobs; i++) {
3387 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3388 torture_warning(tctx, "failed to pause printjob\n");
3390 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3391 torture_warning(tctx, "failed to resume printjob\n");
3398 static bool test_DoPrintTest(struct torture_context *tctx,
3399 struct dcerpc_binding_handle *b,
3400 struct policy_handle *handle)
3403 uint32_t num_jobs = 8;
3407 torture_comment(tctx, "Testing real print operations\n");
3409 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3411 for (i=0; i < num_jobs; i++) {
3412 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
3415 for (i=0; i < num_jobs; i++) {
3416 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3420 torture_comment(tctx, "real print operations test succeeded\n\n");
3426 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3427 struct dcerpc_binding_handle *b,
3428 struct policy_handle *handle)
3431 uint32_t num_jobs = 8;
3434 torture_comment(tctx, "Testing real print operations (extended)\n");
3436 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3438 for (i=0; i < num_jobs; i++) {
3439 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
3442 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3444 for (i=0; i < num_jobs; i++) {
3445 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3449 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3455 static bool test_PausePrinter(struct torture_context *tctx,
3456 struct dcerpc_binding_handle *b,
3457 struct policy_handle *handle)
3460 struct spoolss_SetPrinter r;
3461 struct spoolss_SetPrinterInfoCtr info_ctr;
3462 struct spoolss_DevmodeContainer devmode_ctr;
3463 struct sec_desc_buf secdesc_ctr;
3466 info_ctr.info.info0 = NULL;
3468 ZERO_STRUCT(devmode_ctr);
3469 ZERO_STRUCT(secdesc_ctr);
3471 r.in.handle = handle;
3472 r.in.info_ctr = &info_ctr;
3473 r.in.devmode_ctr = &devmode_ctr;
3474 r.in.secdesc_ctr = &secdesc_ctr;
3475 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3477 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3479 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3481 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3483 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3488 static bool test_ResumePrinter(struct torture_context *tctx,
3489 struct dcerpc_binding_handle *b,
3490 struct policy_handle *handle)
3493 struct spoolss_SetPrinter r;
3494 struct spoolss_SetPrinterInfoCtr info_ctr;
3495 struct spoolss_DevmodeContainer devmode_ctr;
3496 struct sec_desc_buf secdesc_ctr;
3499 info_ctr.info.info0 = NULL;
3501 ZERO_STRUCT(devmode_ctr);
3502 ZERO_STRUCT(secdesc_ctr);
3504 r.in.handle = handle;
3505 r.in.info_ctr = &info_ctr;
3506 r.in.devmode_ctr = &devmode_ctr;
3507 r.in.secdesc_ctr = &secdesc_ctr;
3508 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3510 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3512 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3514 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3516 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3521 static bool test_GetPrinterData_checktype(struct torture_context *tctx,
3522 struct dcerpc_binding_handle *b,
3523 struct policy_handle *handle,
3524 const char *value_name,
3525 enum winreg_Type *expected_type,
3526 enum winreg_Type *type_p,
3531 struct spoolss_GetPrinterData r;
3533 enum winreg_Type type;
3534 union spoolss_PrinterData data;
3536 r.in.handle = handle;
3537 r.in.value_name = value_name;
3539 r.out.needed = &needed;
3541 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3543 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3545 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3546 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3548 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3549 if (expected_type) {
3550 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3552 r.in.offered = needed;
3553 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3554 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3555 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3558 torture_assert_werr_ok(tctx, r.out.result,
3559 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3561 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3568 *data_p = r.out.data;
3578 static bool test_GetPrinterData(struct torture_context *tctx,
3579 struct dcerpc_binding_handle *b,
3580 struct policy_handle *handle,
3581 const char *value_name,
3582 enum winreg_Type *type_p,
3586 return test_GetPrinterData_checktype(tctx, b, handle, value_name,
3587 NULL, type_p, data_p, needed_p);
3590 static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
3591 struct dcerpc_pipe *p,
3592 struct policy_handle *handle,
3593 const char *key_name,
3594 const char *value_name,
3595 enum winreg_Type *expected_type,
3596 enum winreg_Type *type_p,
3601 struct spoolss_GetPrinterDataEx r;
3602 enum winreg_Type type;
3604 union spoolss_PrinterData data;
3605 struct dcerpc_binding_handle *b = p->binding_handle;
3607 r.in.handle = handle;
3608 r.in.key_name = key_name;
3609 r.in.value_name = value_name;
3612 r.out.needed = &needed;
3613 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3615 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3616 r.in.key_name, r.in.value_name);
3618 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3619 if (!NT_STATUS_IS_OK(status)) {
3620 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3621 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3623 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3626 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3627 if (expected_type) {
3628 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3630 r.in.offered = needed;
3631 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3632 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3633 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3636 torture_assert_werr_ok(tctx, r.out.result,
3637 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3639 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3646 *data_p = r.out.data;
3656 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3657 struct dcerpc_pipe *p,
3658 struct policy_handle *handle,
3659 const char *key_name,
3660 const char *value_name,
3661 enum winreg_Type *type_p,
3665 return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
3666 NULL, type_p, data_p, needed_p);
3669 static bool test_get_environment(struct torture_context *tctx,
3670 struct dcerpc_binding_handle *b,
3671 struct policy_handle *handle,
3672 const char **architecture)
3675 enum winreg_Type type;
3679 torture_assert(tctx,
3680 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3681 "failed to get Architecture");
3683 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3685 blob = data_blob_const(data, needed);
3686 *architecture = reg_val_data_string(tctx, REG_SZ, blob);
3691 static bool test_GetPrinterData_list(struct torture_context *tctx,
3694 struct test_spoolss_context *ctx =
3695 talloc_get_type_abort(private_data, struct test_spoolss_context);
3696 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3697 struct dcerpc_binding_handle *b = p->binding_handle;
3698 const char *list[] = {
3702 /* "NetPopup", not on w2k8 */
3703 /* "NetPopupToComputer", not on w2k8 */
3706 "DefaultSpoolDirectory",
3710 /* "OSVersionEx", not on s3 */
3715 for (i=0; i < ARRAY_SIZE(list); i++) {
3716 enum winreg_Type type, type_ex;
3717 uint8_t *data, *data_ex;
3718 uint32_t needed, needed_ex;
3720 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
3721 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
3722 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
3723 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
3724 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
3725 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
3726 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3732 static bool test_EnumPrinterData(struct torture_context *tctx,
3733 struct dcerpc_pipe *p,
3734 struct policy_handle *handle,
3735 uint32_t enum_index,
3736 uint32_t value_offered,
3737 uint32_t data_offered,
3738 enum winreg_Type *type_p,
3739 uint32_t *value_needed_p,
3740 uint32_t *data_needed_p,
3741 const char **value_name_p,
3745 struct spoolss_EnumPrinterData r;
3746 uint32_t data_needed;
3747 uint32_t value_needed;
3748 enum winreg_Type type;
3749 struct dcerpc_binding_handle *b = p->binding_handle;
3751 r.in.handle = handle;
3752 r.in.enum_index = enum_index;
3753 r.in.value_offered = value_offered;
3754 r.in.data_offered = data_offered;
3755 r.out.data_needed = &data_needed;
3756 r.out.value_needed = &value_needed;
3758 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3759 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3761 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3763 torture_assert_ntstatus_ok(tctx,
3764 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
3765 "EnumPrinterData failed");
3770 if (value_needed_p) {
3771 *value_needed_p = value_needed;
3773 if (data_needed_p) {
3774 *data_needed_p = data_needed;
3777 *value_name_p = r.out.value_name;
3780 *data_p = r.out.data;
3783 *result_p = r.out.result;
3790 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3791 struct dcerpc_pipe *p,
3792 struct policy_handle *handle)
3794 uint32_t enum_index = 0;
3795 enum winreg_Type type;
3796 uint32_t value_needed;
3797 uint32_t data_needed;
3799 const char *value_name;
3802 torture_comment(tctx, "Testing EnumPrinterData\n");
3805 torture_assert(tctx,
3806 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3807 &type, &value_needed, &data_needed,
3808 &value_name, &data, &result),
3809 "EnumPrinterData failed");
3811 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3815 torture_assert(tctx,
3816 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3817 &type, &value_needed, &data_needed,
3818 &value_name, &data, &result),
3819 "EnumPrinterData failed");
3821 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3827 } while (W_ERROR_IS_OK(result));
3829 torture_comment(tctx, "EnumPrinterData test succeeded\n");
3834 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3835 struct dcerpc_binding_handle *b,
3836 struct policy_handle *handle,
3837 const char *key_name,
3839 struct spoolss_PrinterEnumValues **info_p)
3841 struct spoolss_EnumPrinterDataEx r;
3842 struct spoolss_PrinterEnumValues *info;
3846 r.in.handle = handle;
3847 r.in.key_name = key_name;
3849 r.out.needed = &needed;
3850 r.out.count = &count;
3853 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3855 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3856 "EnumPrinterDataEx failed");
3857 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3858 r.in.offered = needed;
3859 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3860 "EnumPrinterDataEx failed");
3863 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3865 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
3877 static bool test_SetPrinterData(struct torture_context *tctx,
3878 struct dcerpc_binding_handle *b,
3879 struct policy_handle *handle,
3880 const char *value_name,
3881 enum winreg_Type type,
3884 static bool test_DeletePrinterData(struct torture_context *tctx,
3885 struct dcerpc_binding_handle *b,
3886 struct policy_handle *handle,
3887 const char *value_name);
3889 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3890 struct dcerpc_pipe *p,
3891 struct policy_handle *handle)
3894 struct spoolss_PrinterEnumValues *info;
3896 uint32_t value_needed, data_needed;
3897 uint32_t value_offered, data_offered;
3899 struct dcerpc_binding_handle *b = p->binding_handle;
3901 enum winreg_Type type;
3904 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3906 torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
3909 torture_assert(tctx,
3910 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
3911 "SetPrinterData failed");
3913 blob = data_blob_string_const("torture_data2");
3915 torture_assert(tctx,
3916 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3917 "SetPrinterData failed");
3919 blob = data_blob_talloc(tctx, NULL, 4);
3920 SIVAL(blob.data, 0, 0x11223344);
3922 torture_assert(tctx,
3923 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
3924 "SetPrinterData failed");
3926 torture_assert(tctx,
3927 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
3928 "failed to call EnumPrinterDataEx");
3930 /* get the max sizes for value and data */
3932 torture_assert(tctx,
3933 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3934 NULL, &value_needed, &data_needed,
3935 NULL, NULL, &result),
3936 "EnumPrinterData failed");
3937 torture_assert_werr_ok(tctx, result, "unexpected result");
3939 /* check if the reply from the EnumPrinterData really matches max values */
3941 for (i=0; i < count; i++) {
3942 if (info[i].value_name_len > value_needed) {
3944 talloc_asprintf(tctx,
3945 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3946 info[i].value_name_len, value_needed));
3948 if (info[i].data_length > data_needed) {
3950 talloc_asprintf(tctx,
3951 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3952 info[i].data_length, data_needed));
3956 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3957 * sort or not sort the replies by value name, we should be able to do
3958 * the following entry comparison */
3960 data_offered = data_needed;
3961 value_offered = value_needed;
3963 for (i=0; i < count; i++) {
3965 const char *value_name;
3968 torture_assert(tctx,
3969 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3970 &type, &value_needed, &data_needed,
3971 &value_name, &data, &result),
3972 "EnumPrinterData failed");
3974 if (i -1 == count) {
3975 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3976 "unexpected result");
3979 torture_assert_werr_ok(tctx, result, "unexpected result");
3982 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3983 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3984 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
3985 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
3986 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
3989 torture_assert(tctx,
3990 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
3991 "DeletePrinterData failed");
3992 torture_assert(tctx,
3993 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
3994 "DeletePrinterData failed");
3995 torture_assert(tctx,
3996 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
3997 "DeletePrinterData failed");
3999 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4004 static bool test_DeletePrinterData(struct torture_context *tctx,
4005 struct dcerpc_binding_handle *b,
4006 struct policy_handle *handle,
4007 const char *value_name)
4010 struct spoolss_DeletePrinterData r;
4012 r.in.handle = handle;
4013 r.in.value_name = value_name;
4015 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
4018 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
4020 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
4021 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
4026 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
4027 struct dcerpc_binding_handle *b,
4028 struct policy_handle *handle,
4029 const char *key_name,
4030 const char *value_name)
4032 struct spoolss_DeletePrinterDataEx r;
4034 r.in.handle = handle;
4035 r.in.key_name = key_name;
4036 r.in.value_name = value_name;
4038 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
4039 r.in.key_name, r.in.value_name);
4041 torture_assert_ntstatus_ok(tctx,
4042 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
4043 "DeletePrinterDataEx failed");
4044 torture_assert_werr_ok(tctx, r.out.result,
4045 "DeletePrinterDataEx failed");
4050 static bool test_DeletePrinterKey(struct torture_context *tctx,
4051 struct dcerpc_binding_handle *b,
4052 struct policy_handle *handle,
4053 const char *key_name)
4055 struct spoolss_DeletePrinterKey r;
4057 r.in.handle = handle;
4058 r.in.key_name = key_name;
4060 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
4062 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
4063 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
4067 torture_assert_ntstatus_ok(tctx,
4068 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
4069 "DeletePrinterKey failed");
4070 torture_assert_werr_ok(tctx, r.out.result,
4071 "DeletePrinterKey failed");
4076 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4077 struct dcerpc_binding_handle *b,
4078 struct policy_handle *handle)
4080 struct winreg_OpenHKLM r;
4082 r.in.system_name = NULL;
4083 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4084 r.out.handle = handle;
4086 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4088 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4089 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4094 static void init_winreg_String(struct winreg_String *name, const char *s)
4098 name->name_len = 2 * (strlen_m(s) + 1);
4099 name->name_size = name->name_len;
4102 name->name_size = 0;
4106 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4107 struct dcerpc_binding_handle *b,
4108 struct policy_handle *hive_handle,
4109 const char *keyname,
4111 struct policy_handle *key_handle)
4113 struct winreg_OpenKey r;
4115 r.in.parent_handle = hive_handle;
4116 init_winreg_String(&r.in.keyname, keyname);
4117 r.in.options = options;
4118 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4119 r.out.handle = key_handle;
4121 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4123 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4124 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4129 static bool test_winreg_OpenKey(struct torture_context *tctx,
4130 struct dcerpc_binding_handle *b,
4131 struct policy_handle *hive_handle,
4132 const char *keyname,
4133 struct policy_handle *key_handle)
4135 return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4136 REG_OPTION_NON_VOLATILE, key_handle);
4139 static bool test_winreg_CloseKey(struct torture_context *tctx,
4140 struct dcerpc_binding_handle *b,
4141 struct policy_handle *handle)
4143 struct winreg_CloseKey r;
4145 r.in.handle = handle;
4146 r.out.handle = handle;
4148 torture_comment(tctx, "Testing winreg_CloseKey\n");
4150 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4151 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4156 bool test_winreg_QueryValue(struct torture_context *tctx,
4157 struct dcerpc_binding_handle *b,
4158 struct policy_handle *handle,
4159 const char *value_name,
4160 enum winreg_Type *type_p,
4161 uint32_t *data_size_p,
4162 uint32_t *data_length_p,
4165 struct winreg_QueryValue r;
4166 enum winreg_Type type = REG_NONE;
4167 uint32_t data_size = 0;
4168 uint32_t data_length = 0;
4169 struct winreg_String valuename;
4170 uint8_t *data = NULL;
4172 init_winreg_String(&valuename, value_name);
4174 data = talloc_zero_array(tctx, uint8_t, 0);
4176 r.in.handle = handle;
4177 r.in.value_name = &valuename;
4179 r.in.data_size = &data_size;
4180 r.in.data_length = &data_length;
4184 r.out.data_size = &data_size;
4185 r.out.data_length = &data_length;
4187 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4189 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4190 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4191 *r.in.data_size = *r.out.data_size;
4192 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4195 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4197 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4200 *type_p = *r.out.type;
4203 *data_size_p = *r.out.data_size;
4205 if (data_length_p) {
4206 *data_length_p = *r.out.data_length;
4209 *data_p = r.out.data;
4215 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4216 struct dcerpc_binding_handle *b,
4217 struct policy_handle *handle,
4218 const char *printer_name,
4219 const char *key_name,
4220 const char *value_name,
4221 enum winreg_Type *w_type,
4226 const char *printer_key;
4227 struct policy_handle key_handle;
4229 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4230 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4232 torture_assert(tctx,
4233 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4235 torture_assert(tctx,
4236 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4238 torture_assert(tctx,
4239 test_winreg_CloseKey(tctx, b, &key_handle), "");
4244 static bool test_GetForm_winreg(struct torture_context *tctx,
4245 struct dcerpc_binding_handle *b,
4246 struct policy_handle *handle,
4247 const char *key_name,
4248 const char *form_name,
4249 enum winreg_Type *w_type,
4254 struct policy_handle key_handle;
4256 torture_assert(tctx,
4257 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4259 torture_assert(tctx,
4260 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4262 torture_assert(tctx,
4263 test_winreg_CloseKey(tctx, b, &key_handle), "");
4268 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4269 struct dcerpc_binding_handle *b,
4270 struct policy_handle *handle,
4271 const char *symlink_keyname,
4272 const char *symlink_destination)
4274 /* check if the first key is a symlink to the second key */
4276 enum winreg_Type w_type;
4280 struct policy_handle key_handle;
4284 if (torture_setting_bool(tctx, "samba3", false)) {
4285 torture_skip(tctx, "skip winreg symlink test against samba");
4288 torture_assert(tctx,
4289 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4290 "failed to open key link");
4292 torture_assert(tctx,
4293 test_winreg_QueryValue(tctx, b, &key_handle,
4294 "SymbolicLinkValue",
4295 &w_type, &w_size, &w_length, &w_data),
4296 "failed to query for 'SymbolicLinkValue' attribute");
4298 torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4300 blob = data_blob(w_data, w_size);
4301 str = reg_val_data_string(tctx, REG_SZ, blob);
4303 torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4305 torture_assert(tctx,
4306 test_winreg_CloseKey(tctx, b, &key_handle),
4307 "failed to close key link");
4312 static const char *strip_unc(const char *unc)
4320 if (unc[0] == '\\' && unc[1] == '\\') {
4324 name = strchr(unc, '\\');
4332 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4333 struct dcerpc_binding_handle *b,
4334 struct policy_handle *handle,
4335 const char *printer_name,
4336 struct dcerpc_binding_handle *winreg_handle,
4337 struct policy_handle *hive_handle)
4339 union spoolss_PrinterInfo info;
4340 const char *keys[] = {
4341 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4342 TOP_LEVEL_PRINT_PRINTERS_KEY
4345 const char *printername, *sharename;
4347 torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4349 torture_assert(tctx,
4350 test_GetPrinter_level(tctx, b, handle, 2, &info),
4351 "failed to get printer info level 2");
4353 printername = strip_unc(info.info2.printername);
4354 sharename = strip_unc(info.info2.sharename);
4356 #define test_sz(wname, iname) \
4360 enum winreg_Type w_type;\
4364 torture_assert(tctx,\
4365 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4366 &w_type, &w_size, &w_length, &w_data),\
4367 "failed to query winreg");\
4368 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4369 blob = data_blob(w_data, w_size);\
4370 str = reg_val_data_string(tctx, REG_SZ, blob);\
4371 if (w_size == 2 && iname == NULL) {\
4372 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4374 torture_assert_str_equal(tctx, str, iname,\
4375 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4379 #define test_dword(wname, iname) \
4382 enum winreg_Type w_type;\
4386 torture_assert(tctx,\
4387 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4388 &w_type, &w_size, &w_length, &w_data),\
4389 "failed to query winreg");\
4390 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4391 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4392 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4393 value = IVAL(w_data, 0);\
4394 torture_assert_int_equal(tctx, value, iname,\
4395 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4398 #define test_binary(wname, iname) \
4400 enum winreg_Type w_type;\
4404 torture_assert(tctx,\
4405 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4406 &w_type, &w_size, &w_length, &w_data),\
4407 "failed to query winreg");\
4408 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4409 torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4410 torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4415 #define test_dm(wname, iname) \
4418 struct spoolss_DeviceMode dm;\
4419 enum ndr_err_code ndr_err;\
4420 enum winreg_Type w_type;\
4424 torture_assert(tctx,\
4425 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4426 &w_type, &w_size, &w_length, &w_data),\
4427 "failed to query winreg");\
4428 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4429 blob = data_blob(w_data, w_size);\
4430 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4431 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4432 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4433 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4437 #define test_sd(wname, iname) \
4440 struct security_descriptor sd;\
4441 enum ndr_err_code ndr_err;\
4442 enum winreg_Type w_type;\
4446 torture_assert(tctx,\
4447 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4448 &w_type, &w_size, &w_length, &w_data),\
4449 "failed to query winreg");\
4450 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4451 blob = data_blob(w_data, w_size);\
4452 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4453 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4454 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4455 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4459 #define test_multi_sz(wname, iname) \
4462 const char **array;\
4463 enum winreg_Type w_type;\
4468 torture_assert(tctx,\
4469 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4470 &w_type, &w_size, &w_length, &w_data),\
4471 "failed to query winreg");\
4472 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4473 blob = data_blob(w_data, w_size);\
4474 torture_assert(tctx, \
4475 pull_reg_multi_sz(tctx, &blob, &array),\
4476 "failed to pull multi sz");\
4477 for (i=0; array[i] != NULL; i++) {\
4478 torture_assert_str_equal(tctx, array[i], iname[i],\
4479 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4483 if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4484 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4485 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4487 torture_warning(tctx, "failed to check for winreg symlink");
4490 for (i=0; i < ARRAY_SIZE(keys); i++) {
4492 const char *printer_key;
4493 struct policy_handle key_handle;
4495 printer_key = talloc_asprintf(tctx, "%s\\%s",
4496 keys[i], printer_name);
4498 torture_assert(tctx,
4499 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4501 test_sz("Name", printername);
4502 test_sz("Share Name", sharename);
4503 test_sz("Port", info.info2.portname);
4504 test_sz("Printer Driver", info.info2.drivername);
4505 test_sz("Description", info.info2.comment);
4506 test_sz("Location", info.info2.location);
4507 test_sz("Separator File", info.info2.sepfile);
4508 test_sz("Print Processor", info.info2.printprocessor);
4509 test_sz("Datatype", info.info2.datatype);
4510 test_sz("Parameters", info.info2.parameters);
4511 /* winreg: 0, spoolss not */
4512 /* test_dword("Attributes", info.info2.attributes); */
4513 test_dword("Priority", info.info2.priority);
4514 test_dword("Default Priority", info.info2.defaultpriority);
4515 /* winreg: 60, spoolss: 0 */
4516 /* test_dword("StartTime", info.info2.starttime); */
4517 /* test_dword("UntilTime", info.info2.untiltime); */
4518 /* winreg != spoolss */
4519 /* test_dword("Status", info.info2.status); */
4520 test_dm("Default DevMode", info.info2.devmode);
4521 test_sd("Security", info.info2.secdesc);
4523 torture_assert(tctx,
4524 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4530 torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4535 static bool test_PrintProcessors(struct torture_context *tctx,
4536 struct dcerpc_binding_handle *b,
4537 const char *environment,
4538 struct dcerpc_binding_handle *winreg_handle,
4539 struct policy_handle *hive_handle)
4541 union spoolss_PrintProcessorInfo *info;
4545 torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4547 torture_assert(tctx,
4548 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
4549 "failed to enum print processors level 1");
4551 for (i=0; i < count; i++) {
4553 const char *processor_key;
4554 struct policy_handle key_handle;
4556 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4557 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4559 info[i].info1.print_processor_name);
4561 torture_assert(tctx,
4562 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4564 /* nothing to check in there so far */
4566 torture_assert(tctx,
4567 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4570 torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4575 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4576 struct dcerpc_binding_handle *b,
4577 struct policy_handle *handle,
4578 const char *driver_name,
4579 const char *architecture,
4581 uint32_t client_major_version,
4582 uint32_t client_minor_version,
4583 union spoolss_DriverInfo *info_p,
4586 static const char *strip_path(const char *path)
4594 p = strrchr(path, '\\');
4602 static const char **strip_paths(const char **path_array)
4606 if (path_array == NULL) {
4610 for (i=0; path_array[i] != NULL; i++) {
4611 path_array[i] = strip_path(path_array[i]);
4617 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4623 return talloc_strdup(mem_ctx, "01/01/1601");
4626 t = nt_time_to_unix(nt);
4629 return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4630 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4633 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4635 return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4636 (unsigned)((v >> 48) & 0xFFFF),
4637 (unsigned)((v >> 32) & 0xFFFF),
4638 (unsigned)((v >> 16) & 0xFFFF),
4639 (unsigned)(v & 0xFFFF));
4642 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4643 struct dcerpc_binding_handle *b,
4644 struct policy_handle *handle,
4645 const char *printer_name,
4646 const char *driver_name,
4647 const char *environment,
4648 enum spoolss_DriverOSVersion version,
4649 struct dcerpc_binding_handle *winreg_handle,
4650 struct policy_handle *hive_handle,
4651 const char *server_name_slash)
4654 union spoolss_DriverInfo info;
4655 const char *driver_key;
4656 struct policy_handle key_handle;
4658 const char *driver_path;
4659 const char *data_file;
4660 const char *config_file;
4661 const char *help_file;
4662 const char **dependent_files;
4664 const char *driver_date;
4665 const char *inbox_driver_date;
4667 const char *driver_version;
4668 const char *inbox_driver_version;
4670 torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4672 driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4673 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4678 torture_assert(tctx,
4679 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4680 "failed to open driver key");
4682 if (torture_setting_bool(tctx, "samba3", false) ||
4683 torture_setting_bool(tctx, "w2k3", false)) {
4688 torture_assert(tctx,
4689 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
4690 "failed to get driver info level 8");
4692 torture_assert(tctx,
4693 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
4694 "failed to get driver info level 8");
4697 if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4701 driver_path = strip_path(info.info8.driver_path);
4702 data_file = strip_path(info.info8.data_file);
4703 config_file = strip_path(info.info8.config_file);
4704 help_file = strip_path(info.info8.help_file);
4705 dependent_files = strip_paths(info.info8.dependent_files);
4707 driver_date = driver_winreg_date(tctx, info.info8.driver_date);
4708 inbox_driver_date = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
4710 driver_version = driver_winreg_version(tctx, info.info8.driver_version);
4711 inbox_driver_version = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
4713 test_sz("Configuration File", config_file);
4714 test_sz("Data File", data_file);
4715 test_sz("Datatype", info.info8.default_datatype);
4716 test_sz("Driver", driver_path);
4717 test_sz("DriverDate", driver_date);
4718 test_sz("DriverVersion", driver_version);
4719 test_sz("HardwareID", info.info8.hardware_id);
4720 test_sz("Help File", help_file);
4721 test_sz("InfPath", info.info8.inf_path);
4722 test_sz("Manufacturer", info.info8.manufacturer_name);
4723 test_sz("MinInboxDriverVerDate", inbox_driver_date);
4724 test_sz("MinInboxDriverVerVersion", inbox_driver_version);
4725 test_sz("Monitor", info.info8.monitor_name);
4726 test_sz("OEM URL", info.info8.manufacturer_url);
4727 test_sz("Print Processor", info.info8.print_processor);
4728 test_sz("Provider", info.info8.provider);
4729 test_sz("VendorSetup", info.info8.vendor_setup);
4730 test_multi_sz("ColorProfiles", info.info8.color_profiles);
4731 test_multi_sz("Dependent Files", dependent_files);
4732 test_multi_sz("CoreDependencies", info.info8.core_driver_dependencies);
4733 test_multi_sz("Previous Names", info.info8.previous_names);
4734 /* test_dword("Attributes", ?); */
4735 test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
4736 test_dword("Version", info.info8.version);
4737 /* test_dword("TempDir", ?); */
4742 torture_assert(tctx,
4743 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
4744 "failed to get driver info level 6");
4746 torture_assert(tctx,
4747 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
4748 "failed to get driver info level 6");
4751 driver_path = strip_path(info.info6.driver_path);
4752 data_file = strip_path(info.info6.data_file);
4753 config_file = strip_path(info.info6.config_file);
4754 help_file = strip_path(info.info6.help_file);
4755 dependent_files = strip_paths(info.info6.dependent_files);
4757 driver_date = driver_winreg_date(tctx, info.info6.driver_date);
4759 driver_version = driver_winreg_version(tctx, info.info6.driver_version);
4761 test_sz("Configuration File", config_file);
4762 test_sz("Data File", data_file);
4763 test_sz("Datatype", info.info6.default_datatype);
4764 test_sz("Driver", driver_path);
4765 if (torture_setting_bool(tctx, "w2k3", false)) {
4766 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
4767 push_nttime(blob.data, 0, info.info6.driver_date);
4768 test_binary("DriverDate", blob);
4769 SBVAL(blob.data, 0, info.info6.driver_version);
4770 test_binary("DriverVersion", blob);
4772 test_sz("DriverDate", driver_date);
4773 test_sz("DriverVersion", driver_version);
4775 test_sz("HardwareID", info.info6.hardware_id);
4776 test_sz("Help File", help_file);
4777 test_sz("Manufacturer", info.info6.manufacturer_name);
4778 test_sz("Monitor", info.info6.monitor_name);
4779 test_sz("OEM URL", info.info6.manufacturer_url);
4780 test_sz("Provider", info.info6.provider);
4781 test_multi_sz("Dependent Files", dependent_files);
4782 test_multi_sz("Previous Names", info.info6.previous_names);
4783 /* test_dword("Attributes", ?); */
4784 test_dword("Version", info.info6.version);
4785 /* test_dword("TempDir", ?); */
4788 torture_assert(tctx,
4789 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
4790 "failed to get driver info level 3");
4792 torture_assert(tctx,
4793 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
4794 "failed to get driver info level 3");
4797 driver_path = strip_path(info.info3.driver_path);
4798 data_file = strip_path(info.info3.data_file);
4799 config_file = strip_path(info.info3.config_file);
4800 help_file = strip_path(info.info3.help_file);
4801 dependent_files = strip_paths(info.info3.dependent_files);
4803 test_sz("Configuration File", config_file);
4804 test_sz("Data File", data_file);
4805 test_sz("Datatype", info.info3.default_datatype);
4806 test_sz("Driver", driver_path);
4807 test_sz("Help File", help_file);
4808 test_sz("Monitor", info.info3.monitor_name);
4809 test_multi_sz("Dependent Files", dependent_files);
4810 /* test_dword("Attributes", ?); */
4811 test_dword("Version", info.info3.version);
4812 /* test_dword("TempDir", ?); */
4815 torture_assert(tctx,
4816 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4818 torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
4826 static bool test_SetPrinterData(struct torture_context *tctx,
4827 struct dcerpc_binding_handle *b,
4828 struct policy_handle *handle,
4829 const char *value_name,
4830 enum winreg_Type type,
4834 struct spoolss_SetPrinterData r;
4836 r.in.handle = handle;
4837 r.in.value_name = value_name;
4840 r.in.offered = offered;
4842 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
4845 torture_assert_ntstatus_ok(tctx,
4846 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
4847 "SetPrinterData failed");
4848 torture_assert_werr_ok(tctx, r.out.result,
4849 "SetPrinterData failed");
4854 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
4855 struct dcerpc_binding_handle *b,
4856 struct policy_handle *handle,
4857 const char *printer_name,
4858 struct dcerpc_binding_handle *winreg_handle,
4859 struct policy_handle *hive_handle)
4861 const char *values[] = {
4865 /* FIXME: not working with s3 atm. */
4871 /* FIXME: not working with s3 atm. */
4878 for (i=0; i < ARRAY_SIZE(values); i++) {
4880 enum winreg_Type type, expected_type = REG_SZ;
4885 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
4888 torture_assert(tctx,
4889 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
4890 "SetPrinterData failed");
4892 torture_assert(tctx,
4893 test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
4894 "GetPrinterData failed");
4896 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
4897 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
4898 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
4900 if (winreg_handle && hive_handle) {
4902 enum winreg_Type w_type;
4907 torture_assert(tctx,
4908 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4909 printer_name, "PrinterDriverData", values[i],
4910 &w_type, &w_size, &w_length, &w_data), "");
4912 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
4913 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
4914 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
4915 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
4918 torture_assert(tctx,
4919 test_DeletePrinterData(tctx, b, handle, values[i]),
4920 "DeletePrinterData failed");
4927 static bool test_EnumPrinterKey(struct torture_context *tctx,
4928 struct dcerpc_binding_handle *b,
4929 struct policy_handle *handle,
4930 const char *key_name,
4931 const char ***array);
4933 static bool test_SetPrinterDataEx(struct torture_context *tctx,
4934 struct dcerpc_binding_handle *b,
4935 struct policy_handle *handle,
4936 const char *key_name,
4937 const char *value_name,
4938 enum winreg_Type type,
4943 struct spoolss_SetPrinterDataEx r;
4945 r.in.handle = handle;
4946 r.in.key_name = key_name;
4947 r.in.value_name = value_name;
4950 r.in.offered = offered;
4952 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
4953 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
4955 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
4957 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
4958 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
4963 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
4964 struct dcerpc_pipe *p,
4965 struct policy_handle *handle)
4967 struct dcerpc_binding_handle *b = p->binding_handle;
4968 const char *value_name = "dog";
4969 const char *keys[] = {
4972 "torturedataex_with_subkey\\subkey",
4973 "torturedataex_with_subkey\\subkey:0",
4974 "torturedataex_with_subkey\\subkey:1",
4975 "torturedataex_with_subkey\\subkey\\subsubkey",
4976 "torturedataex_with_subkey\\subkey\\subsubkey:0",
4977 "torturedataex_with_subkey\\subkey\\subsubkey:1",
4984 "torture/data ex/sub",
4987 "torture//data ex/sub",
4988 "torture//data ex//sub",
4992 for (i=0; i < ARRAY_SIZE(keys); i++) {
4996 enum winreg_Type type;
4997 DATA_BLOB blob_in, blob_out;
4998 const char **subkeys;
5000 struct spoolss_PrinterEnumValues *einfo;
5003 blob_in = data_blob_talloc(tctx, NULL, 42);
5005 generate_random_buffer(blob_in.data, blob_in.length);
5007 torture_assert(tctx,
5008 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
5009 "failed to call SetPrinterDataEx");
5011 torture_assert(tctx,
5012 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
5013 "failed to call GetPrinterDataEx");
5015 blob_out.length = needed;
5016 torture_assert(tctx,
5017 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
5018 "failed to call EnumPrinterDataEx");
5020 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5021 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5022 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5024 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5025 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5026 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5027 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5028 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5029 if (einfo[0].data_length > 0) {
5030 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5033 key = talloc_strdup(tctx, keys[i]);
5035 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
5039 c = strchr(key, '\\');
5043 /* we have subkeys */
5047 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
5051 for (k=0; subkeys && subkeys[k]; k++) {
5053 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
5055 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
5060 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5065 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5074 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
5075 struct dcerpc_pipe *p,
5076 struct policy_handle *handle)
5078 struct dcerpc_binding_handle *b = p->binding_handle;
5079 const char *key = "torturedataex";
5080 const char *values[] = {
5090 for (i=0; i < ARRAY_SIZE(values); i++) {
5092 enum winreg_Type type;
5093 DATA_BLOB blob_in, blob_out;
5095 struct spoolss_PrinterEnumValues *einfo;
5098 if (torture_setting_bool(tctx, "samba3", false)) {
5100 q = strrchr(values[i], ',');
5102 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
5108 blob_in = data_blob_talloc(tctx, NULL, 42);
5110 generate_random_buffer(blob_in.data, blob_in.length);
5112 torture_assert(tctx,
5113 test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
5114 "failed to call SetPrinterDataEx");
5116 torture_assert(tctx,
5117 test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
5118 "failed to call GetPrinterDataEx");
5120 blob_out.length = needed;
5121 torture_assert(tctx,
5122 test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
5123 "failed to call EnumPrinterDataEx");
5125 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5126 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5127 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5129 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5130 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5131 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5132 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5133 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5134 if (einfo[0].data_length > 0) {
5135 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5138 torture_assert(tctx,
5139 test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5140 "failed to call DeletePrinterDataEx");
5147 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5148 struct dcerpc_pipe *p,
5149 struct policy_handle *handle,
5150 const char *printername,
5151 struct dcerpc_binding_handle *winreg_handle,
5152 struct policy_handle *hive_handle)
5154 struct dcerpc_binding_handle *b = p->binding_handle;
5155 const char *value_name = "dog";
5156 const char *key_name = "torturedataex";
5157 enum winreg_Type types[] = {
5163 const char *str = "abcdefghi";
5166 for (t=0; t < ARRAY_SIZE(types); t++) {
5167 for (s=0; s < strlen(str); s++) {
5169 enum winreg_Type type;
5170 const char *string = talloc_strndup(tctx, str, s);
5171 const char *array[2];
5172 DATA_BLOB blob = data_blob_string_const(string);
5175 uint32_t needed, offered = 0;
5177 struct spoolss_PrinterEnumValues *einfo;
5179 array[0] = talloc_strdup(tctx, string);
5182 if (types[t] == REG_DWORD) {
5189 offered = blob.length;
5192 data = data_blob_talloc(tctx, NULL, 4);
5193 SIVAL(data.data, 0, 0x12345678);
5197 torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5199 offered = data.length;
5200 /*strlen_m_term(data.string)*2;*/
5203 torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5204 type = REG_MULTI_SZ;
5205 offered = data.length;
5208 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5211 torture_assert(tctx,
5212 test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5213 "failed to call SetPrinterDataEx");
5215 torture_assert(tctx,
5216 test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
5217 "failed to call GetPrinterDataEx");
5219 torture_assert(tctx,
5220 test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5221 "failed to call EnumPrinterDataEx");
5223 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5224 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5225 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5227 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5228 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5229 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5230 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5231 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5232 if (einfo[0].data_length > 0) {
5233 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5236 if (winreg_handle && hive_handle) {
5237 enum winreg_Type w_type;
5242 torture_assert(tctx,
5243 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5244 printername, key_name, value_name,
5245 &w_type, &w_size, &w_length, &w_data), "");
5247 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5248 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5249 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5250 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5253 torture_assert(tctx,
5254 test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5255 "failed to call DeletePrinterDataEx");
5262 static bool test_PrinterData_winreg(struct torture_context *tctx,
5263 struct dcerpc_pipe *p,
5264 struct policy_handle *handle,
5265 const char *printer_name)
5267 struct dcerpc_binding_handle *b = p->binding_handle;
5268 struct dcerpc_pipe *p2;
5270 struct policy_handle hive_handle;
5271 struct dcerpc_binding_handle *b2;
5273 torture_assert_ntstatus_ok(tctx,
5274 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5275 "could not open winreg pipe");
5276 b2 = p2->binding_handle;
5278 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5280 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5281 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5283 test_winreg_CloseKey(tctx, b2, &hive_handle);
5290 static bool test_Forms_winreg(struct torture_context *tctx,
5291 struct dcerpc_binding_handle *b,
5292 struct policy_handle *handle,
5294 const char *printer_name)
5296 struct dcerpc_pipe *p2;
5298 struct policy_handle hive_handle;
5299 struct dcerpc_binding_handle *b2;
5301 torture_assert_ntstatus_ok(tctx,
5302 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5303 "could not open winreg pipe");
5304 b2 = p2->binding_handle;
5306 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5308 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5310 test_winreg_CloseKey(tctx, b2, &hive_handle);
5317 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5318 struct dcerpc_pipe *p,
5319 struct policy_handle *handle,
5320 const char *printer_name)
5322 struct dcerpc_binding_handle *b = p->binding_handle;
5323 struct dcerpc_pipe *p2;
5325 struct policy_handle hive_handle;
5326 struct dcerpc_binding_handle *b2;
5328 torture_assert_ntstatus_ok(tctx,
5329 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5330 "could not open winreg pipe");
5331 b2 = p2->binding_handle;
5333 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5335 ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5337 test_winreg_CloseKey(tctx, b2, &hive_handle);
5344 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5345 struct dcerpc_pipe *p,
5346 struct policy_handle *handle,
5347 const char *printer_name,
5348 const char *driver_name,
5349 const char *environment,
5350 enum spoolss_DriverOSVersion version)
5352 struct dcerpc_binding_handle *b = p->binding_handle;
5353 struct dcerpc_pipe *p2;
5355 struct policy_handle hive_handle;
5356 struct dcerpc_binding_handle *b2;
5358 torture_assert_ntstatus_ok(tctx,
5359 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5360 "could not open winreg pipe");
5361 b2 = p2->binding_handle;
5363 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5365 ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
5367 test_winreg_CloseKey(tctx, b2, &hive_handle);
5374 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5375 struct dcerpc_binding_handle *b,
5376 const char *environment)
5378 struct dcerpc_pipe *p2;
5380 struct policy_handle hive_handle;
5381 struct dcerpc_binding_handle *b2;
5383 torture_assert_ntstatus_ok(tctx,
5384 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5385 "could not open winreg pipe");
5386 b2 = p2->binding_handle;
5388 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5390 ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5392 test_winreg_CloseKey(tctx, b2, &hive_handle);
5399 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5400 struct dcerpc_pipe *p,
5401 struct policy_handle *handle,
5402 const char *printer_name)
5404 struct spoolss_SetPrinterInfoCtr info_ctr;
5405 struct spoolss_DevmodeContainer devmode_ctr;
5406 struct sec_desc_buf secdesc_ctr;
5407 union spoolss_SetPrinterInfo sinfo;
5408 union spoolss_PrinterInfo info;
5409 struct dcerpc_binding_handle *b = p->binding_handle;
5412 ZERO_STRUCT(info_ctr);
5413 ZERO_STRUCT(devmode_ctr);
5414 ZERO_STRUCT(secdesc_ctr);
5416 torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5418 torture_assert(tctx,
5419 test_GetPrinter_level(tctx, b, handle, 2, &info),
5420 "failed to query Printer level 2");
5422 torture_assert(tctx,
5423 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5424 "failed to convert");
5427 info_ctr.info = sinfo;
5429 #define TEST_SZ(wname, iname) \
5431 enum winreg_Type type;\
5436 torture_assert(tctx,\
5437 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5438 "failed to query");\
5439 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5440 blob = data_blob_const(data, needed);\
5441 torture_assert(tctx,\
5442 pull_reg_sz(tctx, &blob, &str),\
5443 "failed to pull REG_SZ");\
5444 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5448 #define TEST_SET_SZ(wname, iname, val) \
5450 enum winreg_Type type;\
5455 sinfo.info2->iname = val;\
5456 torture_assert(tctx,\
5457 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5458 "failed to call SetPrinter");\
5459 torture_assert(tctx,\
5460 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5461 "failed to query");\
5462 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5463 blob = data_blob_const(data, needed);\
5464 torture_assert(tctx,\
5465 pull_reg_sz(tctx, &blob, &str),\
5466 "failed to pull REG_SZ");\
5467 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5470 #define TEST_SET_DWORD(wname, iname, val) \
5472 enum winreg_Type type;\
5476 sinfo.info2->iname = val;\
5477 torture_assert(tctx,\
5478 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5479 "failed to call SetPrinter");\
5480 torture_assert(tctx,\
5481 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5482 "failed to query");\
5483 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5484 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5485 value = IVAL(data, 0); \
5486 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5489 TEST_SET_SZ("description", comment, "newval");
5490 TEST_SET_SZ("location", location, "newval");
5491 /* TEST_SET_DWORD("priority", priority, 25); */
5493 torture_assert(tctx,
5494 test_GetPrinter_level(tctx, b, handle, 2, &info),
5495 "failed to query Printer level 2");
5497 TEST_SZ("description", info.info2.comment);
5498 TEST_SZ("driverName", info.info2.drivername);
5499 TEST_SZ("location", info.info2.location);
5501 pname = strrchr(info.info2.printername, '\\');
5502 if (pname == NULL) {
5503 pname = info.info2.printername;
5507 TEST_SZ("printerName", pname);
5508 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5509 /* TEST_SZ("printShareName", info.info2.sharename); */
5511 /* FIXME gd: complete the list */
5517 torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5522 static bool test_print_processors_winreg(struct torture_context *tctx,
5525 struct test_spoolss_context *ctx =
5526 talloc_get_type_abort(private_data, struct test_spoolss_context);
5527 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5528 struct dcerpc_binding_handle *b = p->binding_handle;
5530 return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5533 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5534 struct dcerpc_binding_handle *b,
5535 struct policy_handle *handle,
5536 uint32_t *change_id)
5538 enum winreg_Type type;
5542 torture_assert(tctx,
5543 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5544 "failed to call GetPrinterData");
5546 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5547 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5549 *change_id = IVAL(data, 0);
5554 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5555 struct dcerpc_pipe *p,
5556 struct policy_handle *handle,
5557 uint32_t *change_id)
5559 enum winreg_Type type;
5563 torture_assert(tctx,
5564 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5565 "failed to call GetPrinterData");
5567 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5568 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5570 *change_id = IVAL(data, 0);
5575 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5576 struct dcerpc_binding_handle *b,
5577 struct policy_handle *handle,
5578 uint32_t *change_id)
5580 union spoolss_PrinterInfo info;
5582 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5583 "failed to query Printer level 0");
5585 *change_id = info.info0.change_id;
5590 static bool test_ChangeID(struct torture_context *tctx,
5591 struct dcerpc_pipe *p,
5592 struct policy_handle *handle)
5594 uint32_t change_id, change_id_ex, change_id_info;
5595 uint32_t change_id2, change_id_ex2, change_id_info2;
5596 union spoolss_PrinterInfo info;
5597 const char *comment;
5598 struct dcerpc_binding_handle *b = p->binding_handle;
5600 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5602 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5603 "failed to query for ChangeID");
5604 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5605 "failed to query for ChangeID");
5606 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5607 "failed to query for ChangeID");
5609 torture_assert_int_equal(tctx, change_id, change_id_ex,
5610 "change_ids should all be equal");
5611 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5612 "change_ids should all be equal");
5615 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
5617 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5618 "failed to query for ChangeID");
5619 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5620 "failed to query Printer level 2");
5621 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5622 "failed to query for ChangeID");
5623 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5624 "failed to query for ChangeID");
5625 torture_assert_int_equal(tctx, change_id, change_id_ex,
5626 "change_id should not have changed");
5627 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5628 "change_id should not have changed");
5631 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
5633 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5634 "failed to query for ChangeID");
5635 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5636 "failed to query for ChangeID");
5637 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5638 "failed to query for ChangeID");
5639 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5640 "failed to query Printer level 2");
5641 comment = talloc_strdup(tctx, info.info2.comment);
5644 struct spoolss_SetPrinterInfoCtr info_ctr;
5645 struct spoolss_DevmodeContainer devmode_ctr;
5646 struct sec_desc_buf secdesc_ctr;
5647 union spoolss_SetPrinterInfo sinfo;
5649 ZERO_STRUCT(info_ctr);
5650 ZERO_STRUCT(devmode_ctr);
5651 ZERO_STRUCT(secdesc_ctr);
5654 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5655 sinfo.info2->comment = "torture_comment";
5658 info_ctr.info = sinfo;
5660 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5661 "failed to call SetPrinter");
5663 sinfo.info2->comment = comment;
5665 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5666 "failed to call SetPrinter");
5670 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5671 "failed to query for ChangeID");
5672 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5673 "failed to query for ChangeID");
5674 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5675 "failed to query for ChangeID");
5677 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5678 "change_ids should all be equal");
5679 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5680 "change_ids should all be equal");
5682 torture_assert(tctx, (change_id < change_id2),
5683 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5684 change_id2, change_id));
5685 torture_assert(tctx, (change_id_ex < change_id_ex2),
5686 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5687 change_id_ex2, change_id_ex));
5688 torture_assert(tctx, (change_id_info < change_id_info2),
5689 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5690 change_id_info2, change_id_info));
5692 torture_comment(tctx, "ChangeID tests succeeded\n\n");
5697 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5698 struct dcerpc_pipe *p,
5699 struct policy_handle *handle)
5702 struct dcerpc_binding *b;
5703 struct dcerpc_pipe *p2;
5704 struct spoolss_ClosePrinter cp;
5706 /* only makes sense on SMB */
5707 if (p->conn->transport.transport != NCACN_NP) {
5711 torture_comment(tctx, "Testing close on secondary pipe\n");
5713 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
5714 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
5716 status = dcerpc_secondary_connection(p, &p2, b);
5717 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
5719 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
5720 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
5722 cp.in.handle = handle;
5723 cp.out.handle = handle;
5725 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
5726 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
5727 "ERROR: Allowed close on secondary connection");
5734 static bool test_OpenPrinter_badname(struct torture_context *tctx,
5735 struct dcerpc_binding_handle *b, const char *name)
5738 struct spoolss_OpenPrinter op;
5739 struct spoolss_OpenPrinterEx opEx;
5740 struct policy_handle handle;
5743 op.in.printername = name;
5744 op.in.datatype = NULL;
5745 op.in.devmode_ctr.devmode= NULL;
5746 op.in.access_mask = 0;
5747 op.out.handle = &handle;
5749 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
5751 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
5752 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5753 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
5754 "unexpected result");
5756 if (W_ERROR_IS_OK(op.out.result)) {
5757 ret &=test_ClosePrinter(tctx, b, &handle);
5760 opEx.in.printername = name;
5761 opEx.in.datatype = NULL;
5762 opEx.in.devmode_ctr.devmode = NULL;
5763 opEx.in.access_mask = 0;
5765 opEx.in.userlevel.level1 = NULL;
5766 opEx.out.handle = &handle;
5768 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
5770 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
5771 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5772 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
5773 "unexpected result");
5775 if (W_ERROR_IS_OK(opEx.out.result)) {
5776 ret &=test_ClosePrinter(tctx, b, &handle);
5782 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
5785 struct test_spoolss_context *ctx =
5786 talloc_get_type_abort(private_data, struct test_spoolss_context);
5788 const char *badnames[] = {
5789 "__INVALID_PRINTER__",
5790 "\\\\__INVALID_HOST__",
5793 "\\\\\\__INVALID_PRINTER__"
5795 const char *badname;
5796 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5797 const char *server_name = dcerpc_server_name(p);
5798 struct dcerpc_binding_handle *b = p->binding_handle;
5801 for (i=0; i < ARRAY_SIZE(badnames); i++) {
5802 torture_assert(tctx,
5803 test_OpenPrinter_badname(tctx, b, badnames[i]),
5807 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
5808 torture_assert(tctx,
5809 test_OpenPrinter_badname(tctx, b, badname),
5812 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
5813 torture_assert(tctx,
5814 test_OpenPrinter_badname(tctx, b, badname),
5820 static bool test_OpenPrinter(struct torture_context *tctx,
5821 struct dcerpc_pipe *p,
5823 const char *environment,
5827 struct spoolss_OpenPrinter r;
5828 struct policy_handle handle;
5830 struct dcerpc_binding_handle *b = p->binding_handle;
5832 r.in.printername = name;
5833 r.in.datatype = NULL;
5834 r.in.devmode_ctr.devmode= NULL;
5835 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5836 r.out.handle = &handle;
5838 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5840 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5842 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5844 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5850 if (!test_GetPrinter(tctx, b, &handle, environment)) {
5854 if (!torture_setting_bool(tctx, "samba3", false)) {
5855 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5861 if (!test_ClosePrinter(tctx, b, &handle)) {
5868 static bool test_OpenPrinterEx(struct torture_context *tctx,
5869 struct dcerpc_binding_handle *b,
5870 const char *printername,
5871 const char *datatype,
5872 struct spoolss_DeviceMode *devmode,
5873 uint32_t access_mask,
5875 union spoolss_UserLevel *userlevel,
5876 struct policy_handle *handle,
5877 WERROR expected_result)
5879 struct spoolss_OpenPrinterEx r;
5881 r.in.printername = printername;
5882 r.in.datatype = datatype;
5883 r.in.devmode_ctr.devmode= devmode;
5884 r.in.access_mask = access_mask;
5886 r.in.userlevel = *userlevel;
5887 r.out.handle = handle;
5889 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5891 torture_assert_ntstatus_ok(tctx,
5892 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
5893 "OpenPrinterEx failed");
5895 torture_assert_werr_equal(tctx, r.out.result, expected_result,
5896 "OpenPrinterEx failed");
5901 static bool call_OpenPrinterEx(struct torture_context *tctx,
5902 struct dcerpc_pipe *p,
5904 struct spoolss_DeviceMode *devmode,
5905 struct policy_handle *handle)
5907 union spoolss_UserLevel userlevel;
5908 struct spoolss_UserLevel1 userlevel1;
5909 struct dcerpc_binding_handle *b = p->binding_handle;
5911 userlevel1.size = 1234;
5912 userlevel1.client = "hello";
5913 userlevel1.user = "spottyfoot!";
5914 userlevel1.build = 1;
5915 userlevel1.major = 2;
5916 userlevel1.minor = 3;
5917 userlevel1.processor = 4;
5919 userlevel.level1 = &userlevel1;
5921 return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
5922 SEC_FLAG_MAXIMUM_ALLOWED,
5929 static bool test_printer_rename(struct torture_context *tctx,
5932 struct torture_printer_context *t =
5933 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
5934 struct dcerpc_pipe *p = t->spoolss_pipe;
5937 union spoolss_PrinterInfo info;
5938 union spoolss_SetPrinterInfo sinfo;
5939 struct spoolss_SetPrinterInfoCtr info_ctr;
5940 struct spoolss_DevmodeContainer devmode_ctr;
5941 struct sec_desc_buf secdesc_ctr;
5942 const char *printer_name;
5943 const char *printer_name_orig;
5944 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5945 struct policy_handle new_handle;
5947 struct dcerpc_binding_handle *b = p->binding_handle;
5949 ZERO_STRUCT(devmode_ctr);
5950 ZERO_STRUCT(secdesc_ctr);
5952 torture_comment(tctx, "Testing Printer rename operations\n");
5954 torture_assert(tctx,
5955 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5956 "failed to call GetPrinter level 2");
5958 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5960 q = strrchr(info.info2.printername, '\\');
5962 torture_warning(tctx,
5963 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5966 torture_assert(tctx,
5967 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5969 sinfo.info2->printername = printer_name_new;
5972 info_ctr.info = sinfo;
5974 torture_assert(tctx,
5975 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5976 "failed to call SetPrinter level 2");
5978 torture_assert(tctx,
5979 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5980 "failed to call GetPrinter level 2");
5982 printer_name = talloc_strdup(tctx, info.info2.printername);
5984 q = strrchr(info.info2.printername, '\\');
5986 torture_warning(tctx,
5987 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5992 torture_assert_str_equal(tctx, printer_name, printer_name_new,
5993 "new printer name was not set");
5995 /* samba currently cannot fully rename printers */
5996 if (!torture_setting_bool(tctx, "samba3", false)) {
5997 torture_assert(tctx,
5998 test_OpenPrinter_badname(tctx, b, printer_name_orig),
5999 "still can open printer with oldname after rename");
6001 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
6004 torture_assert(tctx,
6005 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
6006 "failed to open printer with new name");
6008 torture_assert(tctx,
6009 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
6010 "failed to call GetPrinter level 2");
6012 torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
6013 "new printer name was not set");
6015 torture_assert(tctx,
6016 test_ClosePrinter(tctx, b, &new_handle),
6017 "failed to close printer");
6019 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
6024 static bool test_openprinter(struct torture_context *tctx,
6025 struct dcerpc_binding_handle *b,
6026 const char *real_printername)
6028 union spoolss_UserLevel userlevel;
6029 struct policy_handle handle;
6030 struct spoolss_UserLevel1 userlevel1;
6031 const char *printername = NULL;
6036 WERROR expected_result;
6039 .suffix = "rubbish",
6040 .expected_result = WERR_INVALID_PRINTER_NAME
6042 .suffix = ", LocalOnl",
6043 .expected_result = WERR_INVALID_PRINTER_NAME
6045 .suffix = ", localOnly",
6046 .expected_result = WERR_INVALID_PRINTER_NAME
6048 .suffix = ", localonl",
6049 .expected_result = WERR_INVALID_PRINTER_NAME
6051 .suffix = ",LocalOnl",
6052 .expected_result = WERR_INVALID_PRINTER_NAME
6054 .suffix = ",localOnl2",
6055 .expected_result = WERR_INVALID_PRINTER_NAME
6057 .suffix = ", DrvConver2t",
6058 .expected_result = WERR_INVALID_PRINTER_NAME
6060 .suffix = ", drvconvert",
6061 .expected_result = WERR_INVALID_PRINTER_NAME
6063 .suffix = ",drvconvert",
6064 .expected_result = WERR_INVALID_PRINTER_NAME
6066 .suffix = ", DrvConvert",
6067 .expected_result = WERR_OK
6069 .suffix = " , DrvConvert",
6070 .expected_result = WERR_INVALID_PRINTER_NAME
6072 .suffix = ",DrvConvert",
6073 .expected_result = WERR_OK
6075 .suffix = ", DrvConvertsadfasdf",
6076 .expected_result = WERR_OK
6078 .suffix = ",DrvConvertasdfasd",
6079 .expected_result = WERR_OK
6081 .suffix = ", LocalOnly",
6082 .expected_result = WERR_OK
6084 .suffix = " , LocalOnly",
6085 .expected_result = WERR_INVALID_PRINTER_NAME
6087 .suffix = ",LocalOnly",
6088 .expected_result = WERR_OK
6090 .suffix = ", LocalOnlysagi4gjfkd",
6091 .expected_result = WERR_OK
6093 .suffix = ",LocalOnlysagi4gjfkd",
6094 .expected_result = WERR_OK
6098 userlevel1.size = 1234;
6099 userlevel1.client = "hello";
6100 userlevel1.user = "spottyfoot!";
6101 userlevel1.build = 1;
6102 userlevel1.major = 2;
6103 userlevel1.minor = 3;
6104 userlevel1.processor = 4;
6106 userlevel.level1 = &userlevel1;
6108 torture_comment(tctx, "Testing openprinterex printername pattern\n");
6110 torture_assert(tctx,
6111 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0, 1,
6112 &userlevel, &handle,
6114 "OpenPrinterEx failed");
6115 test_ClosePrinter(tctx, b, &handle);
6117 for (i=0; i < ARRAY_SIZE(tests); i++) {
6119 printername = talloc_asprintf(tctx, "%s%s",
6123 torture_assert(tctx,
6124 test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0, 1,
6125 &userlevel, &handle,
6126 tests[i].expected_result),
6127 "OpenPrinterEx failed");
6128 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6129 test_ClosePrinter(tctx, b, &handle);
6137 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6138 struct dcerpc_pipe *p,
6140 const char *environment)
6142 struct policy_handle handle;
6144 struct dcerpc_binding_handle *b = p->binding_handle;
6146 if (!test_openprinter(tctx, b, name)) {
6150 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6154 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6158 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6162 if (!test_EnumForms_all(tctx, b, &handle, false)) {
6166 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6170 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6174 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6178 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6182 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6186 if (!test_printer_all_keys(tctx, b, &handle)) {
6190 if (!test_PausePrinter(tctx, b, &handle)) {
6194 if (!test_DoPrintTest(tctx, b, &handle)) {
6198 if (!test_ResumePrinter(tctx, b, &handle)) {
6202 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
6206 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
6210 if (!torture_setting_bool(tctx, "samba3", false)) {
6211 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6216 if (!test_ClosePrinter(tctx, b, &handle)) {
6223 static bool test_EnumPrinters_old(struct torture_context *tctx,
6226 struct test_spoolss_context *ctx =
6227 talloc_get_type_abort(private_data, struct test_spoolss_context);
6228 struct spoolss_EnumPrinters r;
6230 uint16_t levels[] = {1, 2, 4, 5};
6233 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6234 struct dcerpc_binding_handle *b = p->binding_handle;
6236 for (i=0;i<ARRAY_SIZE(levels);i++) {
6237 union spoolss_PrinterInfo *info;
6242 r.in.flags = PRINTER_ENUM_LOCAL;
6244 r.in.level = levels[i];
6247 r.out.needed = &needed;
6248 r.out.count = &count;
6251 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6253 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6254 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6256 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6257 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6258 r.in.buffer = &blob;
6259 r.in.offered = needed;
6260 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6263 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6265 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6267 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6270 torture_comment(tctx, "No printers returned\n");
6274 for (j=0;j<count;j++) {
6275 if (r.in.level == 1) {
6276 char *unc = talloc_strdup(tctx, info[j].info1.name);
6277 char *slash, *name, *full_name;
6279 if (unc[0] == '\\' && unc[1] == '\\') {
6282 slash = strchr(unc, '\\');
6287 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6288 dcerpc_server_name(p), name);
6289 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6292 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6295 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6298 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6308 static bool test_EnumPrinters_level(struct torture_context *tctx,
6309 struct dcerpc_binding_handle *b,
6311 const char *servername,
6314 union spoolss_PrinterInfo **info_p)
6316 struct spoolss_EnumPrinters r;
6317 union spoolss_PrinterInfo *info;
6322 r.in.server = servername;
6326 r.out.needed = &needed;
6327 r.out.count = &count;
6330 torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6331 r.in.server, r.in.level);
6333 torture_assert_ntstatus_ok(tctx,
6334 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6335 "EnumPrinters failed");
6336 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6337 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6338 r.in.buffer = &blob;
6339 r.in.offered = needed;
6340 torture_assert_ntstatus_ok(tctx,
6341 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6342 "EnumPrinters failed");
6345 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6347 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6359 static const char *get_short_printername(struct torture_context *tctx,
6362 const char *short_name;
6364 if (name[0] == '\\' && name[1] == '\\') {
6366 short_name = strchr(name, '\\');
6368 return talloc_strdup(tctx, short_name+1);
6375 static const char *get_full_printername(struct torture_context *tctx,
6378 const char *full_name = talloc_strdup(tctx, name);
6381 if (name && name[0] == '\\' && name[1] == '\\') {
6383 p = strchr(name, '\\');
6392 static bool test_OnePrinter_servername(struct torture_context *tctx,
6393 struct dcerpc_pipe *p,
6394 struct dcerpc_binding_handle *b,
6395 const char *servername,
6396 const char *printername)
6398 union spoolss_PrinterInfo info;
6399 const char *short_name = get_short_printername(tctx, printername);
6400 const char *full_name = get_full_printername(tctx, printername);
6403 struct policy_handle handle;
6404 torture_assert(tctx,
6405 call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
6406 "failed to open printer");
6408 torture_assert(tctx,
6409 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6410 "failed to get printer info");
6412 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
6413 "unexpected servername");
6414 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
6415 "unexpected printername");
6417 if (info.info2.devmode) {
6418 const char *expected_devicename;
6419 expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
6420 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6421 "unexpected devicemode devicename");
6424 torture_assert(tctx,
6425 test_ClosePrinter(tctx, b, &handle),
6426 "failed to close printer");
6430 struct policy_handle handle;
6432 torture_assert(tctx,
6433 call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
6434 "failed to open printer");
6436 torture_assert(tctx,
6437 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6438 "failed to get printer info");
6440 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
6441 "unexpected servername");
6442 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
6443 "unexpected printername");
6445 if (info.info2.devmode) {
6446 const char *expected_devicename;
6447 expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
6448 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6449 "unexpected devicemode devicename");
6452 torture_assert(tctx,
6453 test_ClosePrinter(tctx, b, &handle),
6454 "failed to close printer");
6460 static bool test_EnumPrinters_servername(struct torture_context *tctx,
6463 struct test_spoolss_context *ctx =
6464 talloc_get_type_abort(private_data, struct test_spoolss_context);
6466 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6467 struct dcerpc_binding_handle *b = p->binding_handle;
6469 union spoolss_PrinterInfo *info;
6470 const char *servername;
6471 uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
6473 torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6475 servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6477 torture_assert(tctx,
6478 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6479 "failed to enumerate printers");
6481 for (i=0; i < count; i++) {
6483 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
6484 "unexpected servername");
6486 torture_assert(tctx,
6487 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6488 "failed to check printer");
6493 torture_assert(tctx,
6494 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6495 "failed to enumerate printers");
6497 for (i=0; i < count; i++) {
6499 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
6500 "unexpected servername");
6502 torture_assert(tctx,
6503 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6504 "failed to check printer");
6512 static bool test_GetPrinterDriver(struct torture_context *tctx,
6513 struct dcerpc_binding_handle *b,
6514 struct policy_handle *handle,
6515 const char *driver_name)
6517 struct spoolss_GetPrinterDriver r;
6520 r.in.handle = handle;
6521 r.in.architecture = "W32X86";
6525 r.out.needed = &needed;
6527 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
6529 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6530 "failed to call GetPrinterDriver");
6531 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6532 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6533 r.in.buffer = &blob;
6534 r.in.offered = needed;
6535 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6536 "failed to call GetPrinterDriver");
6539 torture_assert_werr_ok(tctx, r.out.result,
6540 "failed to call GetPrinterDriver");
6542 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6547 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
6548 struct dcerpc_binding_handle *b,
6549 struct policy_handle *handle,
6550 const char *driver_name,
6551 const char *architecture,
6553 uint32_t client_major_version,
6554 uint32_t client_minor_version,
6555 union spoolss_DriverInfo *info_p,
6559 struct spoolss_GetPrinterDriver2 r;
6561 uint32_t server_major_version;
6562 uint32_t server_minor_version;
6564 r.in.handle = handle;
6565 r.in.architecture = architecture;
6566 r.in.client_major_version = client_major_version;
6567 r.in.client_minor_version = client_minor_version;
6571 r.out.needed = &needed;
6572 r.out.server_major_version = &server_major_version;
6573 r.out.server_minor_version = &server_minor_version;
6575 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
6576 driver_name, r.in.level);
6578 torture_assert_ntstatus_ok(tctx,
6579 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6580 "failed to call GetPrinterDriver2");
6581 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6582 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6583 r.in.buffer = &blob;
6584 r.in.offered = needed;
6585 torture_assert_ntstatus_ok(tctx,
6586 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6587 "failed to call GetPrinterDriver2");
6591 *result_p = r.out.result;
6594 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
6595 switch (r.in.level) {
6598 torture_comment(tctx,
6599 "level %d not implemented, not considering as an error\n",
6607 torture_assert_werr_ok(tctx, r.out.result,
6608 "failed to call GetPrinterDriver2");
6610 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6613 *info_p = *r.out.info;
6619 static bool test_GetPrinterDriver2(struct torture_context *tctx,
6620 struct dcerpc_binding_handle *b,
6621 struct policy_handle *handle,
6622 const char *driver_name,
6623 const char *architecture)
6625 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
6629 for (i=0;i<ARRAY_SIZE(levels);i++) {
6631 torture_assert(tctx,
6632 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
6639 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
6642 struct test_spoolss_context *ctx =
6643 talloc_get_type_abort(private_data, struct test_spoolss_context);
6644 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
6646 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6647 struct dcerpc_binding_handle *b = p->binding_handle;
6648 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6650 for (i=0;i<ARRAY_SIZE(levels);i++) {
6653 union spoolss_DriverInfo *info;
6655 torture_assert(tctx,
6656 test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
6657 "failed to enumerate drivers");
6660 torture_comment(tctx, "No printer drivers returned\n");
6668 static bool test_DeletePrinter(struct torture_context *tctx,
6669 struct dcerpc_binding_handle *b,
6670 struct policy_handle *handle)
6672 struct spoolss_DeletePrinter r;
6674 torture_comment(tctx, "Testing DeletePrinter\n");
6676 r.in.handle = handle;
6678 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
6679 "failed to delete printer");
6680 torture_assert_werr_ok(tctx, r.out.result,
6681 "failed to delete printer");
6686 static bool test_EnumPrinters_findname(struct torture_context *tctx,
6687 struct dcerpc_binding_handle *b,
6693 struct spoolss_EnumPrinters e;
6695 union spoolss_PrinterInfo *info;
6706 e.out.count = &count;
6708 e.out.needed = &needed;
6710 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6711 "failed to enum printers");
6713 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
6714 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6715 e.in.buffer = &blob;
6716 e.in.offered = needed;
6718 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6719 "failed to enum printers");
6722 torture_assert_werr_ok(tctx, e.out.result,
6723 "failed to enum printers");
6725 for (i=0; i < count; i++) {
6727 const char *current = NULL;
6732 current = info[i].info1.name;
6736 if (strequal(current, name)) {
6741 q = strrchr(current, '\\');
6744 torture_warning(tctx,
6745 "server returns printername %s incl. servername although we did not set servername", current);
6748 if (strequal(q, name)) {
6758 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
6759 struct dcerpc_pipe *p,
6760 const char *printername,
6764 struct spoolss_AddPrinter r;
6765 struct spoolss_AddPrinterEx rex;
6766 struct spoolss_SetPrinterInfoCtr info_ctr;
6767 struct spoolss_SetPrinterInfo1 info1;
6768 struct spoolss_DevmodeContainer devmode_ctr;
6769 struct sec_desc_buf secdesc_ctr;
6770 struct spoolss_UserLevelCtr userlevel_ctr;
6771 struct policy_handle handle;
6773 struct dcerpc_binding_handle *b = p->binding_handle;
6775 ZERO_STRUCT(devmode_ctr);
6776 ZERO_STRUCT(secdesc_ctr);
6777 ZERO_STRUCT(userlevel_ctr);
6780 torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
6781 ex ? "Ex":"", printername);
6783 /* try to add printer to wellknown printer list (level 1) */
6785 userlevel_ctr.level = 1;
6787 info_ctr.info.info1 = &info1;
6790 rex.in.server = NULL;
6791 rex.in.info_ctr = &info_ctr;
6792 rex.in.devmode_ctr = &devmode_ctr;
6793 rex.in.secdesc_ctr = &secdesc_ctr;
6794 rex.in.userlevel_ctr = &userlevel_ctr;
6795 rex.out.handle = &handle;
6798 r.in.info_ctr = &info_ctr;
6799 r.in.devmode_ctr = &devmode_ctr;
6800 r.in.secdesc_ctr = &secdesc_ctr;
6801 r.out.handle = &handle;
6803 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6804 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6805 "failed to add printer");
6806 result = ex ? rex.out.result : r.out.result;
6807 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6808 "unexpected result code");
6810 info1.name = printername;
6811 info1.flags = PRINTER_ATTRIBUTE_SHARED;
6813 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6814 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6815 "failed to add printer");
6816 result = ex ? rex.out.result : r.out.result;
6817 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6818 "unexpected result code");
6820 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6821 better do a real check to see the printer is really there */
6823 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6824 PRINTER_ENUM_NETWORK, 1,
6827 "failed to enum printers");
6829 torture_assert(tctx, found, "failed to find newly added printer");
6833 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6834 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6835 "failed to add printer");
6836 result = ex ? rex.out.result : r.out.result;
6837 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6838 "unexpected result code");
6840 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6841 better do a real check to see the printer has really been removed
6842 from the well known printer list */
6846 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6847 PRINTER_ENUM_NETWORK, 1,
6850 "failed to enum printers");
6852 torture_assert(tctx, !found, "printer still in well known printer list");
6857 static bool test_AddPrinter_normal(struct torture_context *tctx,
6858 struct dcerpc_pipe *p,
6859 struct policy_handle *handle_p,
6860 const char *printername,
6861 const char *drivername,
6862 const char *portname,
6863 struct spoolss_DeviceMode *devmode,
6867 struct spoolss_AddPrinter r;
6868 struct spoolss_AddPrinterEx rex;
6869 struct spoolss_SetPrinterInfoCtr info_ctr;
6870 struct spoolss_SetPrinterInfo2 info2;
6871 struct spoolss_DevmodeContainer devmode_ctr;
6872 struct sec_desc_buf secdesc_ctr;
6873 struct spoolss_UserLevelCtr userlevel_ctr;
6874 struct policy_handle handle;
6876 bool existing_printer_deleted = false;
6877 struct dcerpc_binding_handle *b = p->binding_handle;
6879 ZERO_STRUCT(devmode_ctr);
6880 ZERO_STRUCT(secdesc_ctr);
6881 ZERO_STRUCT(userlevel_ctr);
6883 torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
6884 ex ? "Ex":"", printername);
6886 devmode_ctr.devmode = devmode;
6888 userlevel_ctr.level = 1;
6890 rex.in.server = NULL;
6891 rex.in.info_ctr = &info_ctr;
6892 rex.in.devmode_ctr = &devmode_ctr;
6893 rex.in.secdesc_ctr = &secdesc_ctr;
6894 rex.in.userlevel_ctr = &userlevel_ctr;
6895 rex.out.handle = &handle;
6898 r.in.info_ctr = &info_ctr;
6899 r.in.devmode_ctr = &devmode_ctr;
6900 r.in.secdesc_ctr = &secdesc_ctr;
6901 r.out.handle = &handle;
6905 /* try to add printer to printer list (level 2) */
6909 info_ctr.info.info2 = &info2;
6912 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6913 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6914 "failed to add printer");
6915 result = ex ? rex.out.result : r.out.result;
6916 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6917 "unexpected result code");
6919 info2.printername = printername;
6921 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6922 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6923 "failed to add printer");
6924 result = ex ? rex.out.result : r.out.result;
6926 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
6927 struct policy_handle printer_handle;
6929 if (existing_printer_deleted) {
6930 torture_fail(tctx, "already deleted printer still existing?");
6933 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
6934 "failed to open printer handle");
6936 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
6937 "failed to delete printer");
6939 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
6940 "failed to close server handle");
6942 existing_printer_deleted = true;
6947 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
6948 "unexpected result code");
6950 info2.portname = portname;
6952 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6953 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6954 "failed to add printer");
6955 result = ex ? rex.out.result : r.out.result;
6956 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
6957 "unexpected result code");
6959 info2.drivername = drivername;
6961 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6962 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6963 "failed to add printer");
6964 result = ex ? rex.out.result : r.out.result;
6966 /* w2k8r2 allows to add printer w/o defining printprocessor */
6968 if (!W_ERROR_IS_OK(result)) {
6969 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
6970 "unexpected result code");
6972 info2.printprocessor = "winprint";
6974 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6975 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6976 "failed to add printer");
6977 result = ex ? rex.out.result : r.out.result;
6978 torture_assert_werr_ok(tctx, result,
6979 "failed to add printer");
6984 /* we are paranoid, really check if the printer is there now */
6986 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6987 PRINTER_ENUM_LOCAL, 1,
6990 "failed to enum printers");
6991 torture_assert(tctx, found, "failed to find newly added printer");
6993 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6994 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6995 "failed to add printer");
6996 result = ex ? rex.out.result : r.out.result;
6997 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6998 "unexpected result code");
7003 static bool test_printer_info(struct torture_context *tctx,
7006 struct torture_printer_context *t =
7007 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7008 struct dcerpc_pipe *p = t->spoolss_pipe;
7009 struct dcerpc_binding_handle *b = p->binding_handle;
7013 if (torture_setting_bool(tctx, "samba3", false)) {
7014 torture_skip(tctx, "skipping printer info cross tests against samba 3");
7017 if (!test_PrinterInfo(tctx, b, &t->handle)) {
7021 if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
7028 static bool test_EnumPrinterKey(struct torture_context *tctx,
7029 struct dcerpc_binding_handle *b,
7030 struct policy_handle *handle,
7031 const char *key_name,
7032 const char ***array)
7034 struct spoolss_EnumPrinterKey r;
7035 uint32_t needed = 0;
7036 union spoolss_KeyNames key_buffer;
7037 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7041 r.in.handle = handle;
7042 r.in.key_name = key_name;
7043 r.out.key_buffer = &key_buffer;
7044 r.out.needed = &needed;
7045 r.out._ndr_size = &_ndr_size;
7047 for (i=0; i < ARRAY_SIZE(offered); i++) {
7049 if (offered[i] < 0 && needed) {
7053 r.in.offered = needed + offered[i];
7055 r.in.offered = offered[i];
7058 ZERO_STRUCT(key_buffer);
7060 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
7062 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7063 "failed to call EnumPrinterKey");
7064 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
7066 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7067 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7068 _ndr_size, r.in.offered/2));
7070 r.in.offered = needed;
7071 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7072 "failed to call EnumPrinterKey");
7075 if (offered[i] > 0) {
7076 torture_assert_werr_ok(tctx, r.out.result,
7077 "failed to call EnumPrinterKey");
7080 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7081 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7082 _ndr_size, r.in.offered/2));
7084 torture_assert(tctx, (*r.out.needed <= r.in.offered),
7085 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
7087 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
7088 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
7090 if (key_buffer.string_array) {
7091 uint32_t calc_needed = 0;
7093 for (s=0; key_buffer.string_array[s]; s++) {
7094 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7096 if (!key_buffer.string_array[0]) {
7101 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7102 "EnumPrinterKey unexpected size");
7107 *array = key_buffer.string_array;
7113 bool test_printer_all_keys(struct torture_context *tctx,
7114 struct dcerpc_binding_handle *b,
7115 struct policy_handle *handle)
7117 const char **key_array = NULL;
7120 torture_comment(tctx, "Testing Printer Keys\n");
7122 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7123 "failed to call test_EnumPrinterKey");
7125 for (i=0; key_array && key_array[i]; i++) {
7126 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7127 "failed to call test_EnumPrinterKey");
7129 for (i=0; key_array && key_array[i]; i++) {
7130 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7131 "failed to call test_EnumPrinterDataEx");
7134 torture_comment(tctx, "Printer Keys test succeeded\n\n");
7139 static bool test_openprinter_wrap(struct torture_context *tctx,
7142 struct torture_printer_context *t =
7143 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7144 struct dcerpc_pipe *p = t->spoolss_pipe;
7145 struct dcerpc_binding_handle *b = p->binding_handle;
7146 const char *printername = t->info2.printername;
7148 return test_openprinter(tctx, b, printername);
7151 static bool test_csetprinter(struct torture_context *tctx,
7154 struct torture_printer_context *t =
7155 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7156 struct dcerpc_pipe *p = t->spoolss_pipe;
7158 const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7159 const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7160 const char *portname = t->info2.portname;
7162 union spoolss_PrinterInfo info;
7163 struct policy_handle new_handle, new_handle2;
7164 struct dcerpc_binding_handle *b = p->binding_handle;
7166 torture_comment(tctx, "Testing c_setprinter\n");
7168 torture_assert(tctx,
7169 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7170 "failed to get level 0 printer info");
7171 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7172 info.info0.c_setprinter);
7174 /* check if c_setprinter on 1st handle increases after a printer has
7177 torture_assert(tctx,
7178 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7179 "failed to add new printer");
7180 torture_assert(tctx,
7181 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7182 "failed to get level 0 printer info");
7183 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7184 info.info0.c_setprinter);
7186 /* check if c_setprinter on new handle increases after a printer has
7189 torture_assert(tctx,
7190 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7191 "failed to get level 0 printer info");
7192 torture_comment(tctx, "csetprinter on created handle: %d\n",
7193 info.info0.c_setprinter);
7195 /* open the new printer and check if c_setprinter increases */
7197 torture_assert(tctx,
7198 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7199 "failed to open created printer");
7200 torture_assert(tctx,
7201 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
7202 "failed to get level 0 printer info");
7203 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
7204 info.info0.c_setprinter);
7208 torture_assert(tctx,
7209 test_ClosePrinter(tctx, b, &new_handle2),
7210 "failed to close printer");
7211 torture_assert(tctx,
7212 test_DeletePrinter(tctx, b, &new_handle),
7213 "failed to delete new printer");
7218 static bool compose_local_driver_directory(struct torture_context *tctx,
7219 const char *environment,
7220 const char *local_dir,
7225 p = strrchr(local_dir, '/');
7231 if (strequal(environment, "Windows x64")) {
7232 if (!strequal(p, "x64")) {
7233 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
7235 } else if (strequal(environment, "Windows NT x86")) {
7236 if (!strequal(p, "i386")) {
7237 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
7240 torture_assert(tctx, "unknown environment: '%s'\n", environment);
7246 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
7247 const char *devicename)
7249 struct spoolss_DeviceMode *r;
7251 r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
7256 r->devicename = talloc_strdup(r, devicename);
7257 r->specversion = DMSPEC_NT4_AND_ABOVE;
7258 r->driverversion = 0x0600;
7260 r->__driverextra_length = 0;
7261 r->fields = DEVMODE_FORMNAME |
7263 DEVMODE_PRINTQUALITY |
7264 DEVMODE_DEFAULTSOURCE |
7268 DEVMODE_ORIENTATION;
7269 r->orientation = DMORIENT_PORTRAIT;
7270 r->papersize = DMPAPER_LETTER;
7275 r->defaultsource = DMBIN_FORMSOURCE;
7276 r->printquality = DMRES_HIGH;
7277 r->color = DMRES_MONOCHROME;
7278 r->duplex = DMDUP_SIMPLEX;
7280 r->ttoption = DMTT_SUBDEV;
7281 r->collate = DMCOLLATE_FALSE;
7282 r->formname = talloc_strdup(r, "Letter");
7287 static bool test_architecture_buffer(struct torture_context *tctx,
7290 struct test_spoolss_context *ctx =
7291 talloc_get_type_abort(private_data, struct test_spoolss_context);
7293 struct spoolss_OpenPrinterEx r;
7294 struct spoolss_UserLevel1 u1;
7295 struct policy_handle handle;
7296 uint32_t architectures[] = {
7297 PROCESSOR_ARCHITECTURE_INTEL,
7298 PROCESSOR_ARCHITECTURE_IA64,
7299 PROCESSOR_ARCHITECTURE_AMD64
7303 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7304 struct dcerpc_binding_handle *b = p->binding_handle;
7306 for (i=0; i < ARRAY_SIZE(architectures); i++) {
7308 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7316 u1.processor = architectures[i];
7318 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7319 r.in.datatype = NULL;
7320 r.in.devmode_ctr.devmode= NULL;
7321 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7323 r.in.userlevel.level1 = &u1;
7324 r.out.handle = &handle;
7326 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7327 torture_assert_werr_ok(tctx, r.out.result, "");
7330 struct spoolss_EnumPrinters e;
7332 union spoolss_PrinterInfo *info;
7334 e.in.flags = PRINTER_ENUM_LOCAL;
7339 e.out.count = &count;
7341 e.out.needed = &needed[i];
7343 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7345 torture_comment(tctx, "needed was %d\n", needed[i]);
7349 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7352 for (i=1; i < ARRAY_SIZE(architectures); i++) {
7353 if (needed[i-1] != needed[i]) {
7355 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7356 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7363 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
7366 struct test_spoolss_context *ctx =
7367 talloc_get_type_abort(private_data, struct test_spoolss_context);
7368 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7369 struct dcerpc_binding_handle *b = p->binding_handle;
7371 return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
7374 static bool test_PrintServer_Forms(struct torture_context *tctx,
7377 struct test_spoolss_context *ctx =
7378 talloc_get_type_abort(private_data, struct test_spoolss_context);
7379 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7380 struct dcerpc_binding_handle *b = p->binding_handle;
7382 return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
7385 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
7388 struct test_spoolss_context *ctx =
7389 talloc_get_type_abort(private_data, struct test_spoolss_context);
7390 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7391 struct dcerpc_binding_handle *b = p->binding_handle;
7393 return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
7396 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
7400 status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
7402 torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
7404 torture_assert(tctx,
7405 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
7406 "failed to open printserver");
7407 torture_assert(tctx,
7408 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
7409 "failed to get environment");
7414 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
7416 struct test_spoolss_context *t;
7418 *data = t = talloc_zero(tctx, struct test_spoolss_context);
7420 return torture_rpc_spoolss_setup_common(tctx, t);
7423 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
7425 test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
7430 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
7432 struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
7435 ret = torture_rpc_spoolss_teardown_common(tctx, t);
7441 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
7443 struct dcerpc_pipe *p;
7444 struct dcerpc_binding_handle *b;
7445 const char *server_name_slash;
7446 const char *driver_name;
7447 const char *printer_name;
7448 const char *port_name;
7450 torture_assert_ntstatus_ok(tctx,
7451 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
7452 "Error connecting to server");
7454 p = t->spoolss_pipe;
7455 b = p->binding_handle;
7456 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7458 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
7459 t->driver.info8.driver_name = TORTURE_DRIVER;
7460 t->driver.info8.driver_path = "pscript5.dll";
7461 t->driver.info8.data_file = "cups6.ppd";
7462 t->driver.info8.config_file = "ps5ui.dll";
7463 t->driver.info8.help_file = "pscript.hlp";
7464 t->driver.info8.default_datatype = "RAW";
7465 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
7466 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
7467 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
7468 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
7469 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
7470 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
7471 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
7472 t->driver.info8.dependent_files->string[5] = "cups6.ini";
7473 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
7474 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
7476 t->driver.local.driver_directory= "/usr/share/cups/drivers";
7478 t->info2.drivername = "Microsoft XPS Document Writer";
7479 t->info2.portname = "LPT1:";
7481 printer_name = t->info2.printername;
7482 port_name = t->info2.portname;
7484 torture_assert(tctx,
7485 fillup_printserver_info(tctx, p, &t->driver),
7486 "failed to fillup printserver info");
7488 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
7490 torture_assert(tctx,
7491 compose_local_driver_directory(tctx, t->driver.remote.environment,
7492 t->driver.local.driver_directory,
7493 &t->driver.local.driver_directory),
7494 "failed to compose local driver directory");
7496 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7497 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7498 t->info2.drivername, t->driver.remote.environment);
7499 t->have_driver = true;
7503 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
7504 t->info2.drivername, t->driver.remote.environment);
7505 torture_comment(tctx, "trying to upload own driver\n");
7507 if (!directory_exist(t->driver.local.driver_directory)) {
7508 torture_warning(tctx, "no local driver is available!");
7509 t->have_driver = false;
7513 torture_assert(tctx,
7514 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
7515 "failed to upload printer driver");
7517 torture_assert(tctx,
7518 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
7519 "failed to add driver");
7521 t->added_driver = true;
7522 t->have_driver = true;
7525 driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7528 torture_assert(tctx,
7529 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
7530 "failed to add wellknown printer");
7532 torture_assert(tctx,
7533 test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
7534 "failed to add printer");
7540 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
7542 struct torture_printer_context *t;
7544 *data = t = talloc_zero(tctx, struct torture_printer_context);
7547 t->wellknown = false;
7548 t->info2.printername = TORTURE_PRINTER;
7551 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7554 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
7556 struct torture_printer_context *t;
7558 *data = t = talloc_zero(tctx, struct torture_printer_context);
7561 t->wellknown = false;
7562 t->info2.printername = TORTURE_PRINTER_EX;
7565 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7568 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
7570 struct torture_printer_context *t;
7572 *data = t = talloc_zero(tctx, struct torture_printer_context);
7575 t->wellknown = true;
7576 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
7581 torture_skip(tctx, "skipping AddPrinter level 1");
7584 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7587 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
7589 struct torture_printer_context *t;
7591 *data = t = talloc_zero(tctx, struct torture_printer_context);
7594 t->wellknown = true;
7595 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
7600 torture_skip(tctx, "skipping AddPrinterEx level 1");
7603 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7606 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
7608 struct torture_printer_context *t;
7610 *data = t = talloc_zero(tctx, struct torture_printer_context);
7613 t->wellknown = false;
7614 t->info2.printername = TORTURE_PRINTER_EX;
7615 t->devmode = torture_devicemode(t, TORTURE_PRINTER_EX);
7617 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7620 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
7623 struct dcerpc_pipe *p = t->spoolss_pipe;
7624 struct dcerpc_binding_handle *b;
7625 const char *printer_name = t->info2.printername;
7627 if (t->added_driver) {
7628 torture_assert(tctx,
7629 remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
7630 "failed to remove printer driver");
7634 b = p->binding_handle;
7637 if (!t->wellknown) {
7638 torture_assert(tctx,
7639 test_DeletePrinter(tctx, b, &t->handle),
7640 "failed to delete printer");
7642 torture_assert(tctx,
7643 test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
7644 printer_name, &found),
7645 "failed to enumerate printers");
7647 torture_assert(tctx, !found, "deleted printer still there");
7653 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
7655 struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
7658 ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
7664 static bool test_print_test(struct torture_context *tctx,
7667 struct torture_printer_context *t =
7668 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7669 struct dcerpc_pipe *p = t->spoolss_pipe;
7670 struct dcerpc_binding_handle *b = p->binding_handle;
7672 torture_assert(tctx,
7673 test_PausePrinter(tctx, b, &t->handle),
7674 "failed to pause printer");
7676 torture_assert(tctx,
7677 test_DoPrintTest(tctx, b, &t->handle),
7678 "failed to do print test");
7680 torture_assert(tctx,
7681 test_ResumePrinter(tctx, b, &t->handle),
7682 "failed to resume printer");
7687 static bool test_print_test_extended(struct torture_context *tctx,
7690 struct torture_printer_context *t =
7691 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7692 struct dcerpc_pipe *p = t->spoolss_pipe;
7693 struct dcerpc_binding_handle *b = p->binding_handle;
7696 torture_assert(tctx,
7697 test_PausePrinter(tctx, b, &t->handle),
7698 "failed to pause printer");
7700 ret = test_DoPrintTest_extended(tctx, b, &t->handle);
7702 torture_comment(tctx, "WARNING! failed to do extended print test\n");
7703 if (torture_setting_bool(tctx, "samba3", false)) {
7704 torture_comment(tctx, "non-critical for samba3\n");
7706 tctx->last_result = TORTURE_SKIP;
7710 torture_assert(tctx,
7711 test_ResumePrinter(tctx, b, &t->handle),
7712 "failed to resume printer");
7717 static bool test_printer_sd(struct torture_context *tctx,
7720 struct torture_printer_context *t =
7721 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7722 struct dcerpc_pipe *p = t->spoolss_pipe;
7723 struct dcerpc_binding_handle *b = p->binding_handle;
7725 torture_assert(tctx,
7726 test_PrinterInfo_SD(tctx, b, &t->handle),
7727 "failed to test security descriptors");
7732 static bool test_printer_dm(struct torture_context *tctx,
7735 struct torture_printer_context *t =
7736 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7737 struct dcerpc_pipe *p = t->spoolss_pipe;
7739 torture_assert(tctx,
7740 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
7741 "failed to test devicemodes");
7746 static bool test_printer_info_winreg(struct torture_context *tctx,
7749 struct torture_printer_context *t =
7750 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7751 struct dcerpc_pipe *p = t->spoolss_pipe;
7753 torture_assert(tctx,
7754 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
7755 "failed to test printer info winreg");
7760 static bool test_printer_change_id(struct torture_context *tctx,
7763 struct torture_printer_context *t =
7764 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7765 struct dcerpc_pipe *p = t->spoolss_pipe;
7767 torture_assert(tctx,
7768 test_ChangeID(tctx, p, &t->handle),
7769 "failed to test change id");
7774 static bool test_printer_keys(struct torture_context *tctx,
7777 struct torture_printer_context *t =
7778 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7779 struct dcerpc_pipe *p = t->spoolss_pipe;
7780 struct dcerpc_binding_handle *b = p->binding_handle;
7782 torture_assert(tctx,
7783 test_printer_all_keys(tctx, b, &t->handle),
7784 "failed to test printer keys");
7789 static bool test_printer_data_consistency(struct torture_context *tctx,
7792 struct torture_printer_context *t =
7793 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7794 struct dcerpc_pipe *p = t->spoolss_pipe;
7796 torture_assert(tctx,
7797 test_EnumPrinterData_consistency(tctx, p, &t->handle),
7798 "failed to test printer data consistency");
7803 static bool test_printer_data_keys(struct torture_context *tctx,
7806 struct torture_printer_context *t =
7807 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7808 struct dcerpc_pipe *p = t->spoolss_pipe;
7810 torture_assert(tctx,
7811 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
7812 "failed to test printer data keys");
7817 static bool test_printer_data_values(struct torture_context *tctx,
7820 struct torture_printer_context *t =
7821 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7822 struct dcerpc_pipe *p = t->spoolss_pipe;
7824 torture_assert(tctx,
7825 test_SetPrinterDataEx_values(tctx, p, &t->handle),
7826 "failed to test printer data values");
7831 static bool test_printer_data_set(struct torture_context *tctx,
7834 struct torture_printer_context *t =
7835 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7836 struct dcerpc_pipe *p = t->spoolss_pipe;
7838 torture_assert(tctx,
7839 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
7840 "failed to test printer data set");
7845 static bool test_printer_data_winreg(struct torture_context *tctx,
7848 struct torture_printer_context *t =
7849 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7850 struct dcerpc_pipe *p = t->spoolss_pipe;
7852 torture_assert(tctx,
7853 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
7854 "failed to test printer data winreg");
7859 static bool test_printer_data_dsspooler(struct torture_context *tctx,
7862 struct torture_printer_context *t =
7863 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7864 struct dcerpc_pipe *p = t->spoolss_pipe;
7866 torture_assert(tctx,
7867 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
7868 "failed to test printer data winreg dsspooler");
7873 static bool test_driver_info_winreg(struct torture_context *tctx,
7876 struct torture_printer_context *t =
7877 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7878 struct dcerpc_pipe *p = t->spoolss_pipe;
7879 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7881 if (!t->have_driver) {
7882 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
7885 torture_assert(tctx,
7886 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
7887 "failed to test driver info winreg");
7892 void torture_tcase_printer(struct torture_tcase *tcase)
7894 torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
7895 torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
7896 torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
7897 torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
7898 torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
7899 torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
7900 torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
7901 torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
7902 torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
7903 torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
7904 torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
7905 torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
7906 torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
7907 torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
7908 torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
7909 torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
7910 torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
7911 torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
7914 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
7916 struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
7917 struct torture_tcase *tcase;
7919 tcase = torture_suite_add_tcase(suite, "addprinter");
7921 torture_tcase_set_fixture(tcase,
7922 torture_rpc_spoolss_printer_setup,
7923 torture_rpc_spoolss_printer_teardown);
7925 torture_tcase_printer(tcase);
7927 tcase = torture_suite_add_tcase(suite, "addprinterex");
7929 torture_tcase_set_fixture(tcase,
7930 torture_rpc_spoolss_printerex_setup,
7931 torture_rpc_spoolss_printer_teardown);
7933 torture_tcase_printer(tcase);
7935 tcase = torture_suite_add_tcase(suite, "addprinterwkn");
7937 torture_tcase_set_fixture(tcase,
7938 torture_rpc_spoolss_printerwkn_setup,
7939 torture_rpc_spoolss_printer_teardown);
7941 tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
7943 torture_tcase_set_fixture(tcase,
7944 torture_rpc_spoolss_printerexwkn_setup,
7945 torture_rpc_spoolss_printer_teardown);
7948 /* test is not correct */
7949 tcase = torture_suite_add_tcase(suite, "addprinterdm");
7951 torture_tcase_set_fixture(tcase,
7952 torture_rpc_spoolss_printerdm_setup,
7953 torture_rpc_spoolss_printer_teardown);
7955 torture_tcase_printer(tcase);
7960 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
7962 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
7963 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
7965 torture_tcase_set_fixture(tcase,
7966 torture_rpc_spoolss_setup,
7967 torture_rpc_spoolss_teardown);
7969 torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
7970 torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
7971 torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
7972 torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
7973 torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
7974 torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
7975 torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
7976 torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
7977 torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
7978 torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
7979 torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
7980 torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
7981 torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
7982 torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
7983 torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
7984 torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
7985 torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
7986 torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
7987 torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
7988 torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
7990 torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
7995 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
7996 struct dcerpc_binding_handle *b,
7998 const char *environment,
8001 struct spoolss_GetPrinterDriverDirectory r;
8004 r.in.server = server;
8005 r.in.environment = environment;
8009 r.out.needed = &needed;
8011 torture_assert_ntstatus_ok(tctx,
8012 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8013 "failed to query driver directory");
8015 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
8016 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
8017 r.in.buffer = &blob;
8018 r.in.offered = needed;
8020 torture_assert_ntstatus_ok(tctx,
8021 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8022 "failed to query driver directory");
8025 torture_assert_werr_ok(tctx, r.out.result,
8026 "failed to query driver directory");
8029 *dir_p = r.out.info->info1.directory_name;
8035 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8037 if (info_ctr == NULL) {
8041 switch (info_ctr->level) {
8043 return info_ctr->info.info1->driver_name;
8045 return info_ctr->info.info2->driver_name;
8047 return info_ctr->info.info3->driver_name;
8049 return info_ctr->info.info4->driver_name;
8051 return info_ctr->info.info6->driver_name;
8053 return info_ctr->info.info8->driver_name;
8059 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8061 if (info_ctr == NULL) {
8065 switch (info_ctr->level) {
8067 return info_ctr->info.info2->architecture;
8069 return info_ctr->info.info3->architecture;
8071 return info_ctr->info.info4->architecture;
8073 return info_ctr->info.info6->architecture;
8075 return info_ctr->info.info8->architecture;
8082 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
8083 struct dcerpc_binding_handle *b,
8084 const char *servername,
8085 struct spoolss_AddDriverInfoCtr *info_ctr,
8086 WERROR expected_result)
8088 struct spoolss_AddPrinterDriver r;
8089 const char *drivername = get_driver_from_info(info_ctr);
8090 const char *environment = get_environment_from_info(info_ctr);
8092 r.in.servername = servername;
8093 r.in.info_ctr = info_ctr;
8095 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
8096 drivername, info_ctr->level, environment);
8098 torture_assert_ntstatus_ok(tctx,
8099 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
8100 "spoolss_AddPrinterDriver failed");
8101 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8102 "spoolss_AddPrinterDriver failed with unexpected result");
8108 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
8109 struct dcerpc_binding_handle *b,
8110 const char *servername,
8111 struct spoolss_AddDriverInfoCtr *info_ctr,
8113 WERROR expected_result)
8115 struct spoolss_AddPrinterDriverEx r;
8116 const char *drivername = get_driver_from_info(info_ctr);
8117 const char *environment = get_environment_from_info(info_ctr);
8119 r.in.servername = servername;
8120 r.in.info_ctr = info_ctr;
8123 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
8124 drivername, info_ctr->level, environment);
8126 torture_assert_ntstatus_ok(tctx,
8127 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
8128 "AddPrinterDriverEx failed");
8129 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8130 "AddPrinterDriverEx failed with unexpected result");
8135 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
8136 if (path && strlen(path)) {\
8137 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
8140 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
8141 struct dcerpc_binding_handle *b,
8142 const char *server_name,
8143 struct spoolss_AddDriverInfo8 *r,
8146 const char *remote_driver_dir)
8148 struct spoolss_AddDriverInfoCtr info_ctr;
8149 struct spoolss_AddDriverInfo1 info1;
8154 info_ctr.info.info1 = &info1;
8157 torture_assert(tctx,
8158 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8159 "failed to test AddPrinterDriverEx level 1");
8161 torture_assert(tctx,
8162 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8163 "failed to test AddPrinterDriver level 1");
8166 info1.driver_name = r->driver_name;
8169 torture_assert(tctx,
8170 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8171 "failed to test AddPrinterDriverEx level 1");
8173 torture_assert(tctx,
8174 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8175 "failed to test AddPrinterDriver level 1");
8181 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
8182 struct dcerpc_binding_handle *b,
8183 const char *server_name,
8184 struct spoolss_AddDriverInfo8 *r,
8187 const char *remote_driver_dir)
8189 struct spoolss_AddDriverInfoCtr info_ctr;
8190 struct spoolss_AddDriverInfo2 info2;
8191 union spoolss_DriverInfo info;
8196 info_ctr.info.info2 = &info2;
8199 torture_assert(tctx,
8200 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8201 "failed to test AddPrinterDriverEx level 2");
8203 torture_assert(tctx,
8204 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8205 "failed to test AddPrinterDriver level 2");
8208 info2.driver_name = r->driver_name;
8211 torture_assert(tctx,
8212 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8213 "failed to test AddPrinterDriverEx level 2");
8215 torture_assert(tctx,
8216 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8217 "failed to test AddPrinterDriver level 2");
8220 info2.version = r->version;
8223 torture_assert(tctx,
8224 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8225 "failed to test AddPrinterDriverEx level 2");
8227 torture_assert(tctx,
8228 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8229 "failed to test AddPrinterDriver level 2");
8232 info2.architecture = r->architecture;
8235 torture_assert(tctx,
8236 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8237 "failed to test AddPrinterDriverEx level 2");
8239 torture_assert(tctx,
8240 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8241 "failed to test AddPrinterDriver level 2");
8244 info2.driver_path = r->driver_path;
8247 torture_assert(tctx,
8248 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8249 "failed to test AddPrinterDriverEx level 2");
8251 torture_assert(tctx,
8252 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8253 "failed to test AddPrinterDriver level 2");
8256 info2.data_file = r->data_file;
8259 torture_assert(tctx,
8260 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8261 "failed to test AddPrinterDriverEx level 2");
8263 torture_assert(tctx,
8264 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8265 "failed to test AddPrinterDriver level 2");
8268 info2.config_file = r->config_file;
8271 torture_assert(tctx,
8272 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
8273 "failed to test AddPrinterDriverEx");
8277 torture_assert(tctx,
8278 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8279 "failed to test AddPrinterDriverEx level 2");
8281 torture_assert(tctx,
8282 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8283 "failed to test AddPrinterDriver level 2");
8286 torture_assert(tctx,
8287 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
8288 "failed to find added printer driver");
8290 if (remote_driver_dir) {
8291 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
8292 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
8293 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
8299 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
8300 struct dcerpc_binding_handle *b,
8301 const char *server_name,
8302 struct spoolss_AddDriverInfo8 *r,
8305 const char *remote_driver_dir)
8307 struct spoolss_AddDriverInfoCtr info_ctr;
8308 struct spoolss_AddDriverInfo3 info3;
8309 union spoolss_DriverInfo info;
8311 info3.driver_name = r->driver_name;
8312 info3.version = r->version;
8313 info3.architecture = r->architecture;
8314 info3.driver_path = r->driver_path;
8315 info3.data_file = r->data_file;
8316 info3.config_file = r->config_file;
8317 info3.help_file = r->help_file;
8318 info3.monitor_name = r->monitor_name;
8319 info3.default_datatype = r->default_datatype;
8320 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8321 info3.dependent_files = r->dependent_files;
8324 info_ctr.info.info3 = &info3;
8327 torture_assert(tctx,
8328 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8329 "failed to test AddPrinterDriverEx level 3");
8331 torture_assert(tctx,
8332 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8333 "failed to test AddPrinterDriver level 3");
8336 torture_assert(tctx,
8337 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
8338 "failed to find added printer driver");
8340 if (remote_driver_dir) {
8342 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
8343 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
8344 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
8345 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
8346 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
8347 ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
8354 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
8355 struct dcerpc_binding_handle *b,
8356 const char *server_name,
8357 struct spoolss_AddDriverInfo8 *r,
8360 const char *remote_driver_dir)
8362 struct spoolss_AddDriverInfoCtr info_ctr;
8363 struct spoolss_AddDriverInfo4 info4;
8364 union spoolss_DriverInfo info;
8366 info4.version = r->version;
8367 info4.driver_name = r->driver_name;
8368 info4.architecture = r->architecture;
8369 info4.driver_path = r->driver_path;
8370 info4.data_file = r->data_file;
8371 info4.config_file = r->config_file;
8372 info4.help_file = r->help_file;
8373 info4.monitor_name = r->monitor_name;
8374 info4.default_datatype = r->default_datatype;
8375 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8376 info4.dependent_files = r->dependent_files;
8377 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
8378 info4.previous_names = r->previous_names;
8381 info_ctr.info.info4 = &info4;
8384 torture_assert(tctx,
8385 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8386 "failed to test AddPrinterDriverEx level 4");
8388 torture_assert(tctx,
8389 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8390 "failed to test AddPrinterDriver level 4");
8393 torture_assert(tctx,
8394 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
8395 "failed to find added printer driver");
8397 if (remote_driver_dir) {
8399 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
8400 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
8401 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
8402 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
8403 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
8404 ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
8411 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
8412 struct dcerpc_binding_handle *b,
8413 const char *server_name,
8414 struct spoolss_AddDriverInfo8 *r,
8417 const char *remote_driver_dir)
8419 struct spoolss_AddDriverInfoCtr info_ctr;
8420 struct spoolss_AddDriverInfo6 info6;
8421 union spoolss_DriverInfo info;
8423 info6.version = r->version;
8424 info6.driver_name = r->driver_name;
8425 info6.architecture = r->architecture;
8426 info6.driver_path = r->driver_path;
8427 info6.data_file = r->data_file;
8428 info6.config_file = r->config_file;
8429 info6.help_file = r->help_file;
8430 info6.monitor_name = r->monitor_name;
8431 info6.default_datatype = r->default_datatype;
8432 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8433 info6.dependent_files = r->dependent_files;
8434 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
8435 info6.previous_names = r->previous_names;
8436 info6.driver_date = r->driver_date;
8437 info6.driver_version = r->driver_version;
8438 info6.manufacturer_name = r->manufacturer_name;
8439 info6.manufacturer_url = r->manufacturer_url;
8440 info6.hardware_id = r->hardware_id;
8441 info6.provider = r->provider;
8444 info_ctr.info.info6 = &info6;
8447 torture_assert(tctx,
8448 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8449 "failed to test AddPrinterDriverEx level 6");
8451 torture_assert(tctx,
8452 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8453 "failed to test AddPrinterDriver level 6");
8456 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8462 torture_assert(tctx,
8463 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
8464 "failed to find added printer driver");
8466 if (remote_driver_dir) {
8468 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
8469 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
8470 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
8471 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
8472 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
8473 ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
8477 torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
8478 torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
8483 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
8484 struct dcerpc_binding_handle *b,
8485 const char *server_name,
8486 struct spoolss_AddDriverInfo8 *r,
8489 const char *remote_driver_dir)
8491 struct spoolss_AddDriverInfoCtr info_ctr;
8492 union spoolss_DriverInfo info;
8495 info_ctr.info.info8 = r;
8498 torture_assert(tctx,
8499 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8500 "failed to test AddPrinterDriverEx level 8");
8502 torture_assert(tctx,
8503 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8504 "failed to test AddPrinterDriver level 8");
8507 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8513 torture_assert(tctx,
8514 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
8515 "failed to find added printer driver");
8517 if (remote_driver_dir) {
8519 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
8520 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
8521 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
8522 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
8523 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
8524 ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
8528 torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
8529 torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
8534 #undef ASSERT_DRIVER_PATH
8536 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
8537 struct dcerpc_binding_handle *b,
8540 const char *environment,
8541 WERROR expected_result)
8543 struct spoolss_DeletePrinterDriver r;
8545 r.in.server = server;
8546 r.in.architecture = environment;
8547 r.in.driver = driver;
8549 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
8551 torture_assert_ntstatus_ok(tctx,
8552 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
8553 "DeletePrinterDriver failed");
8554 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8555 "DeletePrinterDriver failed with unexpected result");
8560 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
8561 struct dcerpc_binding_handle *b,
8564 const char *environment,
8565 uint32_t delete_flags,
8567 WERROR expected_result)
8569 struct spoolss_DeletePrinterDriverEx r;
8571 r.in.server = server;
8572 r.in.architecture = environment;
8573 r.in.driver = driver;
8574 r.in.delete_flags = delete_flags;
8575 r.in.version = version;
8577 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
8579 torture_assert_ntstatus_ok(tctx,
8580 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
8581 "DeletePrinterDriverEx failed");
8582 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8583 "DeletePrinterDriverEx failed with unexpected result");
8588 static bool test_DeletePrinterDriver(struct torture_context *tctx,
8589 struct dcerpc_binding_handle *b,
8590 const char *server_name,
8592 const char *environment)
8594 torture_assert(tctx,
8595 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
8596 "failed to delete driver");
8598 torture_assert(tctx,
8599 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
8600 "failed to delete driver");
8602 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8603 torture_fail(tctx, "deleted driver still enumerated");
8606 torture_assert(tctx,
8607 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
8608 "2nd delete failed");
8613 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
8614 struct dcerpc_binding_handle *b,
8615 const char *server_name,
8617 const char *environment,
8618 uint32_t delete_flags,
8621 torture_assert(tctx,
8622 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
8623 "failed to delete driver");
8625 torture_assert(tctx,
8626 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
8627 "failed to delete driver");
8629 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8630 torture_fail(tctx, "deleted driver still enumerated");
8633 torture_assert(tctx,
8634 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
8635 "2nd delete failed");
8640 static bool test_PrinterDriver_args(struct torture_context *tctx,
8641 struct dcerpc_binding_handle *b,
8642 const char *server_name,
8644 struct spoolss_AddDriverInfo8 *r,
8646 uint32_t delete_flags,
8647 uint32_t delete_version,
8649 const char *remote_driver_dir)
8655 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8658 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8661 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8664 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8667 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8670 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8684 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8686 if (!ex && (level == 6 || level == 8)) {
8691 struct dcerpc_pipe *p2;
8692 struct policy_handle hive_handle;
8693 struct dcerpc_binding_handle *b2;
8695 torture_assert_ntstatus_ok(tctx,
8696 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
8697 "could not open winreg pipe");
8698 b2 = p2->binding_handle;
8700 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
8702 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
8704 test_winreg_CloseKey(tctx, b2, &hive_handle);
8710 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
8712 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
8716 static bool fillup_printserver_info(struct torture_context *tctx,
8717 struct dcerpc_pipe *p,
8718 struct torture_driver_context *d)
8720 struct policy_handle server_handle;
8721 struct dcerpc_binding_handle *b = p->binding_handle;
8722 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8724 torture_assert(tctx,
8725 test_OpenPrinter_server(tctx, p, &server_handle),
8726 "failed to open printserver");
8727 torture_assert(tctx,
8728 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
8729 "failed to get environment");
8730 torture_assert(tctx,
8731 test_ClosePrinter(tctx, b, &server_handle),
8732 "failed to close printserver");
8734 torture_assert(tctx,
8735 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
8736 d->local.environment ? d->local.environment : d->remote.environment,
8737 &d->remote.driver_directory),
8738 "failed to get driver directory");
8743 static const char *driver_directory_dir(const char *driver_directory)
8747 p = strrchr(driver_directory, '\\');
8755 static const char *driver_directory_share(struct torture_context *tctx,
8756 const char *driver_directory)
8761 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
8762 driver_directory += 2;
8765 p = talloc_strdup(tctx, driver_directory);
8767 torture_assert(tctx,
8768 next_token_talloc(tctx, &p, &tok, "\\"),
8769 "cannot explode uri");
8770 torture_assert(tctx,
8771 next_token_talloc(tctx, &p, &tok, "\\"),
8772 "cannot explode uri");
8777 static bool upload_printer_driver_file(struct torture_context *tctx,
8778 struct smbcli_state *cli,
8779 struct torture_driver_context *d,
8780 const char *file_name)
8785 int maxwrite = 64512;
8788 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
8789 const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
8790 const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8792 if (!file_name || strlen(file_name) == 0) {
8796 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
8798 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
8800 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
8803 f = x_fopen(local_name, O_RDONLY, 0);
8805 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
8808 buf = talloc_array(tctx, uint8_t, maxwrite);
8813 while (!x_feof(f)) {
8817 if ((n = x_fread(buf, 1, n, f)) < 1) {
8818 if((n == 0) && x_feof(f))
8819 break; /* Empty local file. */
8821 torture_warning(tctx,
8822 "failed to read file: %s\n", strerror(errno));
8826 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
8829 torture_warning(tctx,
8830 "failed to write file: %s\n", smbcli_errstr(cli->tree));
8839 torture_assert_ntstatus_ok(tctx,
8840 smbcli_close(cli->tree, fnum),
8841 "failed to close file");
8846 static bool connect_printer_driver_share(struct torture_context *tctx,
8847 const char *server_name,
8848 const char *share_name,
8849 struct smbcli_state **cli)
8851 struct smbcli_options smb_options;
8852 struct smbcli_session_options smb_session_options;
8854 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
8855 share_name, server_name);
8857 lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
8858 lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
8860 torture_assert_ntstatus_ok(tctx,
8861 smbcli_full_connection(tctx, cli, server_name,
8862 lpcfg_smb_ports(tctx->lp_ctx),
8864 lpcfg_socket_options(tctx->lp_ctx),
8865 cmdline_credentials,
8866 lpcfg_resolve_context(tctx->lp_ctx),
8869 &smb_session_options,
8870 lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
8871 "failed to open driver share");
8876 static bool upload_printer_driver(struct torture_context *tctx,
8877 const char *server_name,
8878 struct torture_driver_context *d)
8880 struct smbcli_state *cli;
8881 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8884 torture_assert(tctx,
8885 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8886 "failed to connect to driver share");
8888 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
8889 server_name, share_name);
8891 torture_assert(tctx,
8892 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8893 "failed to upload driver_path");
8894 torture_assert(tctx,
8895 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
8896 "failed to upload data_file");
8897 torture_assert(tctx,
8898 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
8899 "failed to upload config_file");
8900 torture_assert(tctx,
8901 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
8902 "failed to upload help_file");
8903 if (d->info8.dependent_files) {
8904 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8905 torture_assert(tctx,
8906 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8907 "failed to upload dependent_files");
8916 static bool remove_printer_driver_file(struct torture_context *tctx,
8917 struct smbcli_state *cli,
8918 struct torture_driver_context *d,
8919 const char *file_name)
8921 const char *remote_name;
8922 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
8924 if (!file_name || strlen(file_name) == 0) {
8928 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8930 torture_comment(tctx, "Removing %s\n", remote_name);
8932 torture_assert_ntstatus_ok(tctx,
8933 smbcli_unlink(cli->tree, remote_name),
8934 "failed to unlink");
8939 static bool remove_printer_driver(struct torture_context *tctx,
8940 const char *server_name,
8941 struct torture_driver_context *d)
8943 struct smbcli_state *cli;
8944 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8947 torture_assert(tctx,
8948 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8949 "failed to connect to driver share");
8951 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
8952 server_name, share_name);
8954 torture_assert(tctx,
8955 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8956 "failed to remove driver_path");
8957 torture_assert(tctx,
8958 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
8959 "failed to remove data_file");
8960 if (!strequal(d->info8.config_file, d->info8.driver_path)) {
8961 torture_assert(tctx,
8962 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
8963 "failed to remove config_file");
8965 torture_assert(tctx,
8966 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
8967 "failed to remove help_file");
8968 if (d->info8.dependent_files) {
8969 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8970 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
8971 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
8972 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
8973 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
8976 torture_assert(tctx,
8977 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8978 "failed to remove dependent_files");
8988 static bool test_add_driver_arg(struct torture_context *tctx,
8989 struct dcerpc_pipe *p,
8990 struct torture_driver_context *d)
8993 struct dcerpc_binding_handle *b = p->binding_handle;
8994 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8995 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
8997 struct spoolss_AddDriverInfo8 info8;
8998 uint32_t add_flags = APD_COPY_NEW_FILES;
8999 uint32_t delete_flags = 0;
9003 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
9004 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
9006 torture_assert(tctx,
9007 fillup_printserver_info(tctx, p, d),
9008 "failed to fillup printserver info");
9010 if (!directory_exist(d->local.driver_directory)) {
9011 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9014 torture_assert(tctx,
9015 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9016 "failed to upload printer driver");
9019 if (d->info8.dependent_files) {
9020 info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
9021 if (d->info8.dependent_files->string) {
9022 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9024 info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
9025 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9026 info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
9030 info8.architecture = d->local.environment;
9032 for (i=0; i < ARRAY_SIZE(levels); i++) {
9034 if (torture_setting_bool(tctx, "samba3", false)) {
9035 switch (levels[i]) {
9039 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9045 if (torture_setting_bool(tctx, "w2k3", false)) {
9046 switch (levels[i]) {
9048 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9055 torture_comment(tctx,
9056 "Testing PrinterDriver%s '%s' add & delete level %d\n",
9057 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9059 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex, d->remote.driver_directory);
9062 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
9063 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
9064 if (d->info8.config_file) {
9065 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
9067 if (d->info8.help_file) {
9068 info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
9070 if (d->info8.dependent_files && d->info8.dependent_files->string) {
9071 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9072 info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
9076 for (i=0; i < ARRAY_SIZE(levels); i++) {
9078 if (torture_setting_bool(tctx, "samba3", false)) {
9079 switch (levels[i]) {
9083 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9089 if (torture_setting_bool(tctx, "w2k3", false)) {
9090 switch (levels[i]) {
9092 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9099 torture_comment(tctx,
9100 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
9101 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9103 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex, d->remote.driver_directory);
9106 torture_assert(tctx,
9107 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9108 "failed to remove printer driver");
9110 torture_comment(tctx, "\n");
9115 static bool test_add_driver_ex_64(struct torture_context *tctx,
9116 struct dcerpc_pipe *p)
9118 struct torture_driver_context *d;
9120 d = talloc_zero(tctx, struct torture_driver_context);
9122 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9123 d->info8.driver_name = TORTURE_DRIVER_EX;
9124 d->info8.architecture = NULL;
9125 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9126 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9127 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9128 d->local.environment = talloc_strdup(d, "Windows x64");
9129 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9132 return test_add_driver_arg(tctx, p, d);
9135 static bool test_add_driver_ex_32(struct torture_context *tctx,
9136 struct dcerpc_pipe *p)
9138 struct torture_driver_context *d;
9140 d = talloc_zero(tctx, struct torture_driver_context);
9142 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9143 d->info8.driver_name = TORTURE_DRIVER_EX;
9144 d->info8.architecture = NULL;
9145 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9146 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9147 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9148 d->local.environment = talloc_strdup(d, "Windows NT x86");
9149 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9152 return test_add_driver_arg(tctx, p, d);
9155 static bool test_add_driver_64(struct torture_context *tctx,
9156 struct dcerpc_pipe *p)
9158 struct torture_driver_context *d;
9160 d = talloc_zero(tctx, struct torture_driver_context);
9162 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9163 d->info8.driver_name = TORTURE_DRIVER;
9164 d->info8.architecture = NULL;
9165 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9166 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9167 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9168 d->local.environment = talloc_strdup(d, "Windows x64");
9169 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9172 return test_add_driver_arg(tctx, p, d);
9175 static bool test_add_driver_32(struct torture_context *tctx,
9176 struct dcerpc_pipe *p)
9178 struct torture_driver_context *d;
9180 d = talloc_zero(tctx, struct torture_driver_context);
9182 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9183 d->info8.driver_name = TORTURE_DRIVER;
9184 d->info8.architecture = NULL;
9185 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9186 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9187 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9188 d->local.environment = talloc_strdup(d, "Windows NT x86");
9189 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9192 return test_add_driver_arg(tctx, p, d);
9195 static bool test_add_driver_adobe(struct torture_context *tctx,
9196 struct dcerpc_pipe *p)
9198 struct torture_driver_context *d;
9200 d = talloc_zero(tctx, struct torture_driver_context);
9202 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9203 d->info8.driver_name = TORTURE_DRIVER_ADOBE;
9204 d->info8.architecture = NULL;
9205 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9206 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9207 d->info8.config_file = talloc_strdup(d, "ADOBEPS4.DRV");
9209 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9210 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9212 d->local.environment = talloc_strdup(d, "Windows 4.0");
9213 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9216 return test_add_driver_arg(tctx, p, d);
9219 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
9220 struct dcerpc_pipe *p)
9222 struct torture_driver_context *d;
9223 struct spoolss_StringArray *a;
9225 if (!torture_setting_bool(tctx, "samba3", false)) {
9226 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
9229 d = talloc_zero(tctx, struct torture_driver_context);
9231 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9232 d->info8.driver_name = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
9233 d->info8.architecture = NULL;
9234 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9235 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9236 d->info8.config_file = NULL;
9237 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9238 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9239 d->info8.default_datatype = talloc_strdup(d, "RAW");
9241 a = talloc_zero(d, struct spoolss_StringArray);
9242 a->string = talloc_zero_array(a, const char *, 7);
9243 a->string[0] = talloc_strdup(a->string, "ADOBEPS4.DRV");
9244 a->string[1] = talloc_strdup(a->string, "DEFPRTR2.PPD");
9245 a->string[2] = talloc_strdup(a->string, "ADOBEPS4.HLP");
9246 a->string[3] = talloc_strdup(a->string, "PSMON.DLL");
9247 a->string[4] = talloc_strdup(a->string, "ADFONTS.MFM");
9248 a->string[5] = talloc_strdup(a->string, "ICONLIB.DLL");
9250 d->info8.dependent_files = a;
9251 d->local.environment = talloc_strdup(d, "Windows 4.0");
9252 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9255 return test_add_driver_arg(tctx, p, d);
9258 static bool test_add_driver_timestamps(struct torture_context *tctx,
9259 struct dcerpc_pipe *p)
9261 struct torture_driver_context *d;
9262 struct timeval t = timeval_current();
9264 if (torture_setting_bool(tctx, "samba3", false)) {
9265 torture_skip(tctx, "skipping timestamps test against samba");
9268 d = talloc_zero(tctx, struct torture_driver_context);
9270 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9271 d->info8.driver_name = TORTURE_DRIVER_TIMESTAMPS;
9272 d->info8.architecture = NULL;
9273 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9274 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9275 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9276 d->info8.driver_date = timeval_to_nttime(&t);
9277 d->local.environment = talloc_strdup(d, "Windows NT x86");
9278 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9281 torture_assert(tctx,
9282 test_add_driver_arg(tctx, p, d),
9285 unix_to_nt_time(&d->info8.driver_date, 1);
9287 torture_assert(tctx,
9288 test_add_driver_arg(tctx, p, d),
9294 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
9296 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
9298 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
9299 "driver", &ndr_table_spoolss);
9300 torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
9301 torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
9303 torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
9304 torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
9306 torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
9308 torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
9310 torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);