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,2013
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 "libcli/smb2/smb2.h"
39 #include "libcli/smb2/smb2_calls.h"
40 #include "lib/cmdline/popt_common.h"
41 #include "system/filesys.h"
42 #include "torture/ndr/ndr.h"
43 #include "torture/smb2/proto.h"
45 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
46 #define TORTURE_PRINTER "torture_printer"
47 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
48 #define TORTURE_PRINTER_EX "torture_printer_ex"
49 #define TORTURE_DRIVER "torture_driver"
50 #define TORTURE_DRIVER_ADD "torture_driver_add"
51 #define TORTURE_DRIVER_EX "torture_driver_ex"
52 #define TORTURE_DRIVER_ADOBE "torture_driver_adobe"
53 #define TORTURE_DRIVER_EX_ADOBE "torture_driver_ex_adobe"
54 #define TORTURE_DRIVER_ADOBE_CUPSADDSMB "torture_driver_adobe_cupsaddsmb"
55 #define TORTURE_DRIVER_TIMESTAMPS "torture_driver_timestamps"
56 #define TORTURE_DRIVER_DELETER "torture_driver_deleter"
57 #define TORTURE_DRIVER_COPY_DIR "torture_driver_copy_from_directory"
58 #define TORTURE_DRIVER_DELETERIN "torture_driver_deleterin"
59 #define TORTURE_PRINTER_STATIC1 "print1"
61 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
62 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
63 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
64 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
65 #define TOP_LEVEL_CONTROL_PRINTERS_KEY TOP_LEVEL_CONTROL_KEY "\\Printers"
66 #define TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY TOP_LEVEL_CONTROL_KEY "\\Environments"
68 struct test_spoolss_context
{
69 struct dcerpc_pipe
*spoolss_pipe
;
71 /* server environment */
72 const char *environment
;
74 /* print server handle */
75 struct policy_handle server_handle
;
78 uint32_t port_count
[3];
79 union spoolss_PortInfo
*ports
[3];
81 /* for EnumPrinterDrivers */
82 uint32_t driver_count
[9];
83 union spoolss_DriverInfo
*drivers
[9];
85 /* for EnumMonitors */
86 uint32_t monitor_count
[3];
87 union spoolss_MonitorInfo
*monitors
[3];
89 /* for EnumPrintProcessors */
90 uint32_t print_processor_count
[2];
91 union spoolss_PrintProcessorInfo
*print_processors
[2];
93 /* for EnumPrinters */
94 uint32_t printer_count
[6];
95 union spoolss_PrinterInfo
*printers
[6];
98 struct torture_driver_context
{
100 const char *driver_directory
;
101 const char *environment
;
104 const char *driver_directory
;
105 const char *driver_upload_directory
;
106 const char *environment
;
108 struct spoolss_AddDriverInfo8 info8
;
112 struct torture_printer_context
{
113 struct dcerpc_pipe
*spoolss_pipe
;
114 struct spoolss_SetPrinterInfo2 info2
;
115 struct torture_driver_context driver
;
120 struct spoolss_DeviceMode
*devmode
;
121 struct policy_handle handle
;
124 static bool upload_printer_driver(struct torture_context
*tctx
,
125 const char *server_name
,
126 struct torture_driver_context
*d
);
127 static bool remove_printer_driver(struct torture_context
*tctx
,
128 const char *server_name
,
129 struct torture_driver_context
*d
);
130 static bool fillup_printserver_info(struct torture_context
*tctx
,
131 struct dcerpc_pipe
*p
,
132 struct torture_driver_context
*d
);
133 static bool test_AddPrinterDriver_args_level_3(struct torture_context
*tctx
,
134 struct dcerpc_binding_handle
*b
,
135 const char *server_name
,
136 struct spoolss_AddDriverInfo8
*r
,
139 const char *remote_driver_dir
);
141 #define COMPARE_STRING(tctx, c,r,e) \
142 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
144 /* not every compiler supports __typeof__() */
146 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
147 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
148 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
150 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
151 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
155 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
158 #define COMPARE_UINT32(tctx, c, r, e) do {\
159 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
160 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
163 #define COMPARE_UINT64(tctx, c, r, e) do {\
164 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
165 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
169 #define COMPARE_NTTIME(tctx, c, r, e) do {\
170 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
171 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
174 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
176 if (!c.e && !r.e) { \
180 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
183 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
185 for (__i=0;c.e[__i] != NULL; __i++) { \
186 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
190 #define CHECK_ALIGN(size, n) do {\
192 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
193 size, n, size + n - (size % n));\
197 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
199 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, needed, align) do { \
200 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
201 uint32_t size = ndr_size_##fn##_info(tctx, level, count, info);\
202 uint32_t round_size = DO_ROUND(size, align);\
203 if (round_size != needed) {\
204 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
205 CHECK_ALIGN(size, align);\
210 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, needed, align) do { \
211 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
212 uint32_t size = ndr_size_##fn##_info(tctx, count, info);\
213 uint32_t round_size = DO_ROUND(size, align);\
214 if (round_size != needed) {\
215 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
216 CHECK_ALIGN(size, align);\
221 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, needed, align) do { \
222 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
223 uint32_t size = ndr_size_##fn(info, level, 0);\
224 uint32_t round_size = DO_ROUND(size, align);\
225 if (round_size != needed) {\
226 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
227 CHECK_ALIGN(size, align);\
232 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context
*tctx
,
233 const union spoolss_PrinterInfo
*i
,
235 union spoolss_SetPrinterInfo
*s
)
239 s
->info0
= talloc(tctx
, struct spoolss_SetPrinterInfo0
);
242 s
->info2
= talloc(tctx
, struct spoolss_SetPrinterInfo2
);
243 s
->info2
->servername
= i
->info2
.servername
;
244 s
->info2
->printername
= i
->info2
.printername
;
245 s
->info2
->sharename
= i
->info2
.sharename
;
246 s
->info2
->portname
= i
->info2
.portname
;
247 s
->info2
->drivername
= i
->info2
.drivername
;
248 s
->info2
->comment
= i
->info2
.comment
;
249 s
->info2
->location
= i
->info2
.location
;
250 s
->info2
->devmode_ptr
= 0;
251 s
->info2
->sepfile
= i
->info2
.sepfile
;
252 s
->info2
->printprocessor
= i
->info2
.printprocessor
;
253 s
->info2
->datatype
= i
->info2
.datatype
;
254 s
->info2
->parameters
= i
->info2
.parameters
;
255 s
->info2
->secdesc_ptr
= 0;
256 s
->info2
->attributes
= i
->info2
.attributes
;
257 s
->info2
->priority
= i
->info2
.priority
;
258 s
->info2
->defaultpriority
= i
->info2
.defaultpriority
;
259 s
->info2
->starttime
= i
->info2
.starttime
;
260 s
->info2
->untiltime
= i
->info2
.untiltime
;
261 s
->info2
->status
= i
->info2
.status
;
262 s
->info2
->cjobs
= i
->info2
.cjobs
;
263 s
->info2
->averageppm
= i
->info2
.averageppm
;
279 static bool test_OpenPrinter_server(struct torture_context
*tctx
,
280 struct dcerpc_pipe
*p
,
281 struct policy_handle
*server_handle
)
284 struct spoolss_OpenPrinter op
;
285 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
287 op
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
288 op
.in
.datatype
= NULL
;
289 op
.in
.devmode_ctr
.devmode
= NULL
;
290 op
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
291 op
.out
.handle
= server_handle
;
293 torture_comment(tctx
, "Testing OpenPrinter(%s)\n", op
.in
.printername
);
295 status
= dcerpc_spoolss_OpenPrinter_r(b
, tctx
, &op
);
296 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_OpenPrinter failed");
297 torture_assert_werr_ok(tctx
, op
.out
.result
, "dcerpc_spoolss_OpenPrinter failed");
302 static bool test_EnumPorts(struct torture_context
*tctx
,
305 struct test_spoolss_context
*ctx
=
306 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
307 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
308 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
310 struct spoolss_EnumPorts r
;
311 uint16_t levels
[] = { 1, 2 };
314 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
315 int level
= levels
[i
];
319 union spoolss_PortInfo
*info
;
321 r
.in
.servername
= "";
325 r
.out
.needed
= &needed
;
326 r
.out
.count
= &count
;
329 torture_comment(tctx
, "Testing EnumPorts level %u\n", r
.in
.level
);
331 status
= dcerpc_spoolss_EnumPorts_r(b
, ctx
, &r
);
332 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPorts failed");
333 if (W_ERROR_IS_OK(r
.out
.result
)) {
334 /* TODO: do some more checks here */
337 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
338 "EnumPorts unexpected return code");
340 blob
= data_blob_talloc_zero(ctx
, needed
);
342 r
.in
.offered
= needed
;
344 status
= dcerpc_spoolss_EnumPorts_r(b
, ctx
, &r
);
345 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPorts failed");
347 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
349 torture_assert(tctx
, info
, "EnumPorts returned no info");
351 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts
, info
, r
.in
.level
, count
, needed
, 4);
353 ctx
->port_count
[level
] = count
;
354 ctx
->ports
[level
] = info
;
357 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
358 int level
= levels
[i
];
359 int old_level
= levels
[i
-1];
360 torture_assert_int_equal(tctx
, ctx
->port_count
[level
], ctx
->port_count
[old_level
],
361 "EnumPorts invalid value");
363 /* if the array sizes are not the same we would maybe segfault in the following code */
365 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
366 int level
= levels
[i
];
367 for (j
=0;j
<ctx
->port_count
[level
];j
++) {
368 union spoolss_PortInfo
*cur
= &ctx
->ports
[level
][j
];
369 union spoolss_PortInfo
*ref
= &ctx
->ports
[2][j
];
372 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, port_name
);
375 /* level 2 is our reference, and it makes no sense to compare it to itself */
384 static bool test_GetPrintProcessorDirectory(struct torture_context
*tctx
,
387 struct test_spoolss_context
*ctx
=
388 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
391 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
392 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
393 struct spoolss_GetPrintProcessorDirectory r
;
408 .server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
))
411 .server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
))
417 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
418 int level
= levels
[i
].level
;
421 r
.in
.server
= levels
[i
].server
;
422 r
.in
.environment
= ctx
->environment
;
426 r
.out
.needed
= &needed
;
428 torture_comment(tctx
, "Testing GetPrintProcessorDirectory level %u\n", r
.in
.level
);
430 status
= dcerpc_spoolss_GetPrintProcessorDirectory_r(b
, tctx
, &r
);
431 torture_assert_ntstatus_ok(tctx
, status
,
432 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
433 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
434 "GetPrintProcessorDirectory unexpected return code");
436 blob
= data_blob_talloc_zero(tctx
, needed
);
438 r
.in
.offered
= needed
;
440 status
= dcerpc_spoolss_GetPrintProcessorDirectory_r(b
, tctx
, &r
);
441 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
443 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrintProcessorDirectory failed");
445 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo
, r
.out
.info
, r
.in
.level
, needed
, 2);
452 static bool test_GetPrinterDriverDirectory(struct torture_context
*tctx
,
455 struct test_spoolss_context
*ctx
=
456 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
459 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
460 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
461 struct spoolss_GetPrinterDriverDirectory r
;
476 .server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
))
479 .server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
))
485 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
486 int level
= levels
[i
].level
;
489 r
.in
.server
= levels
[i
].server
;
490 r
.in
.environment
= ctx
->environment
;
494 r
.out
.needed
= &needed
;
496 torture_comment(tctx
, "Testing GetPrinterDriverDirectory level %u\n", r
.in
.level
);
498 status
= dcerpc_spoolss_GetPrinterDriverDirectory_r(b
, tctx
, &r
);
499 torture_assert_ntstatus_ok(tctx
, status
,
500 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
501 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
502 "GetPrinterDriverDirectory unexpected return code");
504 blob
= data_blob_talloc_zero(tctx
, needed
);
506 r
.in
.offered
= needed
;
508 status
= dcerpc_spoolss_GetPrinterDriverDirectory_r(b
, tctx
, &r
);
509 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
511 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrinterDriverDirectory failed");
513 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo
, r
.out
.info
, r
.in
.level
, needed
, 2);
519 static bool test_EnumPrinterDrivers_buffers(struct torture_context
*tctx
,
520 struct dcerpc_binding_handle
*b
,
521 const char *server_name
,
522 const char *environment
,
526 union spoolss_DriverInfo
**info_p
)
528 struct spoolss_EnumPrinterDrivers r
;
531 union spoolss_DriverInfo
*info
;
535 buffer
= data_blob_talloc_zero(tctx
, offered
);
538 r
.in
.server
= server_name
;
539 r
.in
.environment
= environment
;
541 r
.in
.buffer
= offered
? &buffer
: NULL
;
542 r
.in
.offered
= offered
;
543 r
.out
.needed
= &needed
;
544 r
.out
.count
= &count
;
547 torture_comment(tctx
, "Testing EnumPrinterDrivers(%s) level %u, offered: %u\n",
548 r
.in
.environment
, r
.in
.level
, r
.in
.offered
);
550 torture_assert_ntstatus_ok(tctx
,
551 dcerpc_spoolss_EnumPrinterDrivers_r(b
, tctx
, &r
),
552 "EnumPrinterDrivers failed");
553 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
554 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
556 r
.in
.offered
= needed
;
558 torture_assert_ntstatus_ok(tctx
,
559 dcerpc_spoolss_EnumPrinterDrivers_r(b
, tctx
, &r
),
560 "EnumPrinterDrivers failed");
563 torture_assert_werr_ok(tctx
, r
.out
.result
,
564 "EnumPrinterDrivers failed");
573 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers
, info
, r
.in
.level
, count
, needed
, 4);
580 static bool test_EnumPrinterDrivers_args(struct torture_context
*tctx
,
581 struct dcerpc_binding_handle
*b
,
582 const char *server_name
,
583 const char *environment
,
586 union spoolss_DriverInfo
**info_p
)
588 return test_EnumPrinterDrivers_buffers(tctx
, b
, server_name
,
589 environment
, level
, 0,
593 static bool test_EnumPrinterDrivers_findone(struct torture_context
*tctx
,
594 struct dcerpc_binding_handle
*b
,
595 const char *server_name
,
596 const char *environment
,
598 const char *driver_name
,
599 union spoolss_DriverInfo
*info_p
)
602 union spoolss_DriverInfo
*info
;
604 const char *environment_ret
= NULL
;
607 test_EnumPrinterDrivers_args(tctx
, b
, server_name
, environment
, level
, &count
, &info
),
608 "failed to enumerate printer drivers");
610 for (i
=0; i
< count
; i
++) {
611 const char *driver_name_ret
= "";
614 driver_name_ret
= info
[i
].info1
.driver_name
;
617 driver_name_ret
= info
[i
].info2
.driver_name
;
618 environment_ret
= info
[i
].info2
.architecture
;
621 driver_name_ret
= info
[i
].info3
.driver_name
;
622 environment_ret
= info
[i
].info3
.architecture
;
625 driver_name_ret
= info
[i
].info4
.driver_name
;
626 environment_ret
= info
[i
].info4
.architecture
;
629 driver_name_ret
= info
[i
].info5
.driver_name
;
630 environment_ret
= info
[i
].info5
.architecture
;
633 driver_name_ret
= info
[i
].info6
.driver_name
;
634 environment_ret
= info
[i
].info6
.architecture
;
637 driver_name_ret
= info
[i
].info7
.driver_name
;
640 driver_name_ret
= info
[i
].info8
.driver_name
;
641 environment_ret
= info
[i
].info8
.architecture
;
646 if (environment_ret
) {
647 torture_assert_str_equal(tctx
, environment
, environment_ret
, "architecture mismatch");
649 if (strequal(driver_name
, driver_name_ret
)) {
660 static bool test_EnumPrinterDrivers(struct torture_context
*tctx
,
663 struct test_spoolss_context
*ctx
=
664 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
665 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
666 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
667 uint16_t levels
[] = { 1, 2, 3, 4, 5, 6, 8 };
668 uint16_t buffer_sizes
[] = { 0, 1024, 6040, 0xffff };
671 /* FIXME: gd, come back and fix "" as server, and handle
672 * priority of returned error codes in torture test and samba 3
674 const char *server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
675 const char *environments
[2];
677 environments
[0] = SPOOLSS_ARCHITECTURE_ALL
;
678 environments
[1] = ctx
->environment
;
680 for (a
=0;a
<ARRAY_SIZE(environments
);a
++) {
682 for (i
=0;i
<ARRAY_SIZE(buffer_sizes
);i
++) {
684 test_EnumPrinterDrivers_buffers(tctx
, b
, server_name
,
688 "failed to enumerate drivers");
691 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
692 int level
= levels
[i
];
694 union spoolss_DriverInfo
*info
;
697 test_EnumPrinterDrivers_args(tctx
, b
, server_name
, environments
[a
], level
, &count
, &info
),
698 "failed to enumerate drivers");
700 ctx
->driver_count
[level
] = count
;
701 ctx
->drivers
[level
] = info
;
704 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
705 int level
= levels
[i
];
706 int old_level
= levels
[i
-1];
708 torture_assert_int_equal(tctx
, ctx
->driver_count
[level
], ctx
->driver_count
[old_level
],
709 "EnumPrinterDrivers invalid value");
712 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
713 int level
= levels
[i
];
715 for (j
=0;j
<ctx
->driver_count
[level
- 1];j
++) {
716 union spoolss_DriverInfo
*cur
= &ctx
->drivers
[level
- 1][j
];
717 union spoolss_DriverInfo
*ref
= &ctx
->drivers
[8][j
];
721 COMPARE_STRING(tctx
, cur
->info1
, ref
->info8
, driver_name
);
724 COMPARE_UINT32(tctx
, cur
->info2
, ref
->info8
, version
);
725 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, driver_name
);
726 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, architecture
);
727 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, driver_path
);
728 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, data_file
);
729 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, config_file
);
732 COMPARE_UINT32(tctx
, cur
->info3
, ref
->info8
, version
);
733 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, driver_name
);
734 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, architecture
);
735 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, driver_path
);
736 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, data_file
);
737 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, config_file
);
738 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, help_file
);
739 COMPARE_STRING_ARRAY(tctx
, cur
->info3
, ref
->info8
, dependent_files
);
740 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, monitor_name
);
741 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, default_datatype
);
744 COMPARE_UINT32(tctx
, cur
->info4
, ref
->info8
, version
);
745 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, driver_name
);
746 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, architecture
);
747 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, driver_path
);
748 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, data_file
);
749 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, config_file
);
750 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, help_file
);
751 COMPARE_STRING_ARRAY(tctx
, cur
->info4
, ref
->info8
, dependent_files
);
752 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, monitor_name
);
753 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, default_datatype
);
754 COMPARE_STRING_ARRAY(tctx
, cur
->info4
, ref
->info8
, previous_names
);
757 COMPARE_UINT32(tctx
, cur
->info5
, ref
->info8
, version
);
758 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, driver_name
);
759 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, architecture
);
760 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, driver_path
);
761 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, data_file
);
762 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, config_file
);
763 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
764 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
765 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
768 COMPARE_UINT32(tctx
, cur
->info6
, ref
->info8
, version
);
769 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, driver_name
);
770 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, architecture
);
771 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, driver_path
);
772 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, data_file
);
773 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, config_file
);
774 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, help_file
);
775 COMPARE_STRING_ARRAY(tctx
, cur
->info6
, ref
->info8
, dependent_files
);
776 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, monitor_name
);
777 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, default_datatype
);
778 COMPARE_STRING_ARRAY(tctx
, cur
->info6
, ref
->info8
, previous_names
);
779 COMPARE_NTTIME(tctx
, cur
->info6
, ref
->info8
, driver_date
);
780 COMPARE_UINT64(tctx
, cur
->info6
, ref
->info8
, driver_version
);
781 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, manufacturer_name
);
782 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, manufacturer_url
);
783 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, hardware_id
);
784 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, provider
);
787 /* level 8 is our reference, and it makes no sense to compare it to itself */
797 static bool test_EnumMonitors(struct torture_context
*tctx
,
800 struct test_spoolss_context
*ctx
=
801 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
802 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
803 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
805 struct spoolss_EnumMonitors r
;
806 uint16_t levels
[] = { 1, 2 };
809 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
810 int level
= levels
[i
];
814 union spoolss_MonitorInfo
*info
;
816 r
.in
.servername
= "";
820 r
.out
.needed
= &needed
;
821 r
.out
.count
= &count
;
824 torture_comment(tctx
, "Testing EnumMonitors level %u\n", r
.in
.level
);
826 status
= dcerpc_spoolss_EnumMonitors_r(b
, ctx
, &r
);
827 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumMonitors failed");
828 if (W_ERROR_IS_OK(r
.out
.result
)) {
829 /* TODO: do some more checks here */
832 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
833 "EnumMonitors failed");
835 blob
= data_blob_talloc_zero(ctx
, needed
);
837 r
.in
.offered
= needed
;
839 status
= dcerpc_spoolss_EnumMonitors_r(b
, ctx
, &r
);
840 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumMonitors failed");
842 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumMonitors failed");
844 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors
, info
, r
.in
.level
, count
, needed
, 4);
846 ctx
->monitor_count
[level
] = count
;
847 ctx
->monitors
[level
] = info
;
850 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
851 int level
= levels
[i
];
852 int old_level
= levels
[i
-1];
853 torture_assert_int_equal(tctx
, ctx
->monitor_count
[level
], ctx
->monitor_count
[old_level
],
854 "EnumMonitors invalid value");
857 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
858 int level
= levels
[i
];
859 for (j
=0;j
<ctx
->monitor_count
[level
];j
++) {
860 union spoolss_MonitorInfo
*cur
= &ctx
->monitors
[level
][j
];
861 union spoolss_MonitorInfo
*ref
= &ctx
->monitors
[2][j
];
864 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, monitor_name
);
867 torture_assert_str_equal(tctx
, ref
->info2
.environment
, ctx
->environment
, "invalid environment");
868 /* level 2 is our reference, and it makes no sense to compare it to itself */
877 static bool test_EnumPrintProcessors_level(struct torture_context
*tctx
,
878 struct dcerpc_binding_handle
*b
,
879 const char *environment
,
882 union spoolss_PrintProcessorInfo
**info_p
,
883 WERROR expected_result
)
885 struct spoolss_EnumPrintProcessors r
;
889 union spoolss_PrintProcessorInfo
*info
;
891 r
.in
.servername
= "";
892 r
.in
.environment
= environment
;
896 r
.out
.needed
= &needed
;
897 r
.out
.count
= &count
;
900 torture_comment(tctx
, "Testing EnumPrintProcessors(%s) level %u\n",
901 r
.in
.environment
, r
.in
.level
);
903 torture_assert_ntstatus_ok(tctx
,
904 dcerpc_spoolss_EnumPrintProcessors_r(b
, tctx
, &r
),
905 "EnumPrintProcessors failed");
906 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
907 blob
= data_blob_talloc_zero(tctx
, needed
);
909 r
.in
.offered
= needed
;
910 torture_assert_ntstatus_ok(tctx
,
911 dcerpc_spoolss_EnumPrintProcessors_r(b
, tctx
, &r
),
912 "EnumPrintProcessors failed");
914 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
915 "EnumPrintProcessors failed");
917 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors
, info
, level
, count
, needed
, 4);
929 static bool test_EnumPrintProcessors(struct torture_context
*tctx
,
932 struct test_spoolss_context
*ctx
=
933 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
935 uint16_t levels
[] = {0, 1, 2, 3, 32, 256 };
936 uint16_t ok
[] = {0, 1, 0, 0, 0, 0 };
938 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
939 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
942 test_EnumPrintProcessors_level(tctx
, b
, "phantasy", 1, NULL
, NULL
, WERR_INVALID_ENVIRONMENT
),
943 "test_EnumPrintProcessors_level failed");
945 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
946 union spoolss_PrintProcessorInfo
*info
;
948 WERROR expected_result
= ok
[i
] ? WERR_OK
: WERR_INVALID_LEVEL
;
951 test_EnumPrintProcessors_level(tctx
, b
, ctx
->environment
, levels
[i
], &count
, &info
, expected_result
),
952 "test_EnumPrintProcessors_level failed");
958 static bool test_EnumPrintProcessorDataTypes_level(struct torture_context
*tctx
,
959 struct dcerpc_binding_handle
*b
,
960 const char *print_processor_name
,
963 union spoolss_PrintProcDataTypesInfo
**info_p
,
964 WERROR expected_result
)
966 struct spoolss_EnumPrintProcessorDataTypes r
;
970 union spoolss_PrintProcDataTypesInfo
*info
;
972 r
.in
.servername
= "";
973 r
.in
.print_processor_name
= print_processor_name
;
977 r
.out
.needed
= &needed
;
978 r
.out
.count
= &count
;
981 torture_comment(tctx
, "Testing EnumPrintProcessorDataTypes(%s) level %u\n",
982 r
.in
.print_processor_name
, r
.in
.level
);
984 torture_assert_ntstatus_ok(tctx
,
985 dcerpc_spoolss_EnumPrintProcessorDataTypes_r(b
, tctx
, &r
),
986 "EnumPrintProcessorDataTypes failed");
987 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
988 blob
= data_blob_talloc_zero(tctx
, needed
);
990 r
.in
.offered
= needed
;
991 torture_assert_ntstatus_ok(tctx
,
992 dcerpc_spoolss_EnumPrintProcessorDataTypes_r(b
, tctx
, &r
),
993 "EnumPrintProcessorDataTypes failed");
995 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
996 "EnumPrintProcessorDataTypes failed");
998 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessorDataTypes
, info
, level
, count
, needed
, 4);
1010 static bool test_EnumPrintProcessorDataTypes(struct torture_context
*tctx
,
1013 struct test_spoolss_context
*ctx
=
1014 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
1016 uint16_t levels
[] = {0, 1, 2, 3, 32, 256 };
1017 uint16_t ok
[] = {0, 1, 0, 0, 0, 0 };
1019 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
1020 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
1022 torture_assert(tctx
,
1023 test_EnumPrintProcessorDataTypes_level(tctx
, b
, NULL
, 1, NULL
, NULL
, WERR_UNKNOWN_PRINTPROCESSOR
),
1024 "test_EnumPrintProcessorDataTypes_level failed");
1026 torture_assert(tctx
,
1027 test_EnumPrintProcessorDataTypes_level(tctx
, b
, "nonexisting", 1, NULL
, NULL
, WERR_UNKNOWN_PRINTPROCESSOR
),
1028 "test_EnumPrintProcessorDataTypes_level failed");
1030 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
1031 int level
= levels
[i
];
1033 union spoolss_PrintProcDataTypesInfo
*info
;
1034 WERROR expected_result
= ok
[i
] ? WERR_OK
: WERR_INVALID_LEVEL
;
1036 torture_assert(tctx
,
1037 test_EnumPrintProcessorDataTypes_level(tctx
, b
, "winprint", level
, &count
, &info
, expected_result
),
1038 "test_EnumPrintProcessorDataTypes_level failed");
1042 union spoolss_PrintProcessorInfo
*info
;
1045 torture_assert(tctx
,
1046 test_EnumPrintProcessors_level(tctx
, b
, ctx
->environment
, 1, &count
, &info
, WERR_OK
),
1047 "test_EnumPrintProcessors_level failed");
1049 for (i
=0; i
< count
; i
++) {
1050 torture_assert(tctx
,
1051 test_EnumPrintProcessorDataTypes_level(tctx
, b
, info
[i
].info1
.print_processor_name
, 1, NULL
, NULL
, WERR_OK
),
1052 "test_EnumPrintProcessorDataTypes_level failed");
1060 static bool test_EnumPrinters(struct torture_context
*tctx
,
1063 struct test_spoolss_context
*ctx
=
1064 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
1065 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
1066 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
1067 struct spoolss_EnumPrinters r
;
1069 uint16_t levels
[] = { 0, 1, 2, 4, 5 };
1072 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
1073 int level
= levels
[i
];
1077 union spoolss_PrinterInfo
*info
;
1079 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
1084 r
.out
.needed
= &needed
;
1085 r
.out
.count
= &count
;
1088 torture_comment(tctx
, "Testing EnumPrinters level %u\n", r
.in
.level
);
1090 status
= dcerpc_spoolss_EnumPrinters_r(b
, ctx
, &r
);
1091 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinters failed");
1092 if (W_ERROR_IS_OK(r
.out
.result
)) {
1093 /* TODO: do some more checks here */
1096 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
1097 "EnumPrinters unexpected return code");
1099 blob
= data_blob_talloc_zero(ctx
, needed
);
1100 r
.in
.buffer
= &blob
;
1101 r
.in
.offered
= needed
;
1103 status
= dcerpc_spoolss_EnumPrinters_r(b
, ctx
, &r
);
1104 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinters failed");
1106 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
1108 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters
, info
, r
.in
.level
, count
, needed
, 4);
1110 ctx
->printer_count
[level
] = count
;
1111 ctx
->printers
[level
] = info
;
1114 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
1115 int level
= levels
[i
];
1116 int old_level
= levels
[i
-1];
1117 torture_assert_int_equal(tctx
, ctx
->printer_count
[level
], ctx
->printer_count
[old_level
],
1118 "EnumPrinters invalid value");
1121 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
1122 int level
= levels
[i
];
1123 for (j
=0;j
<ctx
->printer_count
[level
];j
++) {
1124 union spoolss_PrinterInfo
*cur
= &ctx
->printers
[level
][j
];
1125 union spoolss_PrinterInfo
*ref
= &ctx
->printers
[2][j
];
1128 COMPARE_STRING(tctx
, cur
->info0
, ref
->info2
, printername
);
1129 COMPARE_STRING(tctx
, cur
->info0
, ref
->info2
, servername
);
1130 COMPARE_UINT32(tctx
, cur
->info0
, ref
->info2
, cjobs
);
1131 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
1132 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
1133 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
1134 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
1135 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
1136 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
1137 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
1138 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
1139 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
1140 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
1141 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
1142 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
1143 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
1144 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
1145 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
1146 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
1147 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
1148 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
1149 COMPARE_UINT32(tctx
, cur
->info0
, ref
->info2
, status
);
1150 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
1151 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
1152 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
1153 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
1154 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
1155 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
1156 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
1159 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
1160 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
1161 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
1162 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, comment
);
1165 /* level 2 is our reference, and it makes no sense to compare it to itself */
1168 COMPARE_STRING(tctx
, cur
->info4
, ref
->info2
, printername
);
1169 COMPARE_STRING(tctx
, cur
->info4
, ref
->info2
, servername
);
1170 COMPARE_UINT32(tctx
, cur
->info4
, ref
->info2
, attributes
);
1173 COMPARE_STRING(tctx
, cur
->info5
, ref
->info2
, printername
);
1174 COMPARE_STRING(tctx
, cur
->info5
, ref
->info2
, portname
);
1175 COMPARE_UINT32(tctx
, cur
->info5
, ref
->info2
, attributes
);
1176 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
1177 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
1184 * - verify that the port of a printer was in the list returned by EnumPorts
1190 static bool test_GetPrinterDriver2(struct torture_context
*tctx
,
1191 struct dcerpc_binding_handle
*b
,
1192 struct policy_handle
*handle
,
1193 const char *driver_name
,
1194 const char *environment
);
1196 bool test_GetPrinter_level_exp(struct torture_context
*tctx
,
1197 struct dcerpc_binding_handle
*b
,
1198 struct policy_handle
*handle
,
1200 WERROR expected_werror
,
1201 union spoolss_PrinterInfo
*info
)
1203 struct spoolss_GetPrinter r
;
1206 r
.in
.handle
= handle
;
1210 r
.out
.needed
= &needed
;
1212 torture_comment(tctx
, "Testing GetPrinter level %u\n", r
.in
.level
);
1214 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinter_r(b
, tctx
, &r
),
1215 "GetPrinter failed");
1217 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1218 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
1219 r
.in
.buffer
= &blob
;
1220 r
.in
.offered
= needed
;
1222 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinter_r(b
, tctx
, &r
),
1223 "GetPrinter failed");
1226 torture_assert_werr_equal(tctx
,
1227 r
.out
.result
, expected_werror
,
1228 "GetPrinter failed");
1230 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo
, r
.out
.info
, r
.in
.level
, needed
, 4);
1232 if (info
&& r
.out
.info
) {
1233 *info
= *r
.out
.info
;
1239 bool test_GetPrinter_level(struct torture_context
*tctx
,
1240 struct dcerpc_binding_handle
*b
,
1241 struct policy_handle
*handle
,
1243 union spoolss_PrinterInfo
*info
)
1245 return test_GetPrinter_level_exp(tctx
, b
, handle
, level
, WERR_OK
, info
);
1248 static bool test_GetPrinter(struct torture_context
*tctx
,
1249 struct dcerpc_binding_handle
*b
,
1250 struct policy_handle
*handle
,
1251 const char *environment
)
1253 uint32_t levels
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1256 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
1258 union spoolss_PrinterInfo info
;
1262 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, levels
[i
], &info
),
1263 "failed to call GetPrinter");
1265 if ((levels
[i
] == 2) && info
.info2
.drivername
&& strlen(info
.info2
.drivername
)) {
1266 torture_assert(tctx
,
1267 test_GetPrinterDriver2(tctx
, b
, handle
, info
.info2
.drivername
, environment
),
1268 "failed to call test_GetPrinterDriver2");
1275 static bool test_SetPrinter(struct torture_context
*tctx
,
1276 struct dcerpc_binding_handle
*b
,
1277 struct policy_handle
*handle
,
1278 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
1279 struct spoolss_DevmodeContainer
*devmode_ctr
,
1280 struct sec_desc_buf
*secdesc_ctr
,
1281 enum spoolss_PrinterControl command
)
1283 struct spoolss_SetPrinter r
;
1285 r
.in
.handle
= handle
;
1286 r
.in
.info_ctr
= info_ctr
;
1287 r
.in
.devmode_ctr
= devmode_ctr
;
1288 r
.in
.secdesc_ctr
= secdesc_ctr
;
1289 r
.in
.command
= command
;
1291 torture_comment(tctx
, "Testing SetPrinter level %d\n", r
.in
.info_ctr
->level
);
1293 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
),
1294 "failed to call SetPrinter");
1295 torture_assert(tctx
, (W_ERROR_EQUAL(r
.out
.result
, WERR_OK
)
1296 || W_ERROR_EQUAL(r
.out
.result
, WERR_IO_PENDING
)),
1297 "SetPrinter failed");
1302 static bool test_SetPrinter_errors(struct torture_context
*tctx
,
1303 struct dcerpc_binding_handle
*b
,
1304 struct policy_handle
*handle
)
1306 struct spoolss_SetPrinter r
;
1307 uint16_t levels
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1310 struct spoolss_SetPrinterInfoCtr info_ctr
;
1311 struct spoolss_DevmodeContainer devmode_ctr
;
1312 struct sec_desc_buf secdesc_ctr
;
1315 info_ctr
.info
.info0
= NULL
;
1317 ZERO_STRUCT(devmode_ctr
);
1318 ZERO_STRUCT(secdesc_ctr
);
1320 r
.in
.handle
= handle
;
1321 r
.in
.info_ctr
= &info_ctr
;
1322 r
.in
.devmode_ctr
= &devmode_ctr
;
1323 r
.in
.secdesc_ctr
= &secdesc_ctr
;
1326 torture_comment(tctx
, "Testing SetPrinter all zero\n");
1328 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
),
1329 "failed to call SetPrinter");
1330 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAMETER
,
1331 "failed to call SetPrinter");
1334 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
1336 struct spoolss_SetPrinterInfo0 info0
;
1337 struct spoolss_SetPrinterInfo1 info1
;
1338 struct spoolss_SetPrinterInfo2 info2
;
1339 struct spoolss_SetPrinterInfo3 info3
;
1340 struct spoolss_SetPrinterInfo4 info4
;
1341 struct spoolss_SetPrinterInfo5 info5
;
1342 struct spoolss_SetPrinterInfo6 info6
;
1343 struct spoolss_SetPrinterInfo7 info7
;
1344 struct spoolss_SetPrinterInfo8 info8
;
1345 struct spoolss_SetPrinterInfo9 info9
;
1348 info_ctr
.level
= levels
[i
];
1349 switch (levels
[i
]) {
1352 info_ctr
.info
.info0
= &info0
;
1356 info_ctr
.info
.info1
= &info1
;
1360 info_ctr
.info
.info2
= &info2
;
1364 info_ctr
.info
.info3
= &info3
;
1368 info_ctr
.info
.info4
= &info4
;
1372 info_ctr
.info
.info5
= &info5
;
1376 info_ctr
.info
.info6
= &info6
;
1380 info_ctr
.info
.info7
= &info7
;
1384 info_ctr
.info
.info8
= &info8
;
1388 info_ctr
.info
.info9
= &info9
;
1392 torture_comment(tctx
, "Testing SetPrinter level %d, command %d\n",
1393 info_ctr
.level
, r
.in
.command
);
1395 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
),
1396 "failed to call SetPrinter");
1398 switch (r
.in
.command
) {
1399 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
: /* 0 */
1400 /* is ignored for all levels other then 0 */
1401 if (info_ctr
.level
> 0) {
1405 case SPOOLSS_PRINTER_CONTROL_PAUSE
: /* 1 */
1406 case SPOOLSS_PRINTER_CONTROL_RESUME
: /* 2 */
1407 case SPOOLSS_PRINTER_CONTROL_PURGE
: /* 3 */
1408 if (info_ctr
.level
> 0) {
1409 /* is invalid for all levels other then 0 */
1410 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PRINTER_COMMAND
,
1411 "unexpected error code returned");
1414 torture_assert_werr_ok(tctx
, r
.out
.result
,
1415 "failed to call SetPrinter with non 0 command");
1420 case SPOOLSS_PRINTER_CONTROL_SET_STATUS
: /* 4 */
1421 /* FIXME: gd needs further investigation */
1423 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PRINTER_COMMAND
,
1424 "unexpected error code returned");
1428 switch (info_ctr
.level
) {
1430 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_LEVEL
,
1431 "unexpected error code returned");
1434 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_PRINTER_DRIVER
,
1435 "unexpected error code returned");
1441 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAMETER
,
1442 "unexpected error code returned");
1445 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_NOT_SUPPORTED
,
1446 "unexpected error code returned");
1449 torture_assert_werr_ok(tctx
, r
.out
.result
,
1450 "failed to call SetPrinter");
1455 if (r
.in
.command
< 5) {
1463 static void clear_info2(struct spoolss_SetPrinterInfoCtr
*r
)
1465 if ((r
->level
== 2) && (r
->info
.info2
)) {
1466 r
->info
.info2
->secdesc_ptr
= 0;
1467 r
->info
.info2
->devmode_ptr
= 0;
1471 static bool test_PrinterInfo(struct torture_context
*tctx
,
1472 struct dcerpc_binding_handle
*b
,
1473 struct policy_handle
*handle
)
1476 struct spoolss_SetPrinter s
;
1477 struct spoolss_GetPrinter q
;
1478 struct spoolss_GetPrinter q0
;
1479 struct spoolss_SetPrinterInfoCtr info_ctr
;
1480 union spoolss_PrinterInfo info
;
1481 struct spoolss_DevmodeContainer devmode_ctr
;
1482 struct sec_desc_buf secdesc_ctr
;
1487 uint32_t status_list
[] = {
1488 /* these do not stick
1489 PRINTER_STATUS_PAUSED,
1490 PRINTER_STATUS_ERROR,
1491 PRINTER_STATUS_PENDING_DELETION, */
1492 PRINTER_STATUS_PAPER_JAM
,
1493 PRINTER_STATUS_PAPER_OUT
,
1494 PRINTER_STATUS_MANUAL_FEED
,
1495 PRINTER_STATUS_PAPER_PROBLEM
,
1496 PRINTER_STATUS_OFFLINE
,
1497 PRINTER_STATUS_IO_ACTIVE
,
1498 PRINTER_STATUS_BUSY
,
1499 PRINTER_STATUS_PRINTING
,
1500 PRINTER_STATUS_OUTPUT_BIN_FULL
,
1501 PRINTER_STATUS_NOT_AVAILABLE
,
1502 PRINTER_STATUS_WAITING
,
1503 PRINTER_STATUS_PROCESSING
,
1504 PRINTER_STATUS_INITIALIZING
,
1505 PRINTER_STATUS_WARMING_UP
,
1506 PRINTER_STATUS_TONER_LOW
,
1507 PRINTER_STATUS_NO_TONER
,
1508 PRINTER_STATUS_PAGE_PUNT
,
1509 PRINTER_STATUS_USER_INTERVENTION
,
1510 PRINTER_STATUS_OUT_OF_MEMORY
,
1511 PRINTER_STATUS_DOOR_OPEN
,
1512 PRINTER_STATUS_SERVER_UNKNOWN
,
1513 PRINTER_STATUS_POWER_SAVE
,
1514 /* these do not stick
1523 uint32_t default_attribute
= PRINTER_ATTRIBUTE_LOCAL
;
1524 uint32_t attribute_list
[] = {
1525 PRINTER_ATTRIBUTE_QUEUED
,
1526 /* fails with WERR_INVALID_DATATYPE:
1527 PRINTER_ATTRIBUTE_DIRECT, */
1529 PRINTER_ATTRIBUTE_DEFAULT, */
1530 PRINTER_ATTRIBUTE_SHARED
,
1532 PRINTER_ATTRIBUTE_NETWORK, */
1533 PRINTER_ATTRIBUTE_HIDDEN
,
1534 PRINTER_ATTRIBUTE_LOCAL
,
1535 PRINTER_ATTRIBUTE_ENABLE_DEVQ
,
1536 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
,
1537 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST
,
1538 PRINTER_ATTRIBUTE_WORK_OFFLINE
,
1540 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1541 /* fails with WERR_INVALID_DATATYPE:
1542 PRINTER_ATTRIBUTE_RAW_ONLY, */
1543 /* these do not stick
1544 PRINTER_ATTRIBUTE_PUBLISHED,
1545 PRINTER_ATTRIBUTE_FAX,
1546 PRINTER_ATTRIBUTE_TS,
1565 torture_skip(tctx
, "Printer Info test is currently broken, skipping");
1568 ZERO_STRUCT(devmode_ctr
);
1569 ZERO_STRUCT(secdesc_ctr
);
1571 s
.in
.handle
= handle
;
1573 s
.in
.info_ctr
= &info_ctr
;
1574 s
.in
.devmode_ctr
= &devmode_ctr
;
1575 s
.in
.secdesc_ctr
= &secdesc_ctr
;
1577 q
.in
.handle
= handle
;
1581 #define TESTGETCALL(call, r) \
1582 r.in.buffer = NULL; \
1584 r.out.needed = &needed; \
1585 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1586 if (!NT_STATUS_IS_OK(status)) { \
1587 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1588 r.in.level, nt_errstr(status), __location__); \
1592 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1593 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1594 r.in.buffer = &blob; \
1595 r.in.offered = needed; \
1597 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1598 if (!NT_STATUS_IS_OK(status)) { \
1599 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1600 r.in.level, nt_errstr(status), __location__); \
1604 if (!W_ERROR_IS_OK(r.out.result)) { \
1605 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1606 r.in.level, win_errstr(r.out.result), __location__); \
1612 #define TESTSETCALL_EXP(call, r, err) \
1613 clear_info2(&info_ctr);\
1614 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1615 if (!NT_STATUS_IS_OK(status)) { \
1616 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1617 r.in.info_ctr->level, nt_errstr(status), __location__); \
1621 if (!W_ERROR_IS_OK(err)) { \
1622 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1623 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1624 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1629 if (!W_ERROR_IS_OK(r.out.result)) { \
1630 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1631 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1636 #define TESTSETCALL(call, r) \
1637 TESTSETCALL_EXP(call, r, WERR_OK)
1639 #define STRING_EQUAL(s1, s2, field) \
1640 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1641 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1642 #field, s2, __location__); \
1647 #define MEM_EQUAL(s1, s2, length, field) \
1648 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1649 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1650 #field, (const char *)s2, __location__); \
1655 #define INT_EQUAL(i1, i2, field) \
1657 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1658 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1663 #define SD_EQUAL(sd1, sd2, field) \
1664 if (!security_descriptor_equal(sd1, sd2)) { \
1665 torture_comment(tctx, "Failed to set %s (%s)\n", \
1666 #field, __location__); \
1671 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1673 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1674 q.in.level = lvl1; \
1675 TESTGETCALL(GetPrinter, q) \
1676 info_ctr.level = lvl1; \
1677 p = (void *)&q.out.info->info ## lvl1; \
1678 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
1679 info_ctr.info.info ## lvl1->field1 = value;\
1680 TESTSETCALL_EXP(SetPrinter, s, err) \
1681 info_ctr.info.info ## lvl1->field1 = ""; \
1682 TESTGETCALL(GetPrinter, q) \
1683 info_ctr.info.info ## lvl1->field1 = value; \
1684 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1685 q.in.level = lvl2; \
1686 TESTGETCALL(GetPrinter, q) \
1687 p = (void *)&q.out.info->info ## lvl2; \
1688 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)p; \
1689 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1692 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1693 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1696 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1698 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1699 q.in.level = lvl1; \
1700 TESTGETCALL(GetPrinter, q) \
1701 info_ctr.level = lvl1; \
1702 p = (void *)&q.out.info->info ## lvl1; \
1703 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
1704 info_ctr.info.info ## lvl1->field1 = value; \
1705 TESTSETCALL(SetPrinter, s) \
1706 info_ctr.info.info ## lvl1->field1 = 0; \
1707 TESTGETCALL(GetPrinter, q) \
1708 p = (void *)&q.out.info->info ## lvl1; \
1709 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
1710 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1711 q.in.level = lvl2; \
1712 TESTGETCALL(GetPrinter, q) \
1713 p = (void *)&q.out.info->info ## lvl2; \
1714 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)p; \
1715 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1718 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1719 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1723 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1725 TEST_PRINTERINFO_STRING(2, comment
, 1, comment
, "xx2-1 comment");
1726 TEST_PRINTERINFO_STRING(2, comment
, 2, comment
, "xx2-2 comment");
1728 /* level 0 printername does not stick */
1729 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1730 TEST_PRINTERINFO_STRING(2, printername
, 1, name
, "xx2-1 printer");
1731 TEST_PRINTERINFO_STRING(2, printername
, 2, printername
, "xx2-2 printer");
1732 TEST_PRINTERINFO_STRING(2, printername
, 4, printername
, "xx2-4 printer");
1733 TEST_PRINTERINFO_STRING(2, printername
, 5, printername
, "xx2-5 printer");
1734 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1735 TEST_PRINTERINFO_STRING(4, printername
, 1, name
, "xx4-1 printer");
1736 TEST_PRINTERINFO_STRING(4, printername
, 2, printername
, "xx4-2 printer");
1737 TEST_PRINTERINFO_STRING(4, printername
, 4, printername
, "xx4-4 printer");
1738 TEST_PRINTERINFO_STRING(4, printername
, 5, printername
, "xx4-5 printer");
1739 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1740 TEST_PRINTERINFO_STRING(5, printername
, 1, name
, "xx5-1 printer");
1741 TEST_PRINTERINFO_STRING(5, printername
, 2, printername
, "xx5-2 printer");
1742 TEST_PRINTERINFO_STRING(5, printername
, 4, printername
, "xx5-4 printer");
1743 TEST_PRINTERINFO_STRING(5, printername
, 5, printername
, "xx5-5 printer");
1745 /* servername can be set but does not stick
1746 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1747 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1748 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1751 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1752 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname
, 2, portname
, "xx2-2 portname", WERR_UNKNOWN_PORT
);
1753 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname
, 5, portname
, "xx2-5 portname", WERR_UNKNOWN_PORT
);
1754 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname
, 2, portname
, "xx5-2 portname", WERR_UNKNOWN_PORT
);
1755 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname
, 5, portname
, "xx5-5 portname", WERR_UNKNOWN_PORT
);
1757 TEST_PRINTERINFO_STRING(2, sharename
, 2, sharename
, "xx2-2 sharename");
1758 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1759 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername
, 2, drivername
, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER
);
1760 TEST_PRINTERINFO_STRING(2, location
, 2, location
, "xx2-2 location");
1761 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1762 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile
, 2, sepfile
, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE
);
1763 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1764 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor
, 2, printprocessor
, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR
);
1765 TEST_PRINTERINFO_STRING(2, datatype
, 2, datatype
, "xx2-2 datatype");
1766 TEST_PRINTERINFO_STRING(2, parameters
, 2, parameters
, "xx2-2 parameters");
1768 for (i
=0; i
< ARRAY_SIZE(attribute_list
); i
++) {
1769 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1771 (attribute_list[i] | default_attribute)
1773 TEST_PRINTERINFO_INT_EXP(2, attributes
, 2, attributes
,
1775 (attribute_list
[i
] | default_attribute
)
1777 TEST_PRINTERINFO_INT_EXP(2, attributes
, 4, attributes
,
1779 (attribute_list
[i
] | default_attribute
)
1781 TEST_PRINTERINFO_INT_EXP(2, attributes
, 5, attributes
,
1783 (attribute_list
[i
] | default_attribute
)
1785 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1787 (attribute_list[i] | default_attribute)
1789 TEST_PRINTERINFO_INT_EXP(4, attributes
, 2, attributes
,
1791 (attribute_list
[i
] | default_attribute
)
1793 TEST_PRINTERINFO_INT_EXP(4, attributes
, 4, attributes
,
1795 (attribute_list
[i
] | default_attribute
)
1797 TEST_PRINTERINFO_INT_EXP(4, attributes
, 5, attributes
,
1799 (attribute_list
[i
] | default_attribute
)
1801 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1803 (attribute_list[i] | default_attribute)
1805 TEST_PRINTERINFO_INT_EXP(5, attributes
, 2, attributes
,
1807 (attribute_list
[i
] | default_attribute
)
1809 TEST_PRINTERINFO_INT_EXP(5, attributes
, 4, attributes
,
1811 (attribute_list
[i
] | default_attribute
)
1813 TEST_PRINTERINFO_INT_EXP(5, attributes
, 5, attributes
,
1815 (attribute_list
[i
] | default_attribute
)
1819 for (i
=0; i
< ARRAY_SIZE(status_list
); i
++) {
1820 /* level 2 sets do not stick
1821 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1822 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1823 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1824 TEST_PRINTERINFO_INT(6, status
, 0, status
, status_list
[i
]);
1825 TEST_PRINTERINFO_INT(6, status
, 2, status
, status_list
[i
]);
1826 TEST_PRINTERINFO_INT(6, status
, 6, status
, status_list
[i
]);
1829 /* priorities need to be between 0 and 99
1830 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1831 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 0);
1832 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 1);
1833 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 99);
1834 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1835 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 0);
1836 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 1);
1837 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 99);
1838 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1840 TEST_PRINTERINFO_INT(2, starttime
, 2, starttime
, __LINE__
);
1841 TEST_PRINTERINFO_INT(2, untiltime
, 2, untiltime
, __LINE__
);
1844 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1845 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1848 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1849 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1851 /* FIXME: gd also test devmode and secdesc behavior */
1854 /* verify composition of level 1 description field */
1855 const char *description
;
1859 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1861 description
= talloc_strdup(tctx
, q0
.out
.info
->info1
.description
);
1864 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1866 tmp
= talloc_asprintf(tctx
, "%s,%s,%s",
1867 q0
.out
.info
->info2
.printername
,
1868 q0
.out
.info
->info2
.drivername
,
1869 q0
.out
.info
->info2
.location
);
1871 do { STRING_EQUAL(description
, tmp
, "description")} while (0);
1877 static bool test_security_descriptor_equal(struct torture_context
*tctx
,
1878 const struct security_descriptor
*sd1
,
1879 const struct security_descriptor
*sd2
)
1886 torture_comment(tctx
, "%s\n", __location__
);
1890 torture_assert_int_equal(tctx
, sd1
->revision
, sd2
->revision
, "revision mismatch");
1891 torture_assert_int_equal(tctx
, sd1
->type
, sd2
->type
, "type mismatch");
1893 torture_assert_sid_equal(tctx
, sd1
->owner_sid
, sd2
->owner_sid
, "owner mismatch");
1894 torture_assert_sid_equal(tctx
, sd1
->group_sid
, sd2
->group_sid
, "group mismatch");
1896 if (!security_acl_equal(sd1
->sacl
, sd2
->sacl
)) {
1897 torture_comment(tctx
, "%s: sacl mismatch\n", __location__
);
1898 NDR_PRINT_DEBUG(security_acl
, sd1
->sacl
);
1899 NDR_PRINT_DEBUG(security_acl
, sd2
->sacl
);
1902 if (!security_acl_equal(sd1
->dacl
, sd2
->dacl
)) {
1903 torture_comment(tctx
, "%s: dacl mismatch\n", __location__
);
1904 NDR_PRINT_DEBUG(security_acl
, sd1
->dacl
);
1905 NDR_PRINT_DEBUG(security_acl
, sd2
->dacl
);
1912 static bool test_sd_set_level(struct torture_context
*tctx
,
1913 struct dcerpc_binding_handle
*b
,
1914 struct policy_handle
*handle
,
1916 struct security_descriptor
*sd
)
1918 struct spoolss_SetPrinterInfoCtr info_ctr
;
1919 struct spoolss_DevmodeContainer devmode_ctr
;
1920 struct sec_desc_buf secdesc_ctr
;
1921 union spoolss_SetPrinterInfo sinfo
;
1922 union spoolss_PrinterInfo info
;
1923 struct spoolss_SetPrinterInfo3 info3
;
1925 ZERO_STRUCT(devmode_ctr
);
1926 ZERO_STRUCT(secdesc_ctr
);
1930 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
1931 torture_assert(tctx
, PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
1934 info_ctr
.info
= sinfo
;
1940 info3
.sec_desc_ptr
= 0;
1943 info_ctr
.info
.info3
= &info3
;
1951 secdesc_ctr
.sd
= sd
;
1953 torture_assert(tctx
,
1954 test_SetPrinter(tctx
, b
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0), "");
1959 static bool test_PrinterInfo_SDs(struct torture_context
*tctx
,
1960 struct dcerpc_binding_handle
*b
,
1961 struct policy_handle
*handle
)
1963 union spoolss_PrinterInfo info
;
1964 struct security_descriptor
*sd1
, *sd2
;
1967 /* just compare level 2 and level 3 */
1969 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
1971 sd1
= info
.info2
.secdesc
;
1973 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 3, &info
), "");
1975 sd2
= info
.info3
.secdesc
;
1977 torture_assert(tctx
, test_security_descriptor_equal(tctx
, sd1
, sd2
),
1978 "SD level 2 != SD level 3");
1981 /* query level 2, set level 2, query level 2 */
1983 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
1985 sd1
= info
.info2
.secdesc
;
1987 torture_assert(tctx
, test_sd_set_level(tctx
, b
, handle
, 2, sd1
), "");
1989 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
1991 sd2
= info
.info2
.secdesc
;
1992 if (sd1
->type
& SEC_DESC_DACL_DEFAULTED
) {
1993 torture_comment(tctx
, "removing SEC_DESC_DACL_DEFAULTED\n");
1994 sd1
->type
&= ~SEC_DESC_DACL_DEFAULTED
;
1997 torture_assert(tctx
, test_security_descriptor_equal(tctx
, sd1
, sd2
),
1998 "SD level 2 != SD level 2 after SD has been set via level 2");
2001 /* query level 2, set level 3, query level 2 */
2003 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
2005 sd1
= info
.info2
.secdesc
;
2007 torture_assert(tctx
, test_sd_set_level(tctx
, b
, handle
, 3, sd1
), "");
2009 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
2011 sd2
= info
.info2
.secdesc
;
2013 torture_assert(tctx
, test_security_descriptor_equal(tctx
, sd1
, sd2
),
2014 "SD level 2 != SD level 2 after SD has been set via level 3");
2016 /* set modified sd level 3, query level 2 */
2018 for (i
=0; i
< 93; i
++) {
2019 struct security_ace a
;
2020 const char *sid_string
= talloc_asprintf(tctx
, "S-1-5-32-9999%i", i
);
2021 a
.type
= SEC_ACE_TYPE_ACCESS_ALLOWED
;
2023 a
.size
= 0; /* autogenerated */
2025 a
.trustee
= *dom_sid_parse_talloc(tctx
, sid_string
);
2026 torture_assert_ntstatus_ok(tctx
, security_descriptor_dacl_add(sd1
, &a
), "");
2029 torture_assert(tctx
, test_sd_set_level(tctx
, b
, handle
, 3, sd1
), "");
2031 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
2032 sd2
= info
.info2
.secdesc
;
2034 if (sd1
->type
& SEC_DESC_DACL_DEFAULTED
) {
2035 torture_comment(tctx
, "removing SEC_DESC_DACL_DEFAULTED\n");
2036 sd1
->type
&= ~SEC_DESC_DACL_DEFAULTED
;
2039 torture_assert(tctx
, test_security_descriptor_equal(tctx
, sd1
, sd2
),
2040 "modified SD level 2 != SD level 2 after SD has been set via level 3");
2047 * wrapper call that saves original sd, runs tests, and restores sd
2050 static bool test_PrinterInfo_SD(struct torture_context
*tctx
,
2051 struct dcerpc_binding_handle
*b
,
2052 struct policy_handle
*handle
)
2054 union spoolss_PrinterInfo info
;
2055 struct security_descriptor
*sd
;
2058 torture_comment(tctx
, "Testing Printer Security Descriptors\n");
2060 /* save original sd */
2062 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
2063 "failed to get initial security descriptor");
2065 sd
= security_descriptor_copy(tctx
, info
.info2
.secdesc
);
2069 ret
= test_PrinterInfo_SDs(tctx
, b
, handle
);
2071 /* restore original sd */
2073 torture_assert(tctx
, test_sd_set_level(tctx
, b
, handle
, 3, sd
),
2074 "failed to restore initial security descriptor");
2076 torture_comment(tctx
, "Printer Security Descriptors test %s\n\n",
2077 ret
? "succeeded" : "failed");
2083 static bool test_devmode_set_level(struct torture_context
*tctx
,
2084 struct dcerpc_binding_handle
*b
,
2085 struct policy_handle
*handle
,
2087 struct spoolss_DeviceMode
*devmode
)
2089 struct spoolss_SetPrinterInfoCtr info_ctr
;
2090 struct spoolss_DevmodeContainer devmode_ctr
;
2091 struct sec_desc_buf secdesc_ctr
;
2092 union spoolss_SetPrinterInfo sinfo
;
2094 ZERO_STRUCT(devmode_ctr
);
2095 ZERO_STRUCT(secdesc_ctr
);
2099 union spoolss_PrinterInfo info
;
2100 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
2101 torture_assert(tctx
, PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
2104 info_ctr
.info
= sinfo
;
2109 struct spoolss_SetPrinterInfo8 info8
;
2111 info8
.devmode_ptr
= 0;
2114 info_ctr
.info
.info8
= &info8
;
2122 devmode_ctr
.devmode
= devmode
;
2124 torture_assert(tctx
,
2125 test_SetPrinter(tctx
, b
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0), "");
2131 static bool test_devicemode_equal(struct torture_context
*tctx
,
2132 const struct spoolss_DeviceMode
*d1
,
2133 const struct spoolss_DeviceMode
*d2
)
2140 torture_comment(tctx
, "%s\n", __location__
);
2143 torture_assert_str_equal(tctx
, d1
->devicename
, d2
->devicename
, "devicename mismatch");
2144 torture_assert_int_equal(tctx
, d1
->specversion
, d2
->specversion
, "specversion mismatch");
2145 torture_assert_int_equal(tctx
, d1
->driverversion
, d2
->driverversion
, "driverversion mismatch");
2146 torture_assert_int_equal(tctx
, d1
->size
, d2
->size
, "size mismatch");
2147 torture_assert_int_equal(tctx
, d1
->__driverextra_length
, d2
->__driverextra_length
, "__driverextra_length mismatch");
2148 torture_assert_int_equal(tctx
, d1
->fields
, d2
->fields
, "fields mismatch");
2149 torture_assert_int_equal(tctx
, d1
->orientation
, d2
->orientation
, "orientation mismatch");
2150 torture_assert_int_equal(tctx
, d1
->papersize
, d2
->papersize
, "papersize mismatch");
2151 torture_assert_int_equal(tctx
, d1
->paperlength
, d2
->paperlength
, "paperlength mismatch");
2152 torture_assert_int_equal(tctx
, d1
->paperwidth
, d2
->paperwidth
, "paperwidth mismatch");
2153 torture_assert_int_equal(tctx
, d1
->scale
, d2
->scale
, "scale mismatch");
2154 torture_assert_int_equal(tctx
, d1
->copies
, d2
->copies
, "copies mismatch");
2155 torture_assert_int_equal(tctx
, d1
->defaultsource
, d2
->defaultsource
, "defaultsource mismatch");
2156 torture_assert_int_equal(tctx
, d1
->printquality
, d2
->printquality
, "printquality mismatch");
2157 torture_assert_int_equal(tctx
, d1
->color
, d2
->color
, "color mismatch");
2158 torture_assert_int_equal(tctx
, d1
->duplex
, d2
->duplex
, "duplex mismatch");
2159 torture_assert_int_equal(tctx
, d1
->yresolution
, d2
->yresolution
, "yresolution mismatch");
2160 torture_assert_int_equal(tctx
, d1
->ttoption
, d2
->ttoption
, "ttoption mismatch");
2161 torture_assert_int_equal(tctx
, d1
->collate
, d2
->collate
, "collate mismatch");
2162 torture_assert_str_equal(tctx
, d1
->formname
, d2
->formname
, "formname mismatch");
2163 torture_assert_int_equal(tctx
, d1
->logpixels
, d2
->logpixels
, "logpixels mismatch");
2164 torture_assert_int_equal(tctx
, d1
->bitsperpel
, d2
->bitsperpel
, "bitsperpel mismatch");
2165 torture_assert_int_equal(tctx
, d1
->pelswidth
, d2
->pelswidth
, "pelswidth mismatch");
2166 torture_assert_int_equal(tctx
, d1
->pelsheight
, d2
->pelsheight
, "pelsheight mismatch");
2167 torture_assert_int_equal(tctx
, d1
->displayflags
, d2
->displayflags
, "displayflags mismatch");
2168 torture_assert_int_equal(tctx
, d1
->displayfrequency
, d2
->displayfrequency
, "displayfrequency mismatch");
2169 torture_assert_int_equal(tctx
, d1
->icmmethod
, d2
->icmmethod
, "icmmethod mismatch");
2170 torture_assert_int_equal(tctx
, d1
->icmintent
, d2
->icmintent
, "icmintent mismatch");
2171 torture_assert_int_equal(tctx
, d1
->mediatype
, d2
->mediatype
, "mediatype mismatch");
2172 torture_assert_int_equal(tctx
, d1
->dithertype
, d2
->dithertype
, "dithertype mismatch");
2173 torture_assert_int_equal(tctx
, d1
->reserved1
, d2
->reserved1
, "reserved1 mismatch");
2174 torture_assert_int_equal(tctx
, d1
->reserved2
, d2
->reserved2
, "reserved2 mismatch");
2175 torture_assert_int_equal(tctx
, d1
->panningwidth
, d2
->panningwidth
, "panningwidth mismatch");
2176 torture_assert_int_equal(tctx
, d1
->panningheight
, d2
->panningheight
, "panningheight mismatch");
2177 torture_assert_data_blob_equal(tctx
, d1
->driverextra_data
, d2
->driverextra_data
, "driverextra_data mismatch");
2182 static bool test_devicemode_full(struct torture_context
*tctx
,
2183 struct dcerpc_binding_handle
*b
,
2184 struct policy_handle
*handle
)
2186 struct spoolss_SetPrinter s
;
2187 struct spoolss_GetPrinter q
;
2188 struct spoolss_SetPrinterInfoCtr info_ctr
;
2189 struct spoolss_SetPrinterInfo8 info8
;
2190 union spoolss_PrinterInfo info
;
2191 struct spoolss_DevmodeContainer devmode_ctr
;
2192 struct sec_desc_buf secdesc_ctr
;
2197 #define TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, exp_value, expected_result) do { \
2198 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2199 q.in.level = lvl1; \
2200 TESTGETCALL(GetPrinter, q) \
2201 info_ctr.level = lvl1; \
2203 void *p = (void *)&q.out.info->info ## lvl1; \
2204 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
2205 } else if (lvl1 == 8) {\
2206 info_ctr.info.info ## lvl1 = &info8; \
2208 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2209 devmode_ctr.devmode->field1 = value; \
2210 TESTSETCALL_EXP(SetPrinter, s, expected_result) \
2211 if (W_ERROR_IS_OK(expected_result)) { \
2212 TESTGETCALL(GetPrinter, q) \
2213 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2214 q.in.level = lvl2; \
2215 TESTGETCALL(GetPrinter, q) \
2216 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2220 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, expected_result) do { \
2221 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, expected_result); \
2224 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2225 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, WERR_OK); \
2228 ZERO_STRUCT(devmode_ctr
);
2229 ZERO_STRUCT(secdesc_ctr
);
2232 s
.in
.handle
= handle
;
2234 s
.in
.info_ctr
= &info_ctr
;
2235 s
.in
.devmode_ctr
= &devmode_ctr
;
2236 s
.in
.secdesc_ctr
= &secdesc_ctr
;
2238 q
.in
.handle
= handle
;
2242 const char *devicename
;/* [charset(UTF16)] */
2243 enum spoolss_DeviceModeSpecVersion specversion
;
2244 uint16_t driverversion
;
2245 uint16_t __driverextra_length
;/* [value(r->driverextra_data.length)] */
2248 TEST_DEVMODE_INT_EXP(8, size
, 8, size
, __LINE__
, WERR_INVALID_PARAMETER
);
2249 TEST_DEVMODE_INT_EXP(8, size
, 8, size
, 0, WERR_INVALID_PARAMETER
);
2250 TEST_DEVMODE_INT_EXP(8, size
, 8, size
, 0xffff, WERR_INVALID_PARAMETER
);
2251 TEST_DEVMODE_INT_EXP(8, size
, 8, size
, ndr_size_spoolss_DeviceMode(devmode_ctr
.devmode
, 0), (devmode_ctr
.devmode
->__driverextra_length
> 0 ) ? WERR_INVALID_PARAMETER
: WERR_OK
);
2252 TEST_DEVMODE_INT(8, size
, 8, size
, ndr_size_spoolss_DeviceMode(devmode_ctr
.devmode
, 0) - devmode_ctr
.devmode
->__driverextra_length
);
2254 devmode_ctr
.devmode
->driverextra_data
= data_blob_string_const("foobar");
2255 torture_assert(tctx
,
2256 test_devmode_set_level(tctx
, b
, handle
, 8, devmode_ctr
.devmode
),
2257 "failed to set devmode");
2259 TEST_DEVMODE_INT_EXP(8, size
, 8, size
, ndr_size_spoolss_DeviceMode(devmode_ctr
.devmode
, 0), (devmode_ctr
.devmode
->__driverextra_length
> 0 ) ? WERR_INVALID_PARAMETER
: WERR_OK
);
2260 TEST_DEVMODE_INT(8, size
, 8, size
, ndr_size_spoolss_DeviceMode(devmode_ctr
.devmode
, 0) - devmode_ctr
.devmode
->__driverextra_length
);
2262 TEST_DEVMODE_INT(8, orientation
, 8, orientation
, __LINE__
);
2263 TEST_DEVMODE_INT(8, papersize
, 8, papersize
, __LINE__
);
2264 TEST_DEVMODE_INT(8, paperlength
, 8, paperlength
, __LINE__
);
2265 TEST_DEVMODE_INT(8, paperwidth
, 8, paperwidth
, __LINE__
);
2266 TEST_DEVMODE_INT(8, scale
, 8, scale
, __LINE__
);
2267 TEST_DEVMODE_INT(8, copies
, 8, copies
, __LINE__
);
2268 TEST_DEVMODE_INT(8, defaultsource
, 8, defaultsource
, __LINE__
);
2269 TEST_DEVMODE_INT(8, printquality
, 8, printquality
, __LINE__
);
2270 TEST_DEVMODE_INT(8, color
, 8, color
, __LINE__
);
2271 TEST_DEVMODE_INT(8, duplex
, 8, duplex
, __LINE__
);
2272 TEST_DEVMODE_INT(8, yresolution
, 8, yresolution
, __LINE__
);
2273 TEST_DEVMODE_INT(8, ttoption
, 8, ttoption
, __LINE__
);
2274 TEST_DEVMODE_INT(8, collate
, 8, collate
, __LINE__
);
2276 const char *formname
;/* [charset(UTF16)] */
2278 TEST_DEVMODE_INT(8, logpixels
, 8, logpixels
, __LINE__
);
2279 TEST_DEVMODE_INT(8, bitsperpel
, 8, bitsperpel
, __LINE__
);
2280 TEST_DEVMODE_INT(8, pelswidth
, 8, pelswidth
, __LINE__
);
2281 TEST_DEVMODE_INT(8, pelsheight
, 8, pelsheight
, __LINE__
);
2282 TEST_DEVMODE_INT(8, displayflags
, 8, displayflags
, __LINE__
);
2283 TEST_DEVMODE_INT(8, displayfrequency
, 8, displayfrequency
, __LINE__
);
2284 TEST_DEVMODE_INT(8, icmmethod
, 8, icmmethod
, __LINE__
);
2285 TEST_DEVMODE_INT(8, icmintent
, 8, icmintent
, __LINE__
);
2286 TEST_DEVMODE_INT(8, mediatype
, 8, mediatype
, __LINE__
);
2287 TEST_DEVMODE_INT(8, dithertype
, 8, dithertype
, __LINE__
);
2288 TEST_DEVMODE_INT(8, reserved1
, 8, reserved1
, __LINE__
);
2289 TEST_DEVMODE_INT(8, reserved2
, 8, reserved2
, __LINE__
);
2290 TEST_DEVMODE_INT(8, panningwidth
, 8, panningwidth
, __LINE__
);
2291 TEST_DEVMODE_INT(8, panningheight
, 8, panningheight
, __LINE__
);
2296 static bool call_OpenPrinterEx(struct torture_context
*tctx
,
2297 struct dcerpc_pipe
*p
,
2299 struct spoolss_DeviceMode
*devmode
,
2300 struct policy_handle
*handle
);
2302 static bool test_PrinterInfo_DevModes(struct torture_context
*tctx
,
2303 struct dcerpc_pipe
*p
,
2304 struct policy_handle
*handle
,
2307 union spoolss_PrinterInfo info
;
2308 struct spoolss_DeviceMode
*devmode
;
2309 struct spoolss_DeviceMode
*devmode2
;
2310 struct policy_handle handle_devmode
;
2311 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
2313 /* simply compare level8 and level2 devmode */
2315 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 8, &info
), "");
2317 devmode
= info
.info8
.devmode
;
2319 if (devmode
&& devmode
->size
== 0) {
2321 "devmode of zero size!");
2324 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
2326 devmode2
= info
.info2
.devmode
;
2328 if (devmode2
&& devmode2
->size
== 0) {
2330 "devmode of zero size!");
2333 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2334 "DM level 8 != DM level 2");
2337 /* set devicemode level 8 and see if it persists */
2339 devmode
->copies
= 93;
2340 devmode
->formname
= talloc_strdup(tctx
, "Legal");
2342 torture_assert(tctx
, test_devmode_set_level(tctx
, b
, handle
, 8, devmode
), "");
2344 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 8, &info
), "");
2346 devmode2
= info
.info8
.devmode
;
2348 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2349 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2351 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
2353 devmode2
= info
.info2
.devmode
;
2355 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2356 "modified DM level 8 != DM level 2");
2359 /* set devicemode level 2 and see if it persists */
2361 devmode
->copies
= 39;
2362 devmode
->formname
= talloc_strdup(tctx
, "Executive");
2364 torture_assert(tctx
, test_devmode_set_level(tctx
, b
, handle
, 2, devmode
), "");
2366 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 8, &info
), "");
2368 devmode2
= info
.info8
.devmode
;
2370 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2371 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2373 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
2375 devmode2
= info
.info2
.devmode
;
2377 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2378 "modified DM level 8 != DM level 2");
2381 /* check every single bit in public part of devicemode */
2383 torture_assert(tctx
, test_devicemode_full(tctx
, b
, handle
),
2384 "failed to set every single devicemode component");
2387 /* change formname upon open and see if it persists in getprinter calls */
2389 devmode
->formname
= talloc_strdup(tctx
, "A4");
2390 devmode
->copies
= 42;
2392 torture_assert(tctx
, call_OpenPrinterEx(tctx
, p
, name
, devmode
, &handle_devmode
),
2393 "failed to open printer handle");
2395 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, &handle_devmode
, 8, &info
), "");
2397 devmode2
= info
.info8
.devmode
;
2399 if (strequal(devmode
->devicename
, devmode2
->devicename
)) {
2400 torture_warning(tctx
, "devicenames are the same\n");
2402 torture_comment(tctx
, "devicename passed in for open: %s\n", devmode
->devicename
);
2403 torture_comment(tctx
, "devicename after level 8 get: %s\n", devmode2
->devicename
);
2406 if (strequal(devmode
->formname
, devmode2
->formname
)) {
2407 torture_warning(tctx
, "formname are the same\n");
2409 torture_comment(tctx
, "formname passed in for open: %s\n", devmode
->formname
);
2410 torture_comment(tctx
, "formname after level 8 get: %s\n", devmode2
->formname
);
2413 if (devmode
->copies
== devmode2
->copies
) {
2414 torture_warning(tctx
, "copies are the same\n");
2416 torture_comment(tctx
, "copies passed in for open: %d\n", devmode
->copies
);
2417 torture_comment(tctx
, "copies after level 8 get: %d\n", devmode2
->copies
);
2420 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, &handle_devmode
, 2, &info
), "");
2422 devmode2
= info
.info2
.devmode
;
2424 if (strequal(devmode
->devicename
, devmode2
->devicename
)) {
2425 torture_warning(tctx
, "devicenames are the same\n");
2427 torture_comment(tctx
, "devicename passed in for open: %s\n", devmode
->devicename
);
2428 torture_comment(tctx
, "devicename after level 2 get: %s\n", devmode2
->devicename
);
2431 if (strequal(devmode
->formname
, devmode2
->formname
)) {
2432 torture_warning(tctx
, "formname is the same\n");
2434 torture_comment(tctx
, "formname passed in for open: %s\n", devmode
->formname
);
2435 torture_comment(tctx
, "formname after level 2 get: %s\n", devmode2
->formname
);
2438 if (devmode
->copies
== devmode2
->copies
) {
2439 torture_warning(tctx
, "copies are the same\n");
2441 torture_comment(tctx
, "copies passed in for open: %d\n", devmode
->copies
);
2442 torture_comment(tctx
, "copies after level 2 get: %d\n", devmode2
->copies
);
2445 test_ClosePrinter(tctx
, b
, &handle_devmode
);
2451 * wrapper call that saves original devmode, runs tests, and restores devmode
2454 static bool test_PrinterInfo_DevMode(struct torture_context
*tctx
,
2455 struct dcerpc_pipe
*p
,
2456 struct policy_handle
*handle
,
2458 struct spoolss_DeviceMode
*addprinter_devmode
)
2460 union spoolss_PrinterInfo info
;
2461 struct spoolss_DeviceMode
*devmode
;
2463 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
2465 torture_comment(tctx
, "Testing Printer Devicemodes\n");
2467 /* save original devmode */
2469 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 8, &info
),
2470 "failed to get initial global devicemode");
2472 devmode
= info
.info8
.devmode
;
2474 if (devmode
&& devmode
->size
== 0) {
2476 "devmode of zero size!");
2479 if (addprinter_devmode
) {
2480 if (!test_devicemode_equal(tctx
, devmode
, addprinter_devmode
)) {
2481 torture_warning(tctx
, "current global DM is != DM provided in addprinter");
2487 ret
= test_PrinterInfo_DevModes(tctx
, p
, handle
, name
);
2489 /* restore original devmode */
2491 torture_assert(tctx
, test_devmode_set_level(tctx
, b
, handle
, 8, devmode
),
2492 "failed to restore initial global device mode");
2494 torture_comment(tctx
, "Printer Devicemodes test %s\n\n",
2495 ret
? "succeeded" : "failed");
2501 bool test_ClosePrinter(struct torture_context
*tctx
,
2502 struct dcerpc_binding_handle
*b
,
2503 struct policy_handle
*handle
)
2506 struct spoolss_ClosePrinter r
;
2508 r
.in
.handle
= handle
;
2509 r
.out
.handle
= handle
;
2511 torture_comment(tctx
, "Testing ClosePrinter\n");
2513 status
= dcerpc_spoolss_ClosePrinter_r(b
, tctx
, &r
);
2514 torture_assert_ntstatus_ok(tctx
, status
, "ClosePrinter failed");
2515 torture_assert_werr_ok(tctx
, r
.out
.result
, "ClosePrinter failed");
2520 static bool test_GetForm_args(struct torture_context
*tctx
,
2521 struct dcerpc_binding_handle
*b
,
2522 struct policy_handle
*handle
,
2523 const char *form_name
,
2525 union spoolss_FormInfo
*info_p
)
2528 struct spoolss_GetForm r
;
2531 r
.in
.handle
= handle
;
2532 r
.in
.form_name
= form_name
;
2536 r
.out
.needed
= &needed
;
2538 torture_comment(tctx
, "Testing GetForm(%s) level %d\n", form_name
, r
.in
.level
);
2540 status
= dcerpc_spoolss_GetForm_r(b
, tctx
, &r
);
2541 torture_assert_ntstatus_ok(tctx
, status
, "GetForm failed");
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
;
2547 status
= dcerpc_spoolss_GetForm_r(b
, tctx
, &r
);
2548 torture_assert_ntstatus_ok(tctx
, status
, "GetForm failed");
2550 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetForm failed");
2552 torture_assert(tctx
, r
.out
.info
, "No form info returned");
2555 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetForm failed");
2557 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo
, r
.out
.info
, r
.in
.level
, needed
, 4);
2560 *info_p
= *r
.out
.info
;
2566 static bool test_GetForm(struct torture_context
*tctx
,
2567 struct dcerpc_binding_handle
*b
,
2568 struct policy_handle
*handle
,
2569 const char *form_name
,
2572 return test_GetForm_args(tctx
, b
, handle
, form_name
, level
, NULL
);
2575 static bool test_EnumForms(struct torture_context
*tctx
,
2576 struct dcerpc_binding_handle
*b
,
2577 struct policy_handle
*handle
,
2581 union spoolss_FormInfo
**info_p
)
2583 struct spoolss_EnumForms r
;
2586 union spoolss_FormInfo
*info
;
2588 r
.in
.handle
= handle
;
2592 r
.out
.needed
= &needed
;
2593 r
.out
.count
= &count
;
2596 torture_comment(tctx
, "Testing EnumForms level %d\n", r
.in
.level
);
2598 torture_assert_ntstatus_ok(tctx
,
2599 dcerpc_spoolss_EnumForms_r(b
, tctx
, &r
),
2600 "EnumForms failed");
2602 if ((r
.in
.level
== 2) && (W_ERROR_EQUAL(r
.out
.result
, WERR_INVALID_LEVEL
))) {
2603 torture_skip(tctx
, "EnumForms level 2 not supported");
2606 if (print_server
&& W_ERROR_EQUAL(r
.out
.result
, WERR_INVALID_HANDLE
)) {
2607 torture_fail(tctx
, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2610 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2611 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
2612 r
.in
.buffer
= &blob
;
2613 r
.in
.offered
= needed
;
2615 torture_assert_ntstatus_ok(tctx
,
2616 dcerpc_spoolss_EnumForms_r(b
, tctx
, &r
),
2617 "EnumForms failed");
2619 torture_assert(tctx
, info
, "No forms returned");
2622 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumForms failed");
2624 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms
, info
, r
.in
.level
, count
, needed
, 4);
2636 static bool test_EnumForms_all(struct torture_context
*tctx
,
2637 struct dcerpc_binding_handle
*b
,
2638 struct policy_handle
*handle
,
2641 uint32_t levels
[] = { 1, 2 };
2644 for (i
=0; i
<ARRAY_SIZE(levels
); i
++) {
2647 union spoolss_FormInfo
*info
= NULL
;
2649 torture_assert(tctx
,
2650 test_EnumForms(tctx
, b
, handle
, print_server
, levels
[i
], &count
, &info
),
2651 "failed to enum forms");
2653 for (j
= 0; j
< count
; j
++) {
2654 if (!print_server
) {
2655 torture_assert(tctx
,
2656 test_GetForm(tctx
, b
, handle
, info
[j
].info1
.form_name
, levels
[i
]),
2657 "failed to get form");
2665 static bool test_EnumForms_find_one(struct torture_context
*tctx
,
2666 struct dcerpc_binding_handle
*b
,
2667 struct policy_handle
*handle
,
2669 const char *form_name
)
2671 union spoolss_FormInfo
*info
= NULL
;
2676 torture_assert(tctx
,
2677 test_EnumForms(tctx
, b
, handle
, print_server
, 1, &count
, &info
),
2678 "failed to enumerate forms");
2680 for (i
=0; i
<count
; i
++) {
2681 if (strequal(form_name
, info
[i
].info1
.form_name
)) {
2690 static bool test_DeleteForm(struct torture_context
*tctx
,
2691 struct dcerpc_binding_handle
*b
,
2692 struct policy_handle
*handle
,
2693 const char *form_name
,
2694 WERROR expected_result
)
2696 struct spoolss_DeleteForm r
;
2698 r
.in
.handle
= handle
;
2699 r
.in
.form_name
= form_name
;
2701 torture_comment(tctx
, "Testing DeleteForm(%s)\n", form_name
);
2703 torture_assert_ntstatus_ok(tctx
,
2704 dcerpc_spoolss_DeleteForm_r(b
, tctx
, &r
),
2705 "DeleteForm failed");
2706 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
2707 "DeleteForm gave unexpected result");
2708 if (W_ERROR_IS_OK(r
.out
.result
)) {
2709 torture_assert_ntstatus_ok(tctx
,
2710 dcerpc_spoolss_DeleteForm_r(b
, tctx
, &r
),
2711 "2nd DeleteForm failed");
2712 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_FORM_NAME
,
2713 "2nd DeleteForm failed");
2719 static bool test_AddForm(struct torture_context
*tctx
,
2720 struct dcerpc_binding_handle
*b
,
2721 struct policy_handle
*handle
,
2723 union spoolss_AddFormInfo
*info
,
2724 WERROR expected_result
)
2726 struct spoolss_AddForm r
;
2727 struct spoolss_AddFormInfoCtr info_ctr
;
2729 info_ctr
.level
= level
;
2730 info_ctr
.info
= *info
;
2733 torture_skip(tctx
, "only level 1 supported");
2736 r
.in
.handle
= handle
;
2737 r
.in
.info_ctr
= &info_ctr
;
2739 torture_comment(tctx
, "Testing AddForm(%s) level %d, type %d\n",
2740 r
.in
.info_ctr
->info
.info1
->form_name
, level
,
2741 r
.in
.info_ctr
->info
.info1
->flags
);
2743 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_AddForm_r(b
, tctx
, &r
),
2745 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
2746 "AddForm gave unexpected result");
2748 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_AddForm_r(b
, tctx
, &r
),
2749 "2nd AddForm failed");
2750 if (W_ERROR_EQUAL(expected_result
, WERR_INVALID_PARAMETER
)) {
2751 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAMETER
,
2752 "2nd AddForm gave unexpected result");
2754 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_FILE_EXISTS
,
2755 "2nd AddForm gave unexpected result");
2761 static bool test_SetForm(struct torture_context
*tctx
,
2762 struct dcerpc_binding_handle
*b
,
2763 struct policy_handle
*handle
,
2764 const char *form_name
,
2766 union spoolss_AddFormInfo
*info
)
2768 struct spoolss_SetForm r
;
2769 struct spoolss_AddFormInfoCtr info_ctr
;
2771 info_ctr
.level
= level
;
2772 info_ctr
.info
= *info
;
2774 r
.in
.handle
= handle
;
2775 r
.in
.form_name
= form_name
;
2776 r
.in
.info_ctr
= &info_ctr
;
2778 torture_comment(tctx
, "Testing SetForm(%s) level %d\n",
2781 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetForm_r(b
, tctx
, &r
),
2784 torture_assert_werr_ok(tctx
, r
.out
.result
,
2790 static bool test_GetForm_winreg(struct torture_context
*tctx
,
2791 struct dcerpc_binding_handle
*b
,
2792 struct policy_handle
*handle
,
2793 const char *key_name
,
2794 const char *form_name
,
2795 enum winreg_Type
*w_type
,
2800 static bool test_Forms_args(struct torture_context
*tctx
,
2801 struct dcerpc_binding_handle
*b
,
2802 struct policy_handle
*handle
,
2804 const char *printer_name
,
2805 struct dcerpc_binding_handle
*winreg_handle
,
2806 struct policy_handle
*hive_handle
,
2807 const char *form_name
,
2808 struct spoolss_AddFormInfo1
*info1
,
2809 WERROR expected_add_result
,
2810 WERROR expected_delete_result
)
2812 union spoolss_FormInfo info
;
2813 union spoolss_AddFormInfo add_info
;
2815 enum winreg_Type w_type
;
2820 add_info
.info1
= info1
;
2822 torture_assert(tctx
,
2823 test_AddForm(tctx
, b
, handle
, 1, &add_info
, expected_add_result
),
2824 "failed to add form");
2826 if (winreg_handle
&& hive_handle
&& W_ERROR_IS_OK(expected_add_result
)) {
2828 struct spoolss_FormInfo1 i1
;
2830 torture_assert(tctx
,
2831 test_GetForm_winreg(tctx
, winreg_handle
, hive_handle
, TOP_LEVEL_CONTROL_FORMS_KEY
, form_name
, &w_type
, &w_size
, &w_length
, &w_data
),
2832 "failed to get form via winreg");
2834 i1
.size
.width
= IVAL(w_data
, 0);
2835 i1
.size
.height
= IVAL(w_data
, 4);
2836 i1
.area
.left
= IVAL(w_data
, 8);
2837 i1
.area
.top
= IVAL(w_data
, 12);
2838 i1
.area
.right
= IVAL(w_data
, 16);
2839 i1
.area
.bottom
= IVAL(w_data
, 20);
2840 /* skip index here */
2841 i1
.flags
= IVAL(w_data
, 28);
2843 torture_assert_int_equal(tctx
, w_type
, REG_BINARY
, "unexpected type");
2844 torture_assert_int_equal(tctx
, w_size
, 0x20, "unexpected size");
2845 torture_assert_int_equal(tctx
, w_length
, 0x20, "unexpected length");
2846 torture_assert_int_equal(tctx
, i1
.size
.width
, add_info
.info1
->size
.width
, "width mismatch");
2847 torture_assert_int_equal(tctx
, i1
.size
.height
, add_info
.info1
->size
.height
, "height mismatch");
2848 torture_assert_int_equal(tctx
, i1
.area
.left
, add_info
.info1
->area
.left
, "left mismatch");
2849 torture_assert_int_equal(tctx
, i1
.area
.top
, add_info
.info1
->area
.top
, "top mismatch");
2850 torture_assert_int_equal(tctx
, i1
.area
.right
, add_info
.info1
->area
.right
, "right mismatch");
2851 torture_assert_int_equal(tctx
, i1
.area
.bottom
, add_info
.info1
->area
.bottom
, "bottom mismatch");
2852 torture_assert_int_equal(tctx
, i1
.flags
, add_info
.info1
->flags
, "flags mismatch");
2855 if (!print_server
&& W_ERROR_IS_OK(expected_add_result
)) {
2856 torture_assert(tctx
,
2857 test_GetForm_args(tctx
, b
, handle
, form_name
, 1, &info
),
2858 "failed to get added form");
2860 torture_assert_int_equal(tctx
, info
.info1
.size
.width
, add_info
.info1
->size
.width
, "width mismatch");
2861 torture_assert_int_equal(tctx
, info
.info1
.size
.height
, add_info
.info1
->size
.height
, "height mismatch");
2862 torture_assert_int_equal(tctx
, info
.info1
.area
.left
, add_info
.info1
->area
.left
, "left mismatch");
2863 torture_assert_int_equal(tctx
, info
.info1
.area
.top
, add_info
.info1
->area
.top
, "top mismatch");
2864 torture_assert_int_equal(tctx
, info
.info1
.area
.right
, add_info
.info1
->area
.right
, "right mismatch");
2865 torture_assert_int_equal(tctx
, info
.info1
.area
.bottom
, add_info
.info1
->area
.bottom
, "bottom mismatch");
2866 torture_assert_int_equal(tctx
, info
.info1
.flags
, add_info
.info1
->flags
, "flags mismatch");
2868 if (winreg_handle
&& hive_handle
) {
2870 struct spoolss_FormInfo1 i1
;
2872 i1
.size
.width
= IVAL(w_data
, 0);
2873 i1
.size
.height
= IVAL(w_data
, 4);
2874 i1
.area
.left
= IVAL(w_data
, 8);
2875 i1
.area
.top
= IVAL(w_data
, 12);
2876 i1
.area
.right
= IVAL(w_data
, 16);
2877 i1
.area
.bottom
= IVAL(w_data
, 20);
2878 /* skip index here */
2879 i1
.flags
= IVAL(w_data
, 28);
2881 torture_assert_int_equal(tctx
, i1
.size
.width
, info
.info1
.size
.width
, "width mismatch");
2882 torture_assert_int_equal(tctx
, i1
.size
.height
, info
.info1
.size
.height
, "height mismatch");
2883 torture_assert_int_equal(tctx
, i1
.area
.left
, info
.info1
.area
.left
, "left mismatch");
2884 torture_assert_int_equal(tctx
, i1
.area
.top
, info
.info1
.area
.top
, "top mismatch");
2885 torture_assert_int_equal(tctx
, i1
.area
.right
, info
.info1
.area
.right
, "right mismatch");
2886 torture_assert_int_equal(tctx
, i1
.area
.bottom
, info
.info1
.area
.bottom
, "bottom mismatch");
2887 torture_assert_int_equal(tctx
, i1
.flags
, info
.info1
.flags
, "flags mismatch");
2890 add_info
.info1
->size
.width
= 1234;
2892 torture_assert(tctx
,
2893 test_SetForm(tctx
, b
, handle
, form_name
, 1, &add_info
),
2894 "failed to set form");
2895 torture_assert(tctx
,
2896 test_GetForm_args(tctx
, b
, handle
, form_name
, 1, &info
),
2897 "failed to get setted form");
2899 torture_assert_int_equal(tctx
, info
.info1
.size
.width
, add_info
.info1
->size
.width
, "width mismatch");
2902 if (!W_ERROR_EQUAL(expected_add_result
, WERR_INVALID_PARAMETER
)) {
2903 torture_assert(tctx
,
2904 test_EnumForms_find_one(tctx
, b
, handle
, print_server
, form_name
),
2905 "Newly added form not found in enum call");
2908 torture_assert(tctx
,
2909 test_DeleteForm(tctx
, b
, handle
, form_name
, expected_delete_result
),
2910 "failed to delete form");
2915 static bool test_Forms(struct torture_context
*tctx
,
2916 struct dcerpc_binding_handle
*b
,
2917 struct policy_handle
*handle
,
2919 const char *printer_name
,
2920 struct dcerpc_binding_handle
*winreg_handle
,
2921 struct policy_handle
*hive_handle
)
2923 const struct spoolss_FormSize size
= {
2927 const struct spoolss_FormArea area
= {
2936 struct spoolss_AddFormInfo1 info1
;
2937 WERROR expected_add_result
;
2938 WERROR expected_delete_result
;
2942 .flags
= SPOOLSS_FORM_USER
,
2943 .form_name
= "testform_user",
2947 .expected_add_result
= WERR_OK
,
2948 .expected_delete_result
= WERR_OK
2951 weird, we can add a builtin form but we can never remove it
2956 .flags = SPOOLSS_FORM_BUILTIN,
2957 .form_name = "testform_builtin",
2961 .expected_add_result = WERR_OK,
2962 .expected_delete_result = WERR_INVALID_PARAMETER,
2967 .flags
= SPOOLSS_FORM_PRINTER
,
2968 .form_name
= "testform_printer",
2972 .expected_add_result
= WERR_OK
,
2973 .expected_delete_result
= WERR_OK
2977 .flags
= SPOOLSS_FORM_USER
,
2978 .form_name
= "Letter",
2982 .expected_add_result
= WERR_FILE_EXISTS
,
2983 .expected_delete_result
= WERR_INVALID_PARAMETER
2987 .flags
= SPOOLSS_FORM_BUILTIN
,
2988 .form_name
= "Letter",
2992 .expected_add_result
= WERR_FILE_EXISTS
,
2993 .expected_delete_result
= WERR_INVALID_PARAMETER
2997 .flags
= SPOOLSS_FORM_PRINTER
,
2998 .form_name
= "Letter",
3002 .expected_add_result
= WERR_FILE_EXISTS
,
3003 .expected_delete_result
= WERR_INVALID_PARAMETER
3008 .form_name
= "invalid_flags",
3012 .expected_add_result
= WERR_INVALID_PARAMETER
,
3013 .expected_delete_result
= WERR_INVALID_FORM_NAME
3018 for (i
=0; i
< ARRAY_SIZE(forms
); i
++) {
3019 torture_assert(tctx
,
3020 test_Forms_args(tctx
, b
, handle
, print_server
, printer_name
,
3021 winreg_handle
, hive_handle
,
3022 forms
[i
].info1
.form_name
,
3024 forms
[i
].expected_add_result
,
3025 forms
[i
].expected_delete_result
),
3026 talloc_asprintf(tctx
, "failed to test form '%s'", forms
[i
].info1
.form_name
));
3032 static bool test_EnumPorts_old(struct torture_context
*tctx
,
3035 struct test_spoolss_context
*ctx
=
3036 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
3039 struct spoolss_EnumPorts r
;
3042 union spoolss_PortInfo
*info
;
3043 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
3044 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
3046 r
.in
.servername
= talloc_asprintf(tctx
, "\\\\%s",
3047 dcerpc_server_name(p
));
3051 r
.out
.needed
= &needed
;
3052 r
.out
.count
= &count
;
3055 torture_comment(tctx
, "Testing EnumPorts\n");
3057 status
= dcerpc_spoolss_EnumPorts_r(b
, tctx
, &r
);
3059 torture_assert_ntstatus_ok(tctx
, status
, "EnumPorts failed");
3061 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
3062 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
3063 r
.in
.buffer
= &blob
;
3064 r
.in
.offered
= needed
;
3066 status
= dcerpc_spoolss_EnumPorts_r(b
, tctx
, &r
);
3067 torture_assert_ntstatus_ok(tctx
, status
, "EnumPorts failed");
3068 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
3070 torture_assert(tctx
, info
, "No ports returned");
3073 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
3075 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts
, info
, 2, count
, needed
, 4);
3080 static bool test_AddPort(struct torture_context
*tctx
,
3083 struct test_spoolss_context
*ctx
=
3084 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
3087 struct spoolss_AddPort r
;
3088 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
3089 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
3091 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s",
3092 dcerpc_server_name(p
));
3094 r
.in
.monitor_name
= "foo";
3096 torture_comment(tctx
, "Testing AddPort\n");
3098 status
= dcerpc_spoolss_AddPort_r(b
, tctx
, &r
);
3100 torture_assert_ntstatus_ok(tctx
, status
, "AddPort failed");
3102 /* win2k3 returns WERR_NOT_SUPPORTED */
3106 if (!W_ERROR_IS_OK(r
.out
.result
)) {
3107 printf("AddPort failed - %s\n", win_errstr(r
.out
.result
));
3116 static bool test_GetJob_args(struct torture_context
*tctx
,
3117 struct dcerpc_binding_handle
*b
,
3118 struct policy_handle
*handle
,
3121 union spoolss_JobInfo
*info_p
)
3124 struct spoolss_GetJob r
;
3125 union spoolss_JobInfo info
;
3128 r
.in
.handle
= handle
;
3129 r
.in
.job_id
= job_id
;
3133 r
.out
.needed
= &needed
;
3136 torture_comment(tctx
, "Testing GetJob(%d), level %d\n", job_id
, r
.in
.level
);
3138 status
= dcerpc_spoolss_GetJob_r(b
, tctx
, &r
);
3139 torture_assert_ntstatus_ok(tctx
, status
, "GetJob failed");
3141 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_LEVEL
, "Unexpected return code");
3144 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
3145 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
3146 r
.in
.buffer
= &blob
;
3147 r
.in
.offered
= needed
;
3149 status
= dcerpc_spoolss_GetJob_r(b
, tctx
, &r
);
3150 torture_assert_ntstatus_ok(tctx
, status
, "GetJob failed");
3153 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetJob failed");
3154 torture_assert(tctx
, r
.out
.info
, "No job info returned");
3156 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo
, r
.out
.info
, r
.in
.level
, needed
, 4);
3159 *info_p
= *r
.out
.info
;
3166 static bool test_GetJob(struct torture_context
*tctx
,
3167 struct dcerpc_binding_handle
*b
,
3168 struct policy_handle
*handle
,
3171 uint32_t levels
[] = {0, 1, 2 /* 3, 4 */};
3174 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
3175 torture_assert(tctx
,
3176 test_GetJob_args(tctx
, b
, handle
, job_id
, levels
[i
], NULL
),
3184 static bool test_SetJob(struct torture_context
*tctx
,
3185 struct dcerpc_binding_handle
*b
,
3186 struct policy_handle
*handle
,
3188 struct spoolss_JobInfoContainer
*ctr
,
3189 enum spoolss_JobControl command
)
3192 struct spoolss_SetJob r
;
3194 r
.in
.handle
= handle
;
3195 r
.in
.job_id
= job_id
;
3197 r
.in
.command
= command
;
3200 case SPOOLSS_JOB_CONTROL_PAUSE
:
3201 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id
);
3203 case SPOOLSS_JOB_CONTROL_RESUME
:
3204 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id
);
3206 case SPOOLSS_JOB_CONTROL_CANCEL
:
3207 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id
);
3209 case SPOOLSS_JOB_CONTROL_RESTART
:
3210 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id
);
3212 case SPOOLSS_JOB_CONTROL_DELETE
:
3213 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id
);
3215 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER
:
3216 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id
);
3218 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED
:
3219 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id
);
3221 case SPOOLSS_JOB_CONTROL_RETAIN
:
3222 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id
);
3224 case SPOOLSS_JOB_CONTROL_RELEASE
:
3225 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id
);
3228 torture_comment(tctx
, "Testing SetJob(%d)\n", job_id
);
3232 status
= dcerpc_spoolss_SetJob_r(b
, tctx
, &r
);
3233 torture_assert_ntstatus_ok(tctx
, status
, "SetJob failed");
3234 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetJob failed");
3239 static bool test_AddJob(struct torture_context
*tctx
,
3240 struct dcerpc_binding_handle
*b
,
3241 struct policy_handle
*handle
)
3244 struct spoolss_AddJob r
;
3248 r
.in
.handle
= handle
;
3250 r
.out
.needed
= &needed
;
3251 r
.in
.buffer
= r
.out
.buffer
= NULL
;
3253 torture_comment(tctx
, "Testing AddJob\n");
3255 status
= dcerpc_spoolss_AddJob_r(b
, tctx
, &r
);
3256 torture_assert_ntstatus_ok(tctx
, status
, "AddJob failed");
3257 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_LEVEL
, "AddJob failed");
3261 status
= dcerpc_spoolss_AddJob_r(b
, tctx
, &r
);
3262 torture_assert_ntstatus_ok(tctx
, status
, "AddJob failed");
3263 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAMETER
, "AddJob failed");
3269 static bool test_EnumJobs_args(struct torture_context
*tctx
,
3270 struct dcerpc_binding_handle
*b
,
3271 struct policy_handle
*handle
,
3273 WERROR werr_expected
,
3275 union spoolss_JobInfo
**info_p
)
3278 struct spoolss_EnumJobs r
;
3281 union spoolss_JobInfo
*info
;
3283 r
.in
.handle
= handle
;
3285 r
.in
.numjobs
= 0xffffffff;
3289 r
.out
.needed
= &needed
;
3290 r
.out
.count
= &count
;
3293 torture_comment(tctx
, "Testing EnumJobs level %d\n", level
);
3295 status
= dcerpc_spoolss_EnumJobs_r(b
, tctx
, &r
);
3297 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
3299 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
3300 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
3301 r
.in
.buffer
= &blob
;
3302 r
.in
.offered
= needed
;
3304 status
= dcerpc_spoolss_EnumJobs_r(b
, tctx
, &r
);
3306 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
3307 torture_assert_werr_equal(tctx
, r
.out
.result
, werr_expected
,
3309 torture_assert(tctx
, info
, "No jobs returned");
3311 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs
, *r
.out
.info
, r
.in
.level
, count
, needed
, 4);
3314 torture_assert_werr_equal(tctx
, r
.out
.result
, werr_expected
,
3328 static bool test_JobPropertiesEnum(struct torture_context
*tctx
,
3329 struct dcerpc_binding_handle
*b
,
3330 struct policy_handle
*handle
,
3333 struct spoolss_EnumJobNamedProperties r
;
3334 uint32_t pcProperties
= 0;
3335 struct spoolss_PrintNamedProperty
*ppProperties
= NULL
;
3337 r
.in
.hPrinter
= handle
;
3338 r
.in
.JobId
= job_id
;
3339 r
.out
.pcProperties
= &pcProperties
;
3340 r
.out
.ppProperties
= &ppProperties
;
3342 torture_comment(tctx
, "Testing EnumJobNamedProperties(%d)\n", job_id
);
3344 torture_assert_ntstatus_ok(tctx
,
3345 dcerpc_spoolss_EnumJobNamedProperties_r(b
, tctx
, &r
),
3346 "spoolss_EnumJobNamedProperties failed");
3347 torture_assert_werr_ok(tctx
, r
.out
.result
,
3348 "spoolss_EnumJobNamedProperties failed");
3353 static bool test_JobPropertySet(struct torture_context
*tctx
,
3354 struct dcerpc_binding_handle
*b
,
3355 struct policy_handle
*handle
,
3357 struct spoolss_PrintNamedProperty
*property
)
3359 struct spoolss_SetJobNamedProperty r
;
3361 r
.in
.hPrinter
= handle
;
3362 r
.in
.JobId
= job_id
;
3363 r
.in
.pProperty
= property
;
3365 torture_comment(tctx
, "Testing SetJobNamedProperty(%d) %s - %d\n",
3366 job_id
, property
->propertyName
,
3367 property
->propertyValue
.ePropertyType
);
3369 torture_assert_ntstatus_ok(tctx
,
3370 dcerpc_spoolss_SetJobNamedProperty_r(b
, tctx
, &r
),
3371 "spoolss_SetJobNamedProperty failed");
3372 torture_assert_werr_ok(tctx
, r
.out
.result
,
3373 "spoolss_SetJobNamedProperty failed");
3378 static bool test_JobPropertyGetValue(struct torture_context
*tctx
,
3379 struct dcerpc_binding_handle
*b
,
3380 struct policy_handle
*handle
,
3382 const char *property_name
,
3383 struct spoolss_PrintPropertyValue
*value
)
3385 struct spoolss_GetJobNamedPropertyValue r
;
3387 r
.in
.hPrinter
= handle
;
3388 r
.in
.JobId
= job_id
;
3389 r
.in
.pszName
= property_name
;
3390 r
.out
.pValue
= value
;
3392 torture_comment(tctx
, "Testing GetJobNamedPropertyValue(%d) %s\n",
3393 job_id
, property_name
);
3395 torture_assert_ntstatus_ok(tctx
,
3396 dcerpc_spoolss_GetJobNamedPropertyValue_r(b
, tctx
, &r
),
3397 "spoolss_GetJobNamedPropertyValue failed");
3398 torture_assert_werr_ok(tctx
, r
.out
.result
,
3399 "spoolss_GetJobNamedPropertyValue failed");
3404 static bool test_JobPropertyDelete(struct torture_context
*tctx
,
3405 struct dcerpc_binding_handle
*b
,
3406 struct policy_handle
*handle
,
3408 const char *property_name
)
3410 struct spoolss_DeleteJobNamedProperty r
;
3412 r
.in
.hPrinter
= handle
;
3413 r
.in
.JobId
= job_id
;
3414 r
.in
.pszName
= property_name
;
3416 torture_comment(tctx
, "Testing DeleteJobNamedProperty(%d) %s\n",
3417 job_id
, property_name
);
3419 torture_assert_ntstatus_ok(tctx
,
3420 dcerpc_spoolss_DeleteJobNamedProperty_r(b
, tctx
, &r
),
3421 "spoolss_DeleteJobNamedProperty failed");
3422 torture_assert_werr_ok(tctx
, r
.out
.result
,
3423 "spoolss_DeleteJobNamedProperty failed");
3428 static bool test_DoPrintTest_add_one_job_common(struct torture_context
*tctx
,
3429 struct dcerpc_binding_handle
*b
,
3430 struct policy_handle
*handle
,
3431 const char *document_name
,
3432 const char *datatype
,
3436 struct spoolss_StartDocPrinter s
;
3437 struct spoolss_DocumentInfoCtr info_ctr
;
3438 struct spoolss_DocumentInfo1 info1
;
3439 struct spoolss_StartPagePrinter sp
;
3440 struct spoolss_WritePrinter w
;
3441 struct spoolss_EndPagePrinter ep
;
3442 struct spoolss_EndDocPrinter e
;
3444 uint32_t num_written
;
3446 torture_comment(tctx
, "Testing StartDocPrinter\n");
3448 s
.in
.handle
= handle
;
3449 s
.in
.info_ctr
= &info_ctr
;
3450 s
.out
.job_id
= job_id
;
3452 info1
.document_name
= document_name
;
3453 info1
.output_file
= NULL
;
3454 info1
.datatype
= datatype
;
3457 info_ctr
.info
.info1
= &info1
;
3459 status
= dcerpc_spoolss_StartDocPrinter_r(b
, tctx
, &s
);
3460 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_StartDocPrinter failed");
3461 torture_assert_werr_ok(tctx
, s
.out
.result
, "StartDocPrinter failed");
3463 for (i
=1; i
< 4; i
++) {
3464 union spoolss_JobInfo ginfo
;
3467 torture_comment(tctx
, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i
, *job_id
);
3469 sp
.in
.handle
= handle
;
3471 status
= dcerpc_spoolss_StartPagePrinter_r(b
, tctx
, &sp
);
3472 torture_assert_ntstatus_ok(tctx
, status
,
3473 "dcerpc_spoolss_StartPagePrinter failed");
3474 torture_assert_werr_ok(tctx
, sp
.out
.result
, "StartPagePrinter failed");
3476 ok
= test_GetJob_args(tctx
, b
, handle
, *job_id
, 1, &ginfo
);
3478 torture_comment(tctx
, "test_GetJob failed for JobId[%d]\n", *job_id
);
3481 torture_comment(tctx
, "Testing WritePrinter: Page[%d], JobId[%d]\n", i
, *job_id
);
3483 w
.in
.handle
= handle
;
3484 w
.in
.data
= data_blob_string_const(talloc_asprintf(tctx
,"TortureTestPage: %d\nData\n",i
));
3485 w
.out
.num_written
= &num_written
;
3487 status
= dcerpc_spoolss_WritePrinter_r(b
, tctx
, &w
);
3488 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_WritePrinter failed");
3489 torture_assert_werr_ok(tctx
, w
.out
.result
, "WritePrinter failed");
3491 torture_comment(tctx
, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i
, *job_id
);
3493 ep
.in
.handle
= handle
;
3495 status
= dcerpc_spoolss_EndPagePrinter_r(b
, tctx
, &ep
);
3496 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndPagePrinter failed");
3497 torture_assert_werr_ok(tctx
, ep
.out
.result
, "EndPagePrinter failed");
3500 torture_comment(tctx
, "Testing EndDocPrinter: JobId[%d]\n", *job_id
);
3502 e
.in
.handle
= handle
;
3504 status
= dcerpc_spoolss_EndDocPrinter_r(b
, tctx
, &e
);
3505 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndDocPrinter failed");
3506 torture_assert_werr_ok(tctx
, e
.out
.result
, "EndDocPrinter failed");
3511 static bool test_DoPrintTest_add_one_job(struct torture_context
*tctx
,
3512 struct dcerpc_binding_handle
*b
,
3513 struct policy_handle
*handle
,
3514 const char *document_name
,
3517 test_DoPrintTest_add_one_job_common(tctx
, b
, handle
, document_name
, "RAW", job_id
);
3522 static bool test_DoPrintTest_add_one_job_v4(struct torture_context
*tctx
,
3523 struct dcerpc_binding_handle
*b
,
3524 struct policy_handle
*handle
,
3525 const char *document_name
,
3528 test_DoPrintTest_add_one_job_common(tctx
, b
, handle
, document_name
, "XPS_PASS", job_id
);
3534 static bool test_DoPrintTest_check_jobs(struct torture_context
*tctx
,
3535 struct dcerpc_binding_handle
*b
,
3536 struct policy_handle
*handle
,
3541 union spoolss_JobInfo
*info
= NULL
;
3544 torture_assert(tctx
,
3545 test_AddJob(tctx
, b
, handle
),
3548 torture_assert(tctx
,
3549 test_EnumJobs_args(tctx
, b
, handle
, 1, WERR_OK
, &count
, &info
),
3550 "EnumJobs level 1 failed");
3552 torture_assert_int_equal(tctx
, count
, num_jobs
, "unexpected number of jobs in queue");
3554 for (i
=0; i
< num_jobs
; i
++) {
3555 union spoolss_JobInfo ginfo
;
3556 const char *document_name
;
3557 const char *new_document_name
= "any_other_docname";
3558 struct spoolss_JobInfoContainer ctr
;
3559 struct spoolss_SetJobInfo1 info1
;
3561 torture_assert_int_equal(tctx
, info
[i
].info1
.job_id
, job_ids
[i
], "job id mismatch");
3563 torture_assert(tctx
,
3564 test_GetJob_args(tctx
, b
, handle
, info
[i
].info1
.job_id
, 1, &ginfo
),
3565 "failed to call test_GetJob");
3567 torture_assert_int_equal(tctx
, ginfo
.info1
.job_id
, info
[i
].info1
.job_id
, "job id mismatch");
3569 document_name
= ginfo
.info1
.document_name
;
3571 info1
.job_id
= ginfo
.info1
.job_id
;
3572 info1
.printer_name
= ginfo
.info1
.printer_name
;
3573 info1
.server_name
= ginfo
.info1
.server_name
;
3574 info1
.user_name
= ginfo
.info1
.user_name
;
3575 info1
.document_name
= new_document_name
;
3576 info1
.data_type
= ginfo
.info1
.data_type
;
3577 info1
.text_status
= ginfo
.info1
.text_status
;
3578 info1
.status
= ginfo
.info1
.status
;
3579 info1
.priority
= ginfo
.info1
.priority
;
3580 info1
.position
= ginfo
.info1
.position
;
3581 info1
.total_pages
= ginfo
.info1
.total_pages
;
3582 info1
.pages_printed
= ginfo
.info1
.pages_printed
;
3583 info1
.submitted
= ginfo
.info1
.submitted
;
3586 ctr
.info
.info1
= &info1
;
3588 torture_assert(tctx
,
3589 test_SetJob(tctx
, b
, handle
, info
[i
].info1
.job_id
, &ctr
, 0),
3590 "failed to call test_SetJob level 1");
3592 torture_assert(tctx
,
3593 test_GetJob_args(tctx
, b
, handle
, info
[i
].info1
.job_id
, 1, &ginfo
),
3594 "failed to call test_GetJob");
3596 if (strequal(ginfo
.info1
.document_name
, document_name
)) {
3597 torture_warning(tctx
,
3598 "document_name did *NOT* change from '%s' to '%s'\n",
3599 document_name
, new_document_name
);
3603 for (i
=0; i
< num_jobs
; i
++) {
3604 if (!test_SetJob(tctx
, b
, handle
, info
[i
].info1
.job_id
, NULL
, SPOOLSS_JOB_CONTROL_PAUSE
)) {
3605 torture_warning(tctx
, "failed to pause printjob\n");
3607 if (!test_SetJob(tctx
, b
, handle
, info
[i
].info1
.job_id
, NULL
, SPOOLSS_JOB_CONTROL_RESUME
)) {
3608 torture_warning(tctx
, "failed to resume printjob\n");
3615 static bool test_DoPrintTest(struct torture_context
*tctx
,
3616 struct dcerpc_binding_handle
*b
,
3617 struct policy_handle
*handle
)
3620 uint32_t num_jobs
= 8;
3624 torture_comment(tctx
, "Testing real print operations\n");
3626 job_ids
= talloc_zero_array(tctx
, uint32_t, num_jobs
);
3628 for (i
=0; i
< num_jobs
; i
++) {
3629 ret
&= test_DoPrintTest_add_one_job(tctx
, b
, handle
, "TorturePrintJob", &job_ids
[i
]);
3632 for (i
=0; i
< num_jobs
; i
++) {
3633 ret
&= test_SetJob(tctx
, b
, handle
, job_ids
[i
], NULL
, SPOOLSS_JOB_CONTROL_DELETE
);
3636 for (i
=0; i
< num_jobs
; i
++) {
3637 ret
&= test_DoPrintTest_add_one_job_v4(tctx
, b
, handle
, "TorturePrintJob v4", &job_ids
[i
]);
3640 for (i
=0; i
< num_jobs
; i
++) {
3641 ret
&= test_SetJob(tctx
, b
, handle
, job_ids
[i
], NULL
, SPOOLSS_JOB_CONTROL_DELETE
);
3645 torture_comment(tctx
, "real print operations test succeeded\n\n");
3651 static bool test_DoPrintTest_extended(struct torture_context
*tctx
,
3652 struct dcerpc_binding_handle
*b
,
3653 struct policy_handle
*handle
)
3656 uint32_t num_jobs
= 8;
3659 torture_comment(tctx
, "Testing real print operations (extended)\n");
3661 job_ids
= talloc_zero_array(tctx
, uint32_t, num_jobs
);
3663 for (i
=0; i
< num_jobs
; i
++) {
3664 ret
&= test_DoPrintTest_add_one_job(tctx
, b
, handle
, "TorturePrintJob", &job_ids
[i
]);
3667 ret
&= test_DoPrintTest_check_jobs(tctx
, b
, handle
, num_jobs
, job_ids
);
3669 for (i
=0; i
< num_jobs
; i
++) {
3670 ret
&= test_SetJob(tctx
, b
, handle
, job_ids
[i
], NULL
, SPOOLSS_JOB_CONTROL_DELETE
);
3674 torture_comment(tctx
, "real print operations (extended) test succeeded\n\n");
3680 static bool test_JobPrintProperties_equal(struct torture_context
*tctx
,
3681 struct spoolss_PrintPropertyValue
*got
,
3682 struct spoolss_PrintNamedProperty
*exp
)
3684 torture_assert_int_equal(tctx
,
3686 exp
->propertyValue
.ePropertyType
,
3689 switch (exp
->propertyValue
.ePropertyType
) {
3690 case kRpcPropertyTypeString
:
3691 torture_assert_str_equal(tctx
,
3692 got
->value
.propertyString
,
3693 exp
->propertyValue
.value
.propertyString
,
3696 case kRpcPropertyTypeInt32
:
3697 torture_assert_int_equal(tctx
,
3698 got
->value
.propertyInt32
,
3699 exp
->propertyValue
.value
.propertyInt32
,
3702 case kRpcPropertyTypeInt64
:
3703 torture_assert_u64_equal(tctx
,
3704 got
->value
.propertyInt64
,
3705 exp
->propertyValue
.value
.propertyInt64
,
3708 case kRpcPropertyTypeByte
:
3709 torture_assert_int_equal(tctx
,
3710 got
->value
.propertyByte
,
3711 exp
->propertyValue
.value
.propertyByte
,
3714 case kRpcPropertyTypeBuffer
:
3715 torture_assert_int_equal(tctx
,
3716 got
->value
.propertyBlob
.cbBuf
,
3717 exp
->propertyValue
.value
.propertyBlob
.cbBuf
,
3718 "propertyBlob.cbBuf");
3719 torture_assert_mem_equal(tctx
,
3720 got
->value
.propertyBlob
.pBuf
,
3721 exp
->propertyValue
.value
.propertyBlob
.pBuf
,
3722 exp
->propertyValue
.value
.propertyBlob
.cbBuf
,
3723 "propertyBlob.pBuf");
3732 static bool test_JobPrintProperties(struct torture_context
*tctx
,
3733 struct dcerpc_binding_handle
*b
,
3734 struct policy_handle
*handle
,
3737 struct spoolss_PrintNamedProperty in
;
3738 struct spoolss_PrintPropertyValue out
;
3740 DATA_BLOB blob
= data_blob_string_const("blob");
3742 const char *property_name
;
3743 enum spoolss_EPrintPropertyType type
;
3744 union spoolss_PrintPropertyValueUnion value
;
3745 WERROR expected_result
;
3748 .property_name
= "torture_property_string",
3749 .type
= kRpcPropertyTypeString
,
3750 .value
.propertyString
= "torture_property_value_string",
3752 .property_name
= "torture_property_int32",
3753 .type
= kRpcPropertyTypeInt32
,
3754 .value
.propertyInt32
= 42,
3756 .property_name
= "torture_property_int64",
3757 .type
= kRpcPropertyTypeInt64
,
3758 .value
.propertyInt64
= 0xaffe,
3760 .property_name
= "torture_property_byte",
3761 .type
= kRpcPropertyTypeByte
,
3762 .value
.propertyByte
= 0xab,
3764 .property_name
= "torture_property_buffer",
3765 .type
= kRpcPropertyTypeBuffer
,
3766 .value
.propertyBlob
.cbBuf
= blob
.length
,
3767 .value
.propertyBlob
.pBuf
= blob
.data
,
3771 torture_assert(tctx
,
3772 test_JobPropertiesEnum(tctx
, b
, handle
, job_id
),
3773 "failed to enum properties");
3775 for (i
=0; i
<ARRAY_SIZE(tests
); i
++) {
3777 in
.propertyName
= tests
[i
].property_name
;
3778 in
.propertyValue
.ePropertyType
= tests
[i
].type
;
3779 in
.propertyValue
.value
= tests
[i
].value
;
3781 torture_assert(tctx
,
3782 test_JobPropertySet(tctx
, b
, handle
, job_id
, &in
),
3783 "failed to set property");
3785 torture_assert(tctx
,
3786 test_JobPropertyGetValue(tctx
, b
, handle
, job_id
, in
.propertyName
, &out
),
3787 "failed to get property");
3789 torture_assert(tctx
,
3790 test_JobPrintProperties_equal(tctx
, &out
, &in
),
3791 "property unequal");
3793 torture_assert(tctx
,
3794 test_JobPropertiesEnum(tctx
, b
, handle
, job_id
),
3795 "failed to enum properties");
3797 torture_assert(tctx
,
3798 test_JobPropertyDelete(tctx
, b
, handle
, job_id
, in
.propertyName
),
3799 "failed to delete job property");
3802 torture_assert(tctx
,
3803 test_JobPropertiesEnum(tctx
, b
, handle
, job_id
),
3804 "failed to enum properties");
3809 static bool test_DoPrintTest_properties(struct torture_context
*tctx
,
3810 struct dcerpc_binding_handle
*b
,
3811 struct policy_handle
*handle
)
3813 uint32_t num_jobs
= 8;
3816 torture_comment(tctx
, "Testing real print operations (properties)\n");
3818 job_ids
= talloc_zero_array(tctx
, uint32_t, num_jobs
);
3820 for (i
=0; i
< num_jobs
; i
++) {
3821 torture_assert(tctx
,
3822 test_DoPrintTest_add_one_job(tctx
, b
, handle
, "TorturePrintJob", &job_ids
[i
]),
3823 "failed to create print job");
3826 for (i
=0; i
< num_jobs
; i
++) {
3827 torture_assert(tctx
,
3828 test_JobPrintProperties(tctx
, b
, handle
, job_ids
[i
]),
3829 "failed to test job properties");
3833 for (i
=0; i
< num_jobs
; i
++) {
3834 torture_assert(tctx
,
3835 test_SetJob(tctx
, b
, handle
, job_ids
[i
], NULL
, SPOOLSS_JOB_CONTROL_DELETE
),
3836 "failed to delete printjob");
3839 torture_comment(tctx
, "real print operations (properties) test succeeded\n\n");
3844 static bool test_PausePrinter(struct torture_context
*tctx
,
3845 struct dcerpc_binding_handle
*b
,
3846 struct policy_handle
*handle
)
3849 struct spoolss_SetPrinter r
;
3850 struct spoolss_SetPrinterInfoCtr info_ctr
;
3851 struct spoolss_DevmodeContainer devmode_ctr
;
3852 struct sec_desc_buf secdesc_ctr
;
3855 info_ctr
.info
.info0
= NULL
;
3857 ZERO_STRUCT(devmode_ctr
);
3858 ZERO_STRUCT(secdesc_ctr
);
3860 r
.in
.handle
= handle
;
3861 r
.in
.info_ctr
= &info_ctr
;
3862 r
.in
.devmode_ctr
= &devmode_ctr
;
3863 r
.in
.secdesc_ctr
= &secdesc_ctr
;
3864 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
3866 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3868 status
= dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
);
3870 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
3872 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
3877 static bool test_ResumePrinter(struct torture_context
*tctx
,
3878 struct dcerpc_binding_handle
*b
,
3879 struct policy_handle
*handle
)
3882 struct spoolss_SetPrinter r
;
3883 struct spoolss_SetPrinterInfoCtr info_ctr
;
3884 struct spoolss_DevmodeContainer devmode_ctr
;
3885 struct sec_desc_buf secdesc_ctr
;
3888 info_ctr
.info
.info0
= NULL
;
3890 ZERO_STRUCT(devmode_ctr
);
3891 ZERO_STRUCT(secdesc_ctr
);
3893 r
.in
.handle
= handle
;
3894 r
.in
.info_ctr
= &info_ctr
;
3895 r
.in
.devmode_ctr
= &devmode_ctr
;
3896 r
.in
.secdesc_ctr
= &secdesc_ctr
;
3897 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
3899 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3901 status
= dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
);
3903 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
3905 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
3910 static bool test_printer_purge(struct torture_context
*tctx
,
3911 struct dcerpc_binding_handle
*b
,
3912 struct policy_handle
*handle
)
3915 struct spoolss_SetPrinter r
;
3916 struct spoolss_SetPrinterInfoCtr info_ctr
;
3917 struct spoolss_DevmodeContainer devmode_ctr
;
3918 struct sec_desc_buf secdesc_ctr
;
3921 info_ctr
.info
.info0
= NULL
;
3923 ZERO_STRUCT(devmode_ctr
);
3924 ZERO_STRUCT(secdesc_ctr
);
3926 r
.in
.handle
= handle
;
3927 r
.in
.info_ctr
= &info_ctr
;
3928 r
.in
.devmode_ctr
= &devmode_ctr
;
3929 r
.in
.secdesc_ctr
= &secdesc_ctr
;
3930 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_PURGE
;
3932 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PURGE\n");
3934 status
= dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
);
3935 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
3936 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
3941 static bool test_GetPrinterData_checktype(struct torture_context
*tctx
,
3942 struct dcerpc_binding_handle
*b
,
3943 struct policy_handle
*handle
,
3944 const char *value_name
,
3945 enum winreg_Type
*expected_type
,
3946 enum winreg_Type
*type_p
,
3951 struct spoolss_GetPrinterData r
;
3953 enum winreg_Type type
;
3954 union spoolss_PrinterData data
;
3956 r
.in
.handle
= handle
;
3957 r
.in
.value_name
= value_name
;
3959 r
.out
.needed
= &needed
;
3961 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
3963 torture_comment(tctx
, "Testing GetPrinterData(%s)\n", r
.in
.value_name
);
3965 status
= dcerpc_spoolss_GetPrinterData_r(b
, tctx
, &r
);
3966 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
3968 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
3969 if (expected_type
) {
3970 torture_assert_int_equal(tctx
, type
, *expected_type
, "unexpected type");
3972 r
.in
.offered
= needed
;
3973 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
3974 status
= dcerpc_spoolss_GetPrinterData_r(b
, tctx
, &r
);
3975 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
3978 torture_assert_werr_ok(tctx
, r
.out
.result
,
3979 talloc_asprintf(tctx
, "GetPrinterData(%s) failed", r
.in
.value_name
));
3981 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData
, &data
, type
, needed
, 1);
3988 *data_p
= r
.out
.data
;
3998 static bool test_GetPrinterData(struct torture_context
*tctx
,
3999 struct dcerpc_binding_handle
*b
,
4000 struct policy_handle
*handle
,
4001 const char *value_name
,
4002 enum winreg_Type
*type_p
,
4006 return test_GetPrinterData_checktype(tctx
, b
, handle
, value_name
,
4007 NULL
, type_p
, data_p
, needed_p
);
4010 static bool test_GetPrinterDataEx_checktype(struct torture_context
*tctx
,
4011 struct dcerpc_pipe
*p
,
4012 struct policy_handle
*handle
,
4013 const char *key_name
,
4014 const char *value_name
,
4015 enum winreg_Type
*expected_type
,
4016 enum winreg_Type
*type_p
,
4021 struct spoolss_GetPrinterDataEx r
;
4022 enum winreg_Type type
;
4024 union spoolss_PrinterData data
;
4025 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4027 r
.in
.handle
= handle
;
4028 r
.in
.key_name
= key_name
;
4029 r
.in
.value_name
= value_name
;
4032 r
.out
.needed
= &needed
;
4033 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
4035 torture_comment(tctx
, "Testing GetPrinterDataEx(%s - %s)\n",
4036 r
.in
.key_name
, r
.in
.value_name
);
4038 status
= dcerpc_spoolss_GetPrinterDataEx_r(b
, tctx
, &r
);
4039 if (!NT_STATUS_IS_OK(status
)) {
4040 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
4041 torture_skip(tctx
, "GetPrinterDataEx not supported by server\n");
4043 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
4046 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
4047 if (expected_type
) {
4048 torture_assert_int_equal(tctx
, type
, *expected_type
, "unexpected type");
4050 r
.in
.offered
= needed
;
4051 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
4052 status
= dcerpc_spoolss_GetPrinterDataEx_r(b
, tctx
, &r
);
4053 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
4056 torture_assert_werr_ok(tctx
, r
.out
.result
,
4057 talloc_asprintf(tctx
, "GetPrinterDataEx(%s - %s) failed", r
.in
.key_name
, r
.in
.value_name
));
4059 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData
, &data
, type
, needed
, 1);
4066 *data_p
= r
.out
.data
;
4076 static bool test_GetPrinterDataEx(struct torture_context
*tctx
,
4077 struct dcerpc_pipe
*p
,
4078 struct policy_handle
*handle
,
4079 const char *key_name
,
4080 const char *value_name
,
4081 enum winreg_Type
*type_p
,
4085 return test_GetPrinterDataEx_checktype(tctx
, p
, handle
, key_name
, value_name
,
4086 NULL
, type_p
, data_p
, needed_p
);
4089 static bool test_get_environment(struct torture_context
*tctx
,
4090 struct dcerpc_binding_handle
*b
,
4091 struct policy_handle
*handle
,
4092 const char **architecture
)
4095 enum winreg_Type type
;
4099 torture_assert(tctx
,
4100 test_GetPrinterData(tctx
, b
, handle
, "Architecture", &type
, &data
, &needed
),
4101 "failed to get Architecture");
4103 torture_assert_int_equal(tctx
, type
, REG_SZ
, "unexpected type");
4105 blob
= data_blob_const(data
, needed
);
4106 *architecture
= reg_val_data_string(tctx
, REG_SZ
, blob
);
4111 static bool test_GetPrinterData_list(struct torture_context
*tctx
,
4114 struct test_spoolss_context
*ctx
=
4115 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
4116 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
4117 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4118 const char *list
[] = {
4122 /* "NetPopup", not on w2k8 */
4123 /* "NetPopupToComputer", not on w2k8 */
4126 "DefaultSpoolDirectory",
4130 /* "OSVersionEx", not on s3 */
4135 for (i
=0; i
< ARRAY_SIZE(list
); i
++) {
4136 enum winreg_Type type
= REG_NONE
;
4137 enum winreg_Type type_ex1
= REG_NONE
;
4138 enum winreg_Type type_ex2
= REG_NONE
;
4140 uint8_t *data_ex1
= NULL
;
4141 uint8_t *data_ex2
= NULL
;
4143 uint32_t needed_ex1
= 0;
4144 uint32_t needed_ex2
= 0;
4146 torture_assert(tctx
, test_GetPrinterData(tctx
, b
, &ctx
->server_handle
, list
[i
], &type
, &data
, &needed
),
4147 talloc_asprintf(tctx
, "GetPrinterData failed on %s\n", list
[i
]));
4148 torture_assert(tctx
, test_GetPrinterDataEx(tctx
, p
, &ctx
->server_handle
, "random_string", list
[i
], &type_ex1
, &data_ex1
, &needed_ex1
),
4149 talloc_asprintf(tctx
, "GetPrinterDataEx failed on %s\n", list
[i
]));
4150 torture_assert(tctx
, test_GetPrinterDataEx(tctx
, p
, &ctx
->server_handle
, "", list
[i
], &type_ex2
, &data_ex2
, &needed_ex2
),
4151 talloc_asprintf(tctx
, "GetPrinterDataEx failed on %s\n", list
[i
]));
4152 torture_assert_int_equal(tctx
, type
, type_ex1
, "type mismatch");
4153 torture_assert_int_equal(tctx
, type
, type_ex2
, "type mismatch");
4154 torture_assert_int_equal(tctx
, needed
, needed_ex1
, "needed mismatch");
4155 torture_assert_int_equal(tctx
, needed
, needed_ex2
, "needed mismatch");
4156 torture_assert_mem_equal(tctx
, data
, data_ex1
, needed
, "data mismatch");
4157 torture_assert_mem_equal(tctx
, data
, data_ex2
, needed
, "data mismatch");
4163 static bool test_EnumPrinterData(struct torture_context
*tctx
,
4164 struct dcerpc_pipe
*p
,
4165 struct policy_handle
*handle
,
4166 uint32_t enum_index
,
4167 uint32_t value_offered
,
4168 uint32_t data_offered
,
4169 enum winreg_Type
*type_p
,
4170 uint32_t *value_needed_p
,
4171 uint32_t *data_needed_p
,
4172 const char **value_name_p
,
4176 struct spoolss_EnumPrinterData r
;
4177 uint32_t data_needed
;
4178 uint32_t value_needed
;
4179 enum winreg_Type type
;
4180 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4182 r
.in
.handle
= handle
;
4183 r
.in
.enum_index
= enum_index
;
4184 r
.in
.value_offered
= value_offered
;
4185 r
.in
.data_offered
= data_offered
;
4186 r
.out
.data_needed
= &data_needed
;
4187 r
.out
.value_needed
= &value_needed
;
4189 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.data_offered
);
4190 r
.out
.value_name
= talloc_zero_array(tctx
, const char, r
.in
.value_offered
);
4192 torture_comment(tctx
, "Testing EnumPrinterData(%d)\n", enum_index
);
4194 torture_assert_ntstatus_ok(tctx
,
4195 dcerpc_spoolss_EnumPrinterData_r(b
, tctx
, &r
),
4196 "EnumPrinterData failed");
4201 if (value_needed_p
) {
4202 *value_needed_p
= value_needed
;
4204 if (data_needed_p
) {
4205 *data_needed_p
= data_needed
;
4208 *value_name_p
= r
.out
.value_name
;
4211 *data_p
= r
.out
.data
;
4214 *result_p
= r
.out
.result
;
4221 static bool test_EnumPrinterData_all(struct torture_context
*tctx
,
4222 struct dcerpc_pipe
*p
,
4223 struct policy_handle
*handle
)
4225 uint32_t enum_index
= 0;
4226 enum winreg_Type type
;
4227 uint32_t value_needed
;
4228 uint32_t data_needed
;
4230 const char *value_name
;
4233 torture_comment(tctx
, "Testing EnumPrinterData\n");
4236 torture_assert(tctx
,
4237 test_EnumPrinterData(tctx
, p
, handle
, enum_index
, 0, 0,
4238 &type
, &value_needed
, &data_needed
,
4239 &value_name
, &data
, &result
),
4240 "EnumPrinterData failed");
4242 if (W_ERROR_EQUAL(result
, WERR_NO_MORE_ITEMS
)) {
4246 torture_assert(tctx
,
4247 test_EnumPrinterData(tctx
, p
, handle
, enum_index
, value_needed
, data_needed
,
4248 &type
, &value_needed
, &data_needed
,
4249 &value_name
, &data
, &result
),
4250 "EnumPrinterData failed");
4252 if (W_ERROR_EQUAL(result
, WERR_NO_MORE_ITEMS
)) {
4258 } while (W_ERROR_IS_OK(result
));
4260 torture_comment(tctx
, "EnumPrinterData test succeeded\n");
4265 static bool test_EnumPrinterDataEx(struct torture_context
*tctx
,
4266 struct dcerpc_binding_handle
*b
,
4267 struct policy_handle
*handle
,
4268 const char *key_name
,
4270 struct spoolss_PrinterEnumValues
**info_p
)
4272 struct spoolss_EnumPrinterDataEx r
;
4273 struct spoolss_PrinterEnumValues
*info
;
4277 r
.in
.handle
= handle
;
4278 r
.in
.key_name
= key_name
;
4280 r
.out
.needed
= &needed
;
4281 r
.out
.count
= &count
;
4284 torture_comment(tctx
, "Testing EnumPrinterDataEx(%s)\n", key_name
);
4286 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterDataEx_r(b
, tctx
, &r
),
4287 "EnumPrinterDataEx failed");
4288 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
4289 r
.in
.offered
= needed
;
4290 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterDataEx_r(b
, tctx
, &r
),
4291 "EnumPrinterDataEx failed");
4294 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDataEx failed");
4296 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx
, info
, count
, needed
, 1);
4308 static bool test_SetPrinterData(struct torture_context
*tctx
,
4309 struct dcerpc_binding_handle
*b
,
4310 struct policy_handle
*handle
,
4311 const char *value_name
,
4312 enum winreg_Type type
,
4315 static bool test_DeletePrinterData(struct torture_context
*tctx
,
4316 struct dcerpc_binding_handle
*b
,
4317 struct policy_handle
*handle
,
4318 const char *value_name
);
4320 static bool test_EnumPrinterData_consistency(struct torture_context
*tctx
,
4321 struct dcerpc_pipe
*p
,
4322 struct policy_handle
*handle
)
4325 struct spoolss_PrinterEnumValues
*info
;
4327 uint32_t value_needed
, data_needed
;
4328 uint32_t value_offered
, data_offered
;
4330 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4332 enum winreg_Type type
;
4335 torture_comment(tctx
, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
4337 torture_assert(tctx
, push_reg_sz(tctx
, &blob
, "torture_data1"), "");
4340 torture_assert(tctx
,
4341 test_SetPrinterData(tctx
, b
, handle
, "torture_value1", type
, blob
.data
, blob
.length
),
4342 "SetPrinterData failed");
4344 blob
= data_blob_string_const("torture_data2");
4346 torture_assert(tctx
,
4347 test_SetPrinterData(tctx
, b
, handle
, "torture_value2", REG_BINARY
, blob
.data
, blob
.length
),
4348 "SetPrinterData failed");
4350 blob
= data_blob_talloc(tctx
, NULL
, 4);
4351 SIVAL(blob
.data
, 0, 0x11223344);
4353 torture_assert(tctx
,
4354 test_SetPrinterData(tctx
, b
, handle
, "torture_value3", type
, blob
.data
, blob
.length
),
4355 "SetPrinterData failed");
4357 torture_assert(tctx
,
4358 test_EnumPrinterDataEx(tctx
, b
, handle
, "PrinterDriverData", &count
, &info
),
4359 "failed to call EnumPrinterDataEx");
4361 /* get the max sizes for value and data */
4363 torture_assert(tctx
,
4364 test_EnumPrinterData(tctx
, p
, handle
, 0, 0, 0,
4365 NULL
, &value_needed
, &data_needed
,
4366 NULL
, NULL
, &result
),
4367 "EnumPrinterData failed");
4368 torture_assert_werr_ok(tctx
, result
, "unexpected result");
4370 /* check if the reply from the EnumPrinterData really matches max values */
4372 for (i
=0; i
< count
; i
++) {
4373 if (info
[i
].value_name_len
> value_needed
) {
4375 talloc_asprintf(tctx
,
4376 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
4377 info
[i
].value_name_len
, value_needed
));
4379 if (info
[i
].data_length
> data_needed
) {
4381 talloc_asprintf(tctx
,
4382 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
4383 info
[i
].data_length
, data_needed
));
4387 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
4388 * sort or not sort the replies by value name, we should be able to do
4389 * the following entry comparison */
4391 data_offered
= data_needed
;
4392 value_offered
= value_needed
;
4394 for (i
=0; i
< count
; i
++) {
4396 const char *value_name
;
4399 torture_assert(tctx
,
4400 test_EnumPrinterData(tctx
, p
, handle
, i
, value_offered
, data_offered
,
4401 &type
, &value_needed
, &data_needed
,
4402 &value_name
, &data
, &result
),
4403 "EnumPrinterData failed");
4405 if (i
-1 == count
) {
4406 torture_assert_werr_equal(tctx
, result
, WERR_NO_MORE_ITEMS
,
4407 "unexpected result");
4410 torture_assert_werr_ok(tctx
, result
, "unexpected result");
4413 torture_assert_int_equal(tctx
, type
, info
[i
].type
, "type mismatch");
4414 torture_assert_int_equal(tctx
, value_needed
, info
[i
].value_name_len
, "value name length mismatch");
4415 torture_assert_str_equal(tctx
, value_name
, info
[i
].value_name
, "value name mismatch");
4416 torture_assert_int_equal(tctx
, data_needed
, info
[i
].data_length
, "data length mismatch");
4417 torture_assert_mem_equal(tctx
, data
, info
[i
].data
->data
, info
[i
].data_length
, "data mismatch");
4420 torture_assert(tctx
,
4421 test_DeletePrinterData(tctx
, b
, handle
, "torture_value1"),
4422 "DeletePrinterData failed");
4423 torture_assert(tctx
,
4424 test_DeletePrinterData(tctx
, b
, handle
, "torture_value2"),
4425 "DeletePrinterData failed");
4426 torture_assert(tctx
,
4427 test_DeletePrinterData(tctx
, b
, handle
, "torture_value3"),
4428 "DeletePrinterData failed");
4430 torture_comment(tctx
, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4435 static bool test_DeletePrinterData(struct torture_context
*tctx
,
4436 struct dcerpc_binding_handle
*b
,
4437 struct policy_handle
*handle
,
4438 const char *value_name
)
4441 struct spoolss_DeletePrinterData r
;
4443 r
.in
.handle
= handle
;
4444 r
.in
.value_name
= value_name
;
4446 torture_comment(tctx
, "Testing DeletePrinterData(%s)\n",
4449 status
= dcerpc_spoolss_DeletePrinterData_r(b
, tctx
, &r
);
4451 torture_assert_ntstatus_ok(tctx
, status
, "DeletePrinterData failed");
4452 torture_assert_werr_ok(tctx
, r
.out
.result
, "DeletePrinterData failed");
4457 static bool test_DeletePrinterDataEx(struct torture_context
*tctx
,
4458 struct dcerpc_binding_handle
*b
,
4459 struct policy_handle
*handle
,
4460 const char *key_name
,
4461 const char *value_name
)
4463 struct spoolss_DeletePrinterDataEx r
;
4465 r
.in
.handle
= handle
;
4466 r
.in
.key_name
= key_name
;
4467 r
.in
.value_name
= value_name
;
4469 torture_comment(tctx
, "Testing DeletePrinterDataEx(%s - %s)\n",
4470 r
.in
.key_name
, r
.in
.value_name
);
4472 torture_assert_ntstatus_ok(tctx
,
4473 dcerpc_spoolss_DeletePrinterDataEx_r(b
, tctx
, &r
),
4474 "DeletePrinterDataEx failed");
4475 torture_assert_werr_ok(tctx
, r
.out
.result
,
4476 "DeletePrinterDataEx failed");
4481 static bool test_DeletePrinterKey(struct torture_context
*tctx
,
4482 struct dcerpc_binding_handle
*b
,
4483 struct policy_handle
*handle
,
4484 const char *key_name
)
4486 struct spoolss_DeletePrinterKey r
;
4488 r
.in
.handle
= handle
;
4489 r
.in
.key_name
= key_name
;
4491 torture_comment(tctx
, "Testing DeletePrinterKey(%s)\n", r
.in
.key_name
);
4493 if (strequal(key_name
, "") && !torture_setting_bool(tctx
, "dangerous", false)) {
4494 torture_skip(tctx
, "not wiping out printer registry - enable dangerous tests to use\n");
4498 torture_assert_ntstatus_ok(tctx
,
4499 dcerpc_spoolss_DeletePrinterKey_r(b
, tctx
, &r
),
4500 "DeletePrinterKey failed");
4501 torture_assert_werr_ok(tctx
, r
.out
.result
,
4502 "DeletePrinterKey failed");
4507 static bool test_winreg_OpenHKLM(struct torture_context
*tctx
,
4508 struct dcerpc_binding_handle
*b
,
4509 struct policy_handle
*handle
)
4511 struct winreg_OpenHKLM r
;
4513 r
.in
.system_name
= NULL
;
4514 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4515 r
.out
.handle
= handle
;
4517 torture_comment(tctx
, "Testing winreg_OpenHKLM\n");
4519 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_OpenHKLM_r(b
, tctx
, &r
), "OpenHKLM failed");
4520 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenHKLM failed");
4525 static void init_winreg_String(struct winreg_String
*name
, const char *s
)
4529 name
->name_len
= 2 * (strlen_m(s
) + 1);
4530 name
->name_size
= name
->name_len
;
4533 name
->name_size
= 0;
4537 static bool test_winreg_OpenKey_opts(struct torture_context
*tctx
,
4538 struct dcerpc_binding_handle
*b
,
4539 struct policy_handle
*hive_handle
,
4540 const char *keyname
,
4542 struct policy_handle
*key_handle
)
4544 struct winreg_OpenKey r
;
4546 r
.in
.parent_handle
= hive_handle
;
4547 init_winreg_String(&r
.in
.keyname
, keyname
);
4548 r
.in
.options
= options
;
4549 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4550 r
.out
.handle
= key_handle
;
4552 torture_comment(tctx
, "Testing winreg_OpenKey(%s)\n", keyname
);
4554 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_OpenKey_r(b
, tctx
, &r
), "OpenKey failed");
4555 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenKey failed");
4560 static bool test_winreg_OpenKey(struct torture_context
*tctx
,
4561 struct dcerpc_binding_handle
*b
,
4562 struct policy_handle
*hive_handle
,
4563 const char *keyname
,
4564 struct policy_handle
*key_handle
)
4566 return test_winreg_OpenKey_opts(tctx
, b
, hive_handle
, keyname
,
4567 REG_OPTION_NON_VOLATILE
, key_handle
);
4570 static bool test_winreg_CloseKey(struct torture_context
*tctx
,
4571 struct dcerpc_binding_handle
*b
,
4572 struct policy_handle
*handle
)
4574 struct winreg_CloseKey r
;
4576 r
.in
.handle
= handle
;
4577 r
.out
.handle
= handle
;
4579 torture_comment(tctx
, "Testing winreg_CloseKey\n");
4581 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_CloseKey_r(b
, tctx
, &r
), "CloseKey failed");
4582 torture_assert_werr_ok(tctx
, r
.out
.result
, "CloseKey failed");
4587 bool test_winreg_QueryValue(struct torture_context
*tctx
,
4588 struct dcerpc_binding_handle
*b
,
4589 struct policy_handle
*handle
,
4590 const char *value_name
,
4591 enum winreg_Type
*type_p
,
4592 uint32_t *data_size_p
,
4593 uint32_t *data_length_p
,
4596 struct winreg_QueryValue r
;
4597 enum winreg_Type type
= REG_NONE
;
4598 uint32_t data_size
= 0;
4599 uint32_t data_length
= 0;
4600 struct winreg_String valuename
;
4601 uint8_t *data
= NULL
;
4603 init_winreg_String(&valuename
, value_name
);
4605 data
= talloc_zero_array(tctx
, uint8_t, 0);
4607 r
.in
.handle
= handle
;
4608 r
.in
.value_name
= &valuename
;
4610 r
.in
.data_size
= &data_size
;
4611 r
.in
.data_length
= &data_length
;
4615 r
.out
.data_size
= &data_size
;
4616 r
.out
.data_length
= &data_length
;
4618 torture_comment(tctx
, "Testing winreg_QueryValue(%s)\n", value_name
);
4620 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_QueryValue_r(b
, tctx
, &r
), "QueryValue failed");
4621 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
4622 *r
.in
.data_size
= *r
.out
.data_size
;
4623 data
= talloc_zero_array(tctx
, uint8_t, *r
.in
.data_size
);
4626 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_QueryValue_r(b
, tctx
, &r
), "QueryValue failed");
4628 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryValue failed");
4631 *type_p
= *r
.out
.type
;
4634 *data_size_p
= *r
.out
.data_size
;
4636 if (data_length_p
) {
4637 *data_length_p
= *r
.out
.data_length
;
4640 *data_p
= r
.out
.data
;
4646 static bool test_winreg_query_printerdata(struct torture_context
*tctx
,
4647 struct dcerpc_binding_handle
*b
,
4648 struct policy_handle
*handle
,
4649 const char *printer_name
,
4650 const char *key_name
,
4651 const char *value_name
,
4652 enum winreg_Type
*w_type
,
4657 const char *printer_key
;
4658 struct policy_handle key_handle
;
4660 printer_key
= talloc_asprintf(tctx
, "%s\\%s\\%s",
4661 TOP_LEVEL_PRINT_PRINTERS_KEY
, printer_name
, key_name
);
4663 torture_assert(tctx
,
4664 test_winreg_OpenKey(tctx
, b
, handle
, printer_key
, &key_handle
), "");
4666 torture_assert(tctx
,
4667 test_winreg_QueryValue(tctx
, b
, &key_handle
, value_name
, w_type
, w_size
, w_length
, w_data
), "");
4669 torture_assert(tctx
,
4670 test_winreg_CloseKey(tctx
, b
, &key_handle
), "");
4675 static bool test_GetForm_winreg(struct torture_context
*tctx
,
4676 struct dcerpc_binding_handle
*b
,
4677 struct policy_handle
*handle
,
4678 const char *key_name
,
4679 const char *form_name
,
4680 enum winreg_Type
*w_type
,
4685 struct policy_handle key_handle
;
4687 torture_assert(tctx
,
4688 test_winreg_OpenKey(tctx
, b
, handle
, key_name
, &key_handle
), "");
4690 torture_assert(tctx
,
4691 test_winreg_QueryValue(tctx
, b
, &key_handle
, form_name
, w_type
, w_size
, w_length
, w_data
), "");
4693 torture_assert(tctx
,
4694 test_winreg_CloseKey(tctx
, b
, &key_handle
), "");
4699 static bool test_winreg_symbolic_link(struct torture_context
*tctx
,
4700 struct dcerpc_binding_handle
*b
,
4701 struct policy_handle
*handle
,
4702 const char *symlink_keyname
,
4703 const char *symlink_destination
)
4705 /* check if the first key is a symlink to the second key */
4707 enum winreg_Type w_type
;
4711 struct policy_handle key_handle
;
4715 if (torture_setting_bool(tctx
, "samba3", false)) {
4716 torture_skip(tctx
, "skip winreg symlink test against samba");
4719 torture_assert(tctx
,
4720 test_winreg_OpenKey_opts(tctx
, b
, handle
, symlink_keyname
, REG_OPTION_OPEN_LINK
, &key_handle
),
4721 "failed to open key link");
4723 torture_assert(tctx
,
4724 test_winreg_QueryValue(tctx
, b
, &key_handle
,
4725 "SymbolicLinkValue",
4726 &w_type
, &w_size
, &w_length
, &w_data
),
4727 "failed to query for 'SymbolicLinkValue' attribute");
4729 torture_assert_int_equal(tctx
, w_type
, REG_LINK
, "unexpected type");
4731 blob
= data_blob(w_data
, w_size
);
4732 str
= reg_val_data_string(tctx
, REG_SZ
, blob
);
4734 torture_assert_str_equal(tctx
, str
, symlink_destination
, "unexpected symlink target string");
4736 torture_assert(tctx
,
4737 test_winreg_CloseKey(tctx
, b
, &key_handle
),
4738 "failed to close key link");
4743 static const char *strip_unc(const char *unc
)
4751 if (unc
[0] == '\\' && unc
[1] == '\\') {
4755 name
= strchr(unc
, '\\');
4763 static bool test_GetPrinterInfo_winreg(struct torture_context
*tctx
,
4764 struct dcerpc_binding_handle
*b
,
4765 struct policy_handle
*handle
,
4766 const char *printer_name
,
4767 struct dcerpc_binding_handle
*winreg_handle
,
4768 struct policy_handle
*hive_handle
)
4770 union spoolss_PrinterInfo info
;
4771 const char *keys
[] = {
4772 TOP_LEVEL_CONTROL_PRINTERS_KEY
,
4773 TOP_LEVEL_PRINT_PRINTERS_KEY
4776 const char *printername
, *sharename
;
4778 torture_comment(tctx
, "Testing Printer Info and winreg consistency\n");
4780 torture_assert(tctx
,
4781 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
4782 "failed to get printer info level 2");
4784 printername
= strip_unc(info
.info2
.printername
);
4785 sharename
= strip_unc(info
.info2
.sharename
);
4787 #define test_sz(wname, iname) \
4791 enum winreg_Type w_type;\
4795 torture_assert(tctx,\
4796 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4797 &w_type, &w_size, &w_length, &w_data),\
4798 "failed to query winreg");\
4799 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4800 blob = data_blob(w_data, w_size);\
4801 str = reg_val_data_string(tctx, REG_SZ, blob);\
4802 if (w_size == 2 && iname == NULL) {\
4803 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4805 torture_assert_str_equal(tctx, str, iname,\
4806 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4810 #define test_dword(wname, iname) \
4813 enum winreg_Type w_type;\
4817 torture_assert(tctx,\
4818 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4819 &w_type, &w_size, &w_length, &w_data),\
4820 "failed to query winreg");\
4821 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4822 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4823 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4824 value = IVAL(w_data, 0);\
4825 torture_assert_int_equal(tctx, value, iname,\
4826 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4829 #define test_binary(wname, iname) \
4831 enum winreg_Type w_type;\
4835 torture_assert(tctx,\
4836 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4837 &w_type, &w_size, &w_length, &w_data),\
4838 "failed to query winreg");\
4839 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4840 torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4841 torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4846 #define test_dm(wname, iname) \
4849 struct spoolss_DeviceMode dm;\
4850 enum ndr_err_code ndr_err;\
4851 enum winreg_Type w_type;\
4855 torture_assert(tctx,\
4856 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4857 &w_type, &w_size, &w_length, &w_data),\
4858 "failed to query winreg");\
4859 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4860 blob = data_blob(w_data, w_size);\
4861 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4862 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4863 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4864 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4868 #define test_sd(wname, iname) \
4871 struct security_descriptor sd;\
4872 enum ndr_err_code ndr_err;\
4873 enum winreg_Type w_type;\
4877 torture_assert(tctx,\
4878 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4879 &w_type, &w_size, &w_length, &w_data),\
4880 "failed to query winreg");\
4881 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4882 blob = data_blob(w_data, w_size);\
4883 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4884 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4885 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4886 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4890 #define test_multi_sz(wname, iname) \
4893 const char **array;\
4894 enum winreg_Type w_type;\
4899 torture_assert(tctx,\
4900 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4901 &w_type, &w_size, &w_length, &w_data),\
4902 "failed to query winreg");\
4903 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4904 blob = data_blob(w_data, w_size);\
4905 torture_assert(tctx, \
4906 pull_reg_multi_sz(tctx, &blob, &array),\
4907 "failed to pull multi sz");\
4908 for (i=0; array[i] != NULL; i++) {\
4909 torture_assert_str_equal(tctx, array[i], iname[i],\
4910 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4914 if (!test_winreg_symbolic_link(tctx
, winreg_handle
, hive_handle
,
4915 TOP_LEVEL_CONTROL_PRINTERS_KEY
,
4916 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4918 torture_warning(tctx
, "failed to check for winreg symlink");
4921 for (i
=0; i
< ARRAY_SIZE(keys
); i
++) {
4923 const char *printer_key
;
4924 struct policy_handle key_handle
;
4926 printer_key
= talloc_asprintf(tctx
, "%s\\%s",
4927 keys
[i
], printer_name
);
4929 torture_assert(tctx
,
4930 test_winreg_OpenKey(tctx
, winreg_handle
, hive_handle
, printer_key
, &key_handle
), "");
4932 test_sz("Name", printername
);
4933 test_sz("Share Name", sharename
);
4934 test_sz("Port", info
.info2
.portname
);
4935 test_sz("Printer Driver", info
.info2
.drivername
);
4936 test_sz("Description", info
.info2
.comment
);
4937 test_sz("Location", info
.info2
.location
);
4938 test_sz("Separator File", info
.info2
.sepfile
);
4939 test_sz("Print Processor", info
.info2
.printprocessor
);
4940 test_sz("Datatype", info
.info2
.datatype
);
4941 test_sz("Parameters", info
.info2
.parameters
);
4942 /* winreg: 0, spoolss not */
4943 /* test_dword("Attributes", info.info2.attributes); */
4944 test_dword("Priority", info
.info2
.priority
);
4945 test_dword("Default Priority", info
.info2
.defaultpriority
);
4946 /* winreg: 60, spoolss: 0 */
4947 /* test_dword("StartTime", info.info2.starttime); */
4948 /* test_dword("UntilTime", info.info2.untiltime); */
4949 /* winreg != spoolss */
4950 /* test_dword("Status", info.info2.status); */
4951 test_dm("Default DevMode", info
.info2
.devmode
);
4952 test_sd("Security", info
.info2
.secdesc
);
4954 torture_assert(tctx
,
4955 test_winreg_CloseKey(tctx
, winreg_handle
, &key_handle
), "");
4960 torture_comment(tctx
, "Printer Info and winreg consistency test succeeded\n\n");
4965 static bool test_GetPrintserverInfo_winreg(struct torture_context
*tctx
,
4966 struct dcerpc_binding_handle
*b
,
4967 struct policy_handle
*handle
,
4968 struct dcerpc_binding_handle
*winreg_handle
,
4969 struct policy_handle
*hive_handle
)
4971 union spoolss_PrinterInfo info
;
4972 struct policy_handle key_handle
;
4974 torture_comment(tctx
,
4975 "Testing Printserver Info and winreg consistency\n");
4977 torture_assert(tctx
,
4978 test_GetPrinter_level(tctx
, b
, handle
, 3, &info
),
4979 "failed to get printer info level 2");
4981 torture_assert(tctx
,
4982 test_winreg_OpenKey(tctx
, winreg_handle
, hive_handle
,
4983 TOP_LEVEL_CONTROL_KEY
, &key_handle
), "");
4985 test_sd("ServerSecurityDescriptor", info
.info3
.secdesc
);
4987 torture_assert(tctx
,
4988 test_winreg_CloseKey(tctx
, winreg_handle
, &key_handle
), "");
4992 torture_comment(tctx
,
4993 "Printserver Info and winreg consistency test succeeded\n\n");
4999 static bool test_PrintProcessors(struct torture_context
*tctx
,
5000 struct dcerpc_binding_handle
*b
,
5001 const char *environment
,
5002 struct dcerpc_binding_handle
*winreg_handle
,
5003 struct policy_handle
*hive_handle
)
5005 union spoolss_PrintProcessorInfo
*info
;
5009 torture_comment(tctx
, "Testing Print Processor Info and winreg consistency\n");
5011 torture_assert(tctx
,
5012 test_EnumPrintProcessors_level(tctx
, b
, environment
, 1, &count
, &info
, WERR_OK
),
5013 "failed to enum print processors level 1");
5015 for (i
=0; i
< count
; i
++) {
5017 const char *processor_key
;
5018 struct policy_handle key_handle
;
5020 processor_key
= talloc_asprintf(tctx
, "%s\\%s\\Print Processors\\%s",
5021 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY
,
5023 info
[i
].info1
.print_processor_name
);
5025 torture_assert(tctx
,
5026 test_winreg_OpenKey(tctx
, winreg_handle
, hive_handle
, processor_key
, &key_handle
), "");
5028 /* nothing to check in there so far */
5030 torture_assert(tctx
,
5031 test_winreg_CloseKey(tctx
, winreg_handle
, &key_handle
), "");
5034 torture_comment(tctx
, "Print Processor Info and winreg consistency test succeeded\n\n");
5039 static bool test_GetPrinterDriver2_level(struct torture_context
*tctx
,
5040 struct dcerpc_binding_handle
*b
,
5041 struct policy_handle
*handle
,
5042 const char *driver_name
,
5043 const char *architecture
,
5045 uint32_t client_major_version
,
5046 uint32_t client_minor_version
,
5047 union spoolss_DriverInfo
*info_p
,
5050 static const char *strip_path(const char *path
)
5058 p
= strrchr(path
, '\\');
5066 static const char **strip_paths(const char **path_array
)
5070 if (path_array
== NULL
) {
5074 for (i
=0; path_array
[i
] != NULL
; i
++) {
5075 path_array
[i
] = strip_path(path_array
[i
]);
5081 static const char *driver_winreg_date(TALLOC_CTX
*mem_ctx
, NTTIME nt
)
5087 return talloc_strdup(mem_ctx
, "01/01/1601");
5090 t
= nt_time_to_unix(nt
);
5093 return talloc_asprintf(mem_ctx
, "%02d/%02d/%04d",
5094 tm
->tm_mon
+ 1, tm
->tm_mday
, tm
->tm_year
+ 1900);
5097 static const char *driver_winreg_version(TALLOC_CTX
*mem_ctx
, uint64_t v
)
5099 return talloc_asprintf(mem_ctx
, "%u.%u.%u.%u",
5100 (unsigned)((v
>> 48) & 0xFFFF),
5101 (unsigned)((v
>> 32) & 0xFFFF),
5102 (unsigned)((v
>> 16) & 0xFFFF),
5103 (unsigned)(v
& 0xFFFF));
5106 static bool test_GetDriverInfo_winreg(struct torture_context
*tctx
,
5107 struct dcerpc_binding_handle
*b
,
5108 struct policy_handle
*handle
,
5109 const char *printer_name
,
5110 const char *driver_name
,
5111 const char *environment
,
5112 enum spoolss_DriverOSVersion version
,
5113 struct dcerpc_binding_handle
*winreg_handle
,
5114 struct policy_handle
*hive_handle
,
5115 const char *server_name_slash
)
5117 WERROR result
= WERR_OK
;
5118 union spoolss_DriverInfo info
;
5119 const char *driver_key
;
5120 struct policy_handle key_handle
;
5122 const char *driver_path
;
5123 const char *data_file
;
5124 const char *config_file
;
5125 const char *help_file
;
5126 const char **dependent_files
;
5128 const char *driver_date
;
5129 const char *inbox_driver_date
;
5131 const char *driver_version
;
5132 const char *inbox_driver_version
;
5134 ZERO_STRUCT(key_handle
);
5136 torture_comment(tctx
, "Testing Driver Info and winreg consistency\n");
5138 driver_key
= talloc_asprintf(tctx
, "%s\\%s\\Drivers\\Version-%d\\%s",
5139 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY
,
5144 torture_assert(tctx
,
5145 test_winreg_OpenKey(tctx
, winreg_handle
, hive_handle
, driver_key
, &key_handle
),
5146 "failed to open driver key");
5148 if (torture_setting_bool(tctx
, "samba3", false) ||
5149 torture_setting_bool(tctx
, "w2k3", false)) {
5154 torture_assert(tctx
,
5155 test_GetPrinterDriver2_level(tctx
, b
, handle
, driver_name
, environment
, 8, version
, 0, &info
, &result
),
5156 "failed to get driver info level 8");
5158 torture_assert(tctx
,
5159 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, environment
, 8, driver_name
, &info
),
5160 "failed to get driver info level 8");
5163 if (W_ERROR_EQUAL(result
, WERR_INVALID_LEVEL
)) {
5167 driver_path
= strip_path(info
.info8
.driver_path
);
5168 data_file
= strip_path(info
.info8
.data_file
);
5169 config_file
= strip_path(info
.info8
.config_file
);
5170 help_file
= strip_path(info
.info8
.help_file
);
5171 dependent_files
= strip_paths(info
.info8
.dependent_files
);
5173 driver_date
= driver_winreg_date(tctx
, info
.info8
.driver_date
);
5174 inbox_driver_date
= driver_winreg_date(tctx
, info
.info8
.min_inbox_driver_ver_date
);
5176 driver_version
= driver_winreg_version(tctx
, info
.info8
.driver_version
);
5177 inbox_driver_version
= driver_winreg_version(tctx
, info
.info8
.min_inbox_driver_ver_version
);
5179 test_sz("Configuration File", config_file
);
5180 test_sz("Data File", data_file
);
5181 test_sz("Datatype", info
.info8
.default_datatype
);
5182 test_sz("Driver", driver_path
);
5183 test_sz("DriverDate", driver_date
);
5184 test_sz("DriverVersion", driver_version
);
5185 test_sz("HardwareID", info
.info8
.hardware_id
);
5186 test_sz("Help File", help_file
);
5187 test_sz("InfPath", info
.info8
.inf_path
);
5188 test_sz("Manufacturer", info
.info8
.manufacturer_name
);
5189 test_sz("MinInboxDriverVerDate", inbox_driver_date
);
5190 test_sz("MinInboxDriverVerVersion", inbox_driver_version
);
5191 test_sz("Monitor", info
.info8
.monitor_name
);
5192 test_sz("OEM URL", info
.info8
.manufacturer_url
);
5193 test_sz("Print Processor", info
.info8
.print_processor
);
5194 test_sz("Provider", info
.info8
.provider
);
5195 test_sz("VendorSetup", info
.info8
.vendor_setup
);
5196 test_multi_sz("ColorProfiles", info
.info8
.color_profiles
);
5197 test_multi_sz("Dependent Files", dependent_files
);
5198 test_multi_sz("CoreDependencies", info
.info8
.core_driver_dependencies
);
5199 test_multi_sz("Previous Names", info
.info8
.previous_names
);
5200 /* test_dword("Attributes", ?); */
5201 test_dword("PrinterDriverAttributes", info
.info8
.printer_driver_attributes
);
5202 test_dword("Version", info
.info8
.version
);
5203 /* test_dword("TempDir", ?); */
5208 torture_assert(tctx
,
5209 test_GetPrinterDriver2_level(tctx
, b
, handle
, driver_name
, environment
, 6, version
, 0, &info
, &result
),
5210 "failed to get driver info level 6");
5212 torture_assert(tctx
,
5213 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, environment
, 6, driver_name
, &info
),
5214 "failed to get driver info level 6");
5217 driver_path
= strip_path(info
.info6
.driver_path
);
5218 data_file
= strip_path(info
.info6
.data_file
);
5219 config_file
= strip_path(info
.info6
.config_file
);
5220 help_file
= strip_path(info
.info6
.help_file
);
5221 dependent_files
= strip_paths(info
.info6
.dependent_files
);
5223 driver_date
= driver_winreg_date(tctx
, info
.info6
.driver_date
);
5225 driver_version
= driver_winreg_version(tctx
, info
.info6
.driver_version
);
5227 test_sz("Configuration File", config_file
);
5228 test_sz("Data File", data_file
);
5229 test_sz("Datatype", info
.info6
.default_datatype
);
5230 test_sz("Driver", driver_path
);
5231 if (torture_setting_bool(tctx
, "w2k3", false)) {
5232 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, 8);
5233 push_nttime(blob
.data
, 0, info
.info6
.driver_date
);
5234 test_binary("DriverDate", blob
);
5235 SBVAL(blob
.data
, 0, info
.info6
.driver_version
);
5236 test_binary("DriverVersion", blob
);
5238 test_sz("DriverDate", driver_date
);
5239 test_sz("DriverVersion", driver_version
);
5241 test_sz("HardwareID", info
.info6
.hardware_id
);
5242 test_sz("Help File", help_file
);
5243 test_sz("Manufacturer", info
.info6
.manufacturer_name
);
5244 test_sz("Monitor", info
.info6
.monitor_name
);
5245 test_sz("OEM URL", info
.info6
.manufacturer_url
);
5246 test_sz("Provider", info
.info6
.provider
);
5247 test_multi_sz("Dependent Files", dependent_files
);
5248 test_multi_sz("Previous Names", info
.info6
.previous_names
);
5249 /* test_dword("Attributes", ?); */
5250 test_dword("Version", info
.info6
.version
);
5251 /* test_dword("TempDir", ?); */
5254 torture_assert(tctx
,
5255 test_GetPrinterDriver2_level(tctx
, b
, handle
, driver_name
, environment
, 3, version
, 0, &info
, &result
),
5256 "failed to get driver info level 3");
5258 torture_assert(tctx
,
5259 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, environment
, 3, driver_name
, &info
),
5260 "failed to get driver info level 3");
5263 driver_path
= strip_path(info
.info3
.driver_path
);
5264 data_file
= strip_path(info
.info3
.data_file
);
5265 config_file
= strip_path(info
.info3
.config_file
);
5266 help_file
= strip_path(info
.info3
.help_file
);
5267 dependent_files
= strip_paths(info
.info3
.dependent_files
);
5269 test_sz("Configuration File", config_file
);
5270 test_sz("Data File", data_file
);
5271 test_sz("Datatype", info
.info3
.default_datatype
);
5272 test_sz("Driver", driver_path
);
5273 test_sz("Help File", help_file
);
5274 test_sz("Monitor", info
.info3
.monitor_name
);
5275 test_multi_sz("Dependent Files", dependent_files
);
5276 /* test_dword("Attributes", ?); */
5277 test_dword("Version", info
.info3
.version
);
5278 /* test_dword("TempDir", ?); */
5281 torture_assert(tctx
,
5282 test_winreg_CloseKey(tctx
, winreg_handle
, &key_handle
), "");
5284 torture_comment(tctx
, "Driver Info and winreg consistency test succeeded\n\n");
5292 static bool test_SetPrinterData(struct torture_context
*tctx
,
5293 struct dcerpc_binding_handle
*b
,
5294 struct policy_handle
*handle
,
5295 const char *value_name
,
5296 enum winreg_Type type
,
5300 struct spoolss_SetPrinterData r
;
5302 r
.in
.handle
= handle
;
5303 r
.in
.value_name
= value_name
;
5306 r
.in
.offered
= offered
;
5308 torture_comment(tctx
, "Testing SetPrinterData(%s)\n",
5311 torture_assert_ntstatus_ok(tctx
,
5312 dcerpc_spoolss_SetPrinterData_r(b
, tctx
, &r
),
5313 "SetPrinterData failed");
5314 torture_assert_werr_ok(tctx
, r
.out
.result
,
5315 "SetPrinterData failed");
5320 static bool test_SetPrinterData_matrix(struct torture_context
*tctx
,
5321 struct dcerpc_binding_handle
*b
,
5322 struct policy_handle
*handle
,
5323 const char *printer_name
,
5324 struct dcerpc_binding_handle
*winreg_handle
,
5325 struct policy_handle
*hive_handle
)
5327 const char *values
[] = {
5331 /* FIXME: not working with s3 atm. */
5337 /* FIXME: not working with s3 atm. */
5344 for (i
=0; i
< ARRAY_SIZE(values
); i
++) {
5346 enum winreg_Type type
, expected_type
= REG_SZ
;
5351 torture_assert(tctx
, push_reg_sz(tctx
, &blob
, "dog"), "");
5354 torture_assert(tctx
,
5355 test_SetPrinterData(tctx
, b
, handle
, values
[i
], REG_SZ
, blob
.data
, blob
.length
),
5356 "SetPrinterData failed");
5358 torture_assert(tctx
,
5359 test_GetPrinterData_checktype(tctx
, b
, handle
, values
[i
], &expected_type
, &type
, &data
, &needed
),
5360 "GetPrinterData failed");
5362 torture_assert_int_equal(tctx
, type
, REG_SZ
, "type mismatch");
5363 torture_assert_int_equal(tctx
, needed
, blob
.length
, "size mismatch");
5364 torture_assert_mem_equal(tctx
, data
, blob
.data
, blob
.length
, "buffer mismatch");
5366 if (winreg_handle
&& hive_handle
) {
5368 enum winreg_Type w_type
;
5373 torture_assert(tctx
,
5374 test_winreg_query_printerdata(tctx
, winreg_handle
, hive_handle
,
5375 printer_name
, "PrinterDriverData", values
[i
],
5376 &w_type
, &w_size
, &w_length
, &w_data
), "");
5378 torture_assert_int_equal(tctx
, w_type
, REG_SZ
, "winreg type mismatch");
5379 torture_assert_int_equal(tctx
, w_size
, blob
.length
, "winreg size mismatch");
5380 torture_assert_int_equal(tctx
, w_length
, blob
.length
, "winreg length mismatch");
5381 torture_assert_mem_equal(tctx
, w_data
, blob
.data
, blob
.length
, "winreg buffer mismatch");
5384 torture_assert(tctx
,
5385 test_DeletePrinterData(tctx
, b
, handle
, values
[i
]),
5386 "DeletePrinterData failed");
5393 static bool test_EnumPrinterKey(struct torture_context
*tctx
,
5394 struct dcerpc_binding_handle
*b
,
5395 struct policy_handle
*handle
,
5396 const char *key_name
,
5397 const char ***array
);
5399 static bool test_SetPrinterDataEx(struct torture_context
*tctx
,
5400 struct dcerpc_binding_handle
*b
,
5401 struct policy_handle
*handle
,
5402 const char *key_name
,
5403 const char *value_name
,
5404 enum winreg_Type type
,
5409 struct spoolss_SetPrinterDataEx r
;
5411 r
.in
.handle
= handle
;
5412 r
.in
.key_name
= key_name
;
5413 r
.in
.value_name
= value_name
;
5416 r
.in
.offered
= offered
;
5418 torture_comment(tctx
, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
5419 r
.in
.key_name
, r
.in
.value_name
, str_regtype(r
.in
.type
), r
.in
.offered
);
5421 status
= dcerpc_spoolss_SetPrinterDataEx_r(b
, tctx
, &r
);
5423 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinterDataEx failed");
5424 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinterDataEx failed");
5429 static bool test_SetPrinterDataEx_keys(struct torture_context
*tctx
,
5430 struct dcerpc_pipe
*p
,
5431 struct policy_handle
*handle
)
5433 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5434 const char *value_name
= "dog";
5435 const char *keys
[] = {
5438 "torturedataex_with_subkey\\subkey",
5439 "torturedataex_with_subkey\\subkey:0",
5440 "torturedataex_with_subkey\\subkey:1",
5441 "torturedataex_with_subkey\\subkey\\subsubkey",
5442 "torturedataex_with_subkey\\subkey\\subsubkey:0",
5443 "torturedataex_with_subkey\\subkey\\subsubkey:1",
5450 "torture/data ex/sub",
5453 "torture//data ex/sub",
5454 "torture//data ex//sub",
5458 for (i
=0; i
< ARRAY_SIZE(keys
); i
++) {
5462 enum winreg_Type type
;
5463 DATA_BLOB blob_in
, blob_out
;
5464 const char **subkeys
;
5466 struct spoolss_PrinterEnumValues
*einfo
;
5469 blob_in
= data_blob_talloc(tctx
, NULL
, 42);
5471 generate_random_buffer(blob_in
.data
, blob_in
.length
);
5473 torture_assert(tctx
,
5474 test_SetPrinterDataEx(tctx
, b
, handle
, keys
[i
], value_name
, REG_BINARY
, blob_in
.data
, blob_in
.length
),
5475 "failed to call SetPrinterDataEx");
5477 torture_assert(tctx
,
5478 test_GetPrinterDataEx(tctx
, p
, handle
, keys
[i
], value_name
, &type
, &blob_out
.data
, &needed
),
5479 "failed to call GetPrinterDataEx");
5481 blob_out
.length
= needed
;
5482 torture_assert(tctx
,
5483 test_EnumPrinterDataEx(tctx
, b
, handle
, keys
[i
], &ecount
, &einfo
),
5484 "failed to call EnumPrinterDataEx");
5486 torture_assert_int_equal(tctx
, type
, REG_BINARY
, "type mismatch");
5487 torture_assert_int_equal(tctx
, blob_out
.length
, blob_in
.length
, "size mismatch");
5488 torture_assert_mem_equal(tctx
, blob_out
.data
, blob_in
.data
, blob_in
.length
, "buffer mismatch");
5490 torture_assert_int_equal(tctx
, ecount
, 1, "unexpected enum count");
5491 torture_assert_str_equal(tctx
, einfo
[0].value_name
, value_name
, "value_name mismatch");
5492 torture_assert_int_equal(tctx
, einfo
[0].value_name_len
, strlen_m_term(value_name
)*2, "unexpected value_name_len");
5493 torture_assert_int_equal(tctx
, einfo
[0].type
, REG_BINARY
, "type mismatch");
5494 torture_assert_int_equal(tctx
, einfo
[0].data_length
, blob_in
.length
, "size mismatch");
5495 if (einfo
[0].data_length
> 0) {
5496 torture_assert_mem_equal(tctx
, einfo
[0].data
->data
, blob_in
.data
, blob_in
.length
, "buffer mismatch");
5499 key
= talloc_strdup(tctx
, keys
[i
]);
5501 if (!test_DeletePrinterDataEx(tctx
, b
, handle
, keys
[i
], value_name
)) {
5505 c
= strchr(key
, '\\');
5509 /* we have subkeys */
5513 if (!test_EnumPrinterKey(tctx
, b
, handle
, key
, &subkeys
)) {
5517 for (k
=0; subkeys
&& subkeys
[k
]; k
++) {
5519 const char *current_key
= talloc_asprintf(tctx
, "%s\\%s", key
, subkeys
[k
]);
5521 if (!test_DeletePrinterKey(tctx
, b
, handle
, current_key
)) {
5526 if (!test_DeletePrinterKey(tctx
, b
, handle
, key
)) {
5531 if (!test_DeletePrinterKey(tctx
, b
, handle
, key
)) {
5540 static bool test_SetPrinterDataEx_values(struct torture_context
*tctx
,
5541 struct dcerpc_pipe
*p
,
5542 struct policy_handle
*handle
)
5544 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5545 const char *key
= "torturedataex";
5546 const char *values
[] = {
5556 for (i
=0; i
< ARRAY_SIZE(values
); i
++) {
5558 enum winreg_Type type
= REG_NONE
;
5559 DATA_BLOB blob_in
= data_blob_null
;
5560 DATA_BLOB blob_out
= data_blob_null
;
5562 struct spoolss_PrinterEnumValues
*einfo
;
5563 uint32_t needed
= 0;
5565 if (torture_setting_bool(tctx
, "samba3", false)) {
5567 q
= strrchr(values
[i
], ',');
5569 torture_comment(tctx
, "skipping valuename '%s' including ',' character against Samba3\n",
5575 blob_in
= data_blob_talloc(tctx
, NULL
, 42);
5577 generate_random_buffer(blob_in
.data
, blob_in
.length
);
5579 torture_assert(tctx
,
5580 test_SetPrinterDataEx(tctx
, b
, handle
, key
, values
[i
], REG_BINARY
, blob_in
.data
, blob_in
.length
),
5581 "failed to call SetPrinterDataEx");
5583 torture_assert(tctx
,
5584 test_GetPrinterDataEx(tctx
, p
, handle
, key
, values
[i
], &type
, &blob_out
.data
, &needed
),
5585 "failed to call GetPrinterDataEx");
5587 blob_out
.length
= needed
;
5588 torture_assert(tctx
,
5589 test_EnumPrinterDataEx(tctx
, b
, handle
, key
, &ecount
, &einfo
),
5590 "failed to call EnumPrinterDataEx");
5592 torture_assert_int_equal(tctx
, type
, REG_BINARY
, "type mismatch");
5593 torture_assert_int_equal(tctx
, blob_out
.length
, blob_in
.length
, "size mismatch");
5594 torture_assert_mem_equal(tctx
, blob_out
.data
, blob_in
.data
, blob_in
.length
, "buffer mismatch");
5596 torture_assert_int_equal(tctx
, ecount
, 1, "unexpected enum count");
5597 torture_assert_str_equal(tctx
, einfo
[0].value_name
, values
[i
], "value_name mismatch");
5598 torture_assert_int_equal(tctx
, einfo
[0].value_name_len
, strlen_m_term(values
[i
])*2, "unexpected value_name_len");
5599 torture_assert_int_equal(tctx
, einfo
[0].type
, REG_BINARY
, "type mismatch");
5600 torture_assert_int_equal(tctx
, einfo
[0].data_length
, blob_in
.length
, "size mismatch");
5601 if (einfo
[0].data_length
> 0) {
5602 torture_assert_mem_equal(tctx
, einfo
[0].data
->data
, blob_in
.data
, blob_in
.length
, "buffer mismatch");
5605 torture_assert(tctx
,
5606 test_DeletePrinterDataEx(tctx
, b
, handle
, key
, values
[i
]),
5607 "failed to call DeletePrinterDataEx");
5614 static bool test_SetPrinterDataEx_matrix(struct torture_context
*tctx
,
5615 struct dcerpc_pipe
*p
,
5616 struct policy_handle
*handle
,
5617 const char *printername
,
5618 struct dcerpc_binding_handle
*winreg_handle
,
5619 struct policy_handle
*hive_handle
)
5621 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5622 const char *value_name
= "dog";
5623 const char *key_name
= "torturedataex";
5624 enum winreg_Type types
[] = {
5630 const char *str
= "abcdefghi";
5633 for (t
=0; t
< ARRAY_SIZE(types
); t
++) {
5634 for (s
=0; s
< strlen(str
); s
++) {
5636 enum winreg_Type type
;
5637 const char *string
= talloc_strndup(tctx
, str
, s
);
5638 const char *array
[2];
5639 DATA_BLOB blob
= data_blob_string_const(string
);
5642 uint32_t needed
, offered
= 0;
5644 struct spoolss_PrinterEnumValues
*einfo
;
5646 array
[0] = talloc_strdup(tctx
, string
);
5649 if (types
[t
] == REG_DWORD
) {
5656 offered
= blob
.length
;
5659 data
= data_blob_talloc(tctx
, NULL
, 4);
5660 SIVAL(data
.data
, 0, 0x12345678);
5664 torture_assert(tctx
, push_reg_sz(tctx
, &data
, string
), "");
5666 offered
= data
.length
;
5667 /*strlen_m_term(data.string)*2;*/
5670 torture_assert(tctx
, push_reg_multi_sz(tctx
, &data
, array
), "");
5671 type
= REG_MULTI_SZ
;
5672 offered
= data
.length
;
5675 torture_fail(tctx
, talloc_asprintf(tctx
, "type %d untested\n", types
[t
]));
5678 torture_assert(tctx
,
5679 test_SetPrinterDataEx(tctx
, b
, handle
, key_name
, value_name
, types
[t
], data
.data
, offered
),
5680 "failed to call SetPrinterDataEx");
5682 torture_assert(tctx
,
5683 test_GetPrinterDataEx_checktype(tctx
, p
, handle
, key_name
, value_name
, &types
[t
], &type
, &data_out
, &needed
),
5684 "failed to call GetPrinterDataEx");
5686 torture_assert(tctx
,
5687 test_EnumPrinterDataEx(tctx
, b
, handle
, key_name
, &ecount
, &einfo
),
5688 "failed to call EnumPrinterDataEx");
5690 torture_assert_int_equal(tctx
, types
[t
], type
, "type mismatch");
5691 torture_assert_int_equal(tctx
, needed
, offered
, "size mismatch");
5692 torture_assert_mem_equal(tctx
, data_out
, data
.data
, offered
, "buffer mismatch");
5694 torture_assert_int_equal(tctx
, ecount
, 1, "unexpected enum count");
5695 torture_assert_str_equal(tctx
, einfo
[0].value_name
, value_name
, "value_name mismatch");
5696 torture_assert_int_equal(tctx
, einfo
[0].value_name_len
, strlen_m_term(value_name
)*2, "unexpected value_name_len");
5697 torture_assert_int_equal(tctx
, einfo
[0].type
, types
[t
], "type mismatch");
5698 torture_assert_int_equal(tctx
, einfo
[0].data_length
, offered
, "size mismatch");
5699 if (einfo
[0].data_length
> 0) {
5700 torture_assert_mem_equal(tctx
, einfo
[0].data
->data
, data
.data
, offered
, "buffer mismatch");
5703 if (winreg_handle
&& hive_handle
) {
5704 enum winreg_Type w_type
;
5709 torture_assert(tctx
,
5710 test_winreg_query_printerdata(tctx
, winreg_handle
, hive_handle
,
5711 printername
, key_name
, value_name
,
5712 &w_type
, &w_size
, &w_length
, &w_data
), "");
5714 torture_assert_int_equal(tctx
, w_type
, types
[t
], "winreg type mismatch");
5715 torture_assert_int_equal(tctx
, w_size
, offered
, "winreg size mismatch");
5716 torture_assert_int_equal(tctx
, w_length
, offered
, "winreg length mismatch");
5717 torture_assert_mem_equal(tctx
, w_data
, data
.data
, offered
, "winreg buffer mismatch");
5720 torture_assert(tctx
,
5721 test_DeletePrinterDataEx(tctx
, b
, handle
, key_name
, value_name
),
5722 "failed to call DeletePrinterDataEx");
5729 static bool test_PrinterData_winreg(struct torture_context
*tctx
,
5730 struct dcerpc_pipe
*p
,
5731 struct policy_handle
*handle
,
5732 const char *printer_name
)
5734 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5735 struct dcerpc_pipe
*p2
;
5737 struct policy_handle hive_handle
;
5738 struct dcerpc_binding_handle
*b2
;
5740 torture_assert_ntstatus_ok(tctx
,
5741 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
5742 "could not open winreg pipe");
5743 b2
= p2
->binding_handle
;
5745 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
5747 ret
&= test_SetPrinterData_matrix(tctx
, b
, handle
, printer_name
, b2
, &hive_handle
);
5748 ret
&= test_SetPrinterDataEx_matrix(tctx
, p
, handle
, printer_name
, b2
, &hive_handle
);
5750 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
5757 static bool test_Forms_winreg(struct torture_context
*tctx
,
5758 struct dcerpc_binding_handle
*b
,
5759 struct policy_handle
*handle
,
5761 const char *printer_name
)
5763 struct dcerpc_pipe
*p2
;
5765 struct policy_handle hive_handle
;
5766 struct dcerpc_binding_handle
*b2
;
5768 torture_assert_ntstatus_ok(tctx
,
5769 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
5770 "could not open winreg pipe");
5771 b2
= p2
->binding_handle
;
5773 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
5775 ret
= test_Forms(tctx
, b
, handle
, print_server
, printer_name
, b2
, &hive_handle
);
5777 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
5784 static bool test_PrinterInfo_winreg(struct torture_context
*tctx
,
5785 struct dcerpc_pipe
*p
,
5786 struct policy_handle
*handle
,
5787 const char *printer_name
)
5789 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5790 struct dcerpc_pipe
*p2
;
5792 struct policy_handle hive_handle
;
5793 struct dcerpc_binding_handle
*b2
;
5795 torture_assert_ntstatus_ok(tctx
,
5796 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
5797 "could not open winreg pipe");
5798 b2
= p2
->binding_handle
;
5800 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
5802 ret
= test_GetPrinterInfo_winreg(tctx
, b
, handle
, printer_name
, b2
, &hive_handle
);
5804 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
5811 static bool test_PrintserverInfo_winreg(struct torture_context
*tctx
,
5812 struct dcerpc_pipe
*p
,
5813 struct policy_handle
*handle
)
5815 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5816 struct dcerpc_pipe
*p2
;
5818 struct policy_handle hive_handle
;
5819 struct dcerpc_binding_handle
*b2
;
5821 torture_assert_ntstatus_ok(tctx
,
5822 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
5823 "could not open winreg pipe");
5824 b2
= p2
->binding_handle
;
5826 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
5828 ret
= test_GetPrintserverInfo_winreg(tctx
, b
, handle
, b2
, &hive_handle
);
5830 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
5838 static bool test_DriverInfo_winreg(struct torture_context
*tctx
,
5839 struct dcerpc_pipe
*p
,
5840 struct policy_handle
*handle
,
5841 const char *printer_name
,
5842 const char *driver_name
,
5843 const char *environment
,
5844 enum spoolss_DriverOSVersion version
)
5846 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5847 struct dcerpc_pipe
*p2
;
5849 struct policy_handle hive_handle
;
5850 struct dcerpc_binding_handle
*b2
;
5852 torture_assert_ntstatus_ok(tctx
,
5853 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
5854 "could not open winreg pipe");
5855 b2
= p2
->binding_handle
;
5857 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
5859 ret
= test_GetDriverInfo_winreg(tctx
, b
, handle
, printer_name
, driver_name
, environment
, version
, b2
, &hive_handle
, NULL
);
5861 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
5868 static bool test_PrintProcessors_winreg(struct torture_context
*tctx
,
5869 struct dcerpc_binding_handle
*b
,
5870 const char *environment
)
5872 struct dcerpc_pipe
*p2
;
5874 struct policy_handle hive_handle
;
5875 struct dcerpc_binding_handle
*b2
;
5877 torture_assert_ntstatus_ok(tctx
,
5878 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
5879 "could not open winreg pipe");
5880 b2
= p2
->binding_handle
;
5882 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
5884 ret
= test_PrintProcessors(tctx
, b
, environment
, b2
, &hive_handle
);
5886 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
5893 static bool test_PrinterData_DsSpooler(struct torture_context
*tctx
,
5894 struct dcerpc_pipe
*p
,
5895 struct policy_handle
*handle
,
5896 const char *printer_name
)
5898 struct spoolss_SetPrinterInfoCtr info_ctr
;
5899 struct spoolss_DevmodeContainer devmode_ctr
;
5900 struct sec_desc_buf secdesc_ctr
;
5901 union spoolss_SetPrinterInfo sinfo
;
5902 union spoolss_PrinterInfo info
;
5903 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5906 ZERO_STRUCT(info_ctr
);
5907 ZERO_STRUCT(devmode_ctr
);
5908 ZERO_STRUCT(secdesc_ctr
);
5910 torture_comment(tctx
, "Testing DsSpooler <-> SetPrinter relations\n");
5912 torture_assert(tctx
,
5913 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
5914 "failed to query Printer level 2");
5916 torture_assert(tctx
,
5917 PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
),
5918 "failed to convert");
5921 info_ctr
.info
= sinfo
;
5923 #define TEST_SZ(wname, iname) \
5925 enum winreg_Type type;\
5930 torture_assert(tctx,\
5931 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5932 "failed to query");\
5933 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5934 blob = data_blob_const(data, needed);\
5935 torture_assert(tctx,\
5936 pull_reg_sz(tctx, &blob, &str),\
5937 "failed to pull REG_SZ");\
5938 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5942 #define TEST_SET_SZ(wname, iname, val) \
5944 enum winreg_Type type;\
5949 sinfo.info2->iname = val;\
5950 torture_assert(tctx,\
5951 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5952 "failed to call SetPrinter");\
5953 torture_assert(tctx,\
5954 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5955 "failed to query");\
5956 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5957 blob = data_blob_const(data, needed);\
5958 torture_assert(tctx,\
5959 pull_reg_sz(tctx, &blob, &str),\
5960 "failed to pull REG_SZ");\
5961 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5964 #define TEST_SET_DWORD(wname, iname, val) \
5966 enum winreg_Type type;\
5970 sinfo.info2->iname = val;\
5971 torture_assert(tctx,\
5972 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5973 "failed to call SetPrinter");\
5974 torture_assert(tctx,\
5975 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5976 "failed to query");\
5977 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5978 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5979 value = IVAL(data, 0); \
5980 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5983 TEST_SET_SZ("description", comment
, "newval");
5984 TEST_SET_SZ("location", location
, "newval");
5985 TEST_SET_SZ("driverName", drivername
, "newval");
5986 /* TEST_SET_DWORD("priority", priority, 25); */
5988 torture_assert(tctx
,
5989 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
5990 "failed to query Printer level 2");
5992 TEST_SZ("description", info
.info2
.comment
);
5993 TEST_SZ("driverName", info
.info2
.drivername
);
5994 TEST_SZ("location", info
.info2
.location
);
5996 pname
= strrchr(info
.info2
.printername
, '\\');
5997 if (pname
== NULL
) {
5998 pname
= info
.info2
.printername
;
6002 TEST_SZ("printerName", pname
);
6003 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
6004 /* TEST_SZ("printShareName", info.info2.sharename); */
6006 /* FIXME gd: complete the list */
6012 torture_comment(tctx
, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
6017 static bool test_print_processors_winreg(struct torture_context
*tctx
,
6020 struct test_spoolss_context
*ctx
=
6021 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
6022 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
6023 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6025 return test_PrintProcessors_winreg(tctx
, b
, ctx
->environment
);
6028 static bool test_AddPrintProcessor(struct torture_context
*tctx
,
6029 struct dcerpc_binding_handle
*b
,
6030 const char *environment
,
6031 const char *path_name
,
6032 const char *print_processor_name
,
6033 WERROR expected_error
)
6035 struct spoolss_AddPrintProcessor r
;
6038 r
.in
.architecture
= environment
;
6039 r
.in
.path_name
= path_name
;
6040 r
.in
.print_processor_name
= print_processor_name
;
6042 torture_comment(tctx
, "Testing AddPrintProcessor(%s)\n",
6043 print_processor_name
);
6045 torture_assert_ntstatus_ok(tctx
,
6046 dcerpc_spoolss_AddPrintProcessor_r(b
, tctx
, &r
),
6047 "spoolss_AddPrintProcessor failed");
6048 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_error
,
6049 "spoolss_AddPrintProcessor failed");
6054 static bool test_DeletePrintProcessor(struct torture_context
*tctx
,
6055 struct dcerpc_binding_handle
*b
,
6056 const char *environment
,
6057 const char *print_processor_name
,
6058 WERROR expected_error
)
6060 struct spoolss_DeletePrintProcessor r
;
6063 r
.in
.architecture
= environment
;
6064 r
.in
.print_processor_name
= print_processor_name
;
6066 torture_comment(tctx
, "Testing DeletePrintProcessor(%s)\n",
6067 print_processor_name
);
6069 torture_assert_ntstatus_ok(tctx
,
6070 dcerpc_spoolss_DeletePrintProcessor_r(b
, tctx
, &r
),
6071 "spoolss_DeletePrintProcessor failed");
6072 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_error
,
6073 "spoolss_DeletePrintProcessor failed");
6078 static bool test_add_print_processor(struct torture_context
*tctx
,
6081 struct test_spoolss_context
*ctx
=
6082 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
6083 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
6084 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6088 const char *environment
;
6089 const char *path_name
;
6090 const char *print_processor_name
;
6091 WERROR expected_add_result
;
6092 WERROR expected_del_result
;
6095 .environment
= ctx
->environment
,
6097 .print_processor_name
= "winprint",
6098 .expected_add_result
= WERR_PRINT_PROCESSOR_ALREADY_INSTALLED
,
6099 .expected_del_result
= WERR_CAN_NOT_COMPLETE
6101 .environment
= ctx
->environment
,
6103 .print_processor_name
= "unknown",
6104 .expected_add_result
= WERR_MOD_NOT_FOUND
,
6105 .expected_del_result
= WERR_UNKNOWN_PRINTPROCESSOR
6109 for (i
=0; i
< ARRAY_SIZE(tests
); i
++) {
6110 torture_assert(tctx
,
6111 test_AddPrintProcessor(tctx
, b
,
6112 tests
[i
].environment
,
6114 tests
[i
].print_processor_name
,
6115 tests
[i
].expected_add_result
),
6116 "add print processor failed");
6117 torture_assert(tctx
,
6118 test_DeletePrintProcessor(tctx
, b
,
6119 tests
[i
].environment
,
6120 tests
[i
].print_processor_name
,
6121 tests
[i
].expected_del_result
),
6122 "delete print processor failed");
6128 static bool test_GetChangeID_PrinterData(struct torture_context
*tctx
,
6129 struct dcerpc_binding_handle
*b
,
6130 struct policy_handle
*handle
,
6131 uint32_t *change_id
)
6133 enum winreg_Type type
;
6137 torture_assert(tctx
,
6138 test_GetPrinterData(tctx
, b
, handle
, "ChangeID", &type
, &data
, &needed
),
6139 "failed to call GetPrinterData");
6141 torture_assert(tctx
, type
== REG_DWORD
, "unexpected type");
6142 torture_assert_int_equal(tctx
, needed
, 4, "unexpected size");
6144 *change_id
= IVAL(data
, 0);
6149 static bool test_GetChangeID_PrinterDataEx(struct torture_context
*tctx
,
6150 struct dcerpc_pipe
*p
,
6151 struct policy_handle
*handle
,
6152 uint32_t *change_id
)
6154 enum winreg_Type type
= REG_NONE
;
6155 uint8_t *data
= NULL
;
6156 uint32_t needed
= 0;
6158 torture_assert(tctx
,
6159 test_GetPrinterDataEx(tctx
, p
, handle
, "PrinterDriverData", "ChangeID", &type
, &data
, &needed
),
6160 "failed to call GetPrinterData");
6162 torture_assert(tctx
, type
== REG_DWORD
, "unexpected type");
6163 torture_assert_int_equal(tctx
, needed
, 4, "unexpected size");
6165 *change_id
= IVAL(data
, 0);
6170 static bool test_GetChangeID_PrinterInfo(struct torture_context
*tctx
,
6171 struct dcerpc_binding_handle
*b
,
6172 struct policy_handle
*handle
,
6173 uint32_t *change_id
)
6175 union spoolss_PrinterInfo info
;
6177 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 0, &info
),
6178 "failed to query Printer level 0");
6180 *change_id
= info
.info0
.change_id
;
6185 static bool test_ChangeID(struct torture_context
*tctx
,
6186 struct dcerpc_pipe
*p
,
6187 struct policy_handle
*handle
)
6189 uint32_t change_id
, change_id_ex
, change_id_info
;
6190 uint32_t change_id2
, change_id_ex2
, change_id_info2
;
6191 union spoolss_PrinterInfo info
;
6192 const char *comment
;
6193 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6195 torture_comment(tctx
, "Testing ChangeID: id change test #1\n");
6197 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id
),
6198 "failed to query for ChangeID");
6199 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex
),
6200 "failed to query for ChangeID");
6201 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info
),
6202 "failed to query for ChangeID");
6204 torture_assert_int_equal(tctx
, change_id
, change_id_ex
,
6205 "change_ids should all be equal");
6206 torture_assert_int_equal(tctx
, change_id_ex
, change_id_info
,
6207 "change_ids should all be equal");
6210 torture_comment(tctx
, "Testing ChangeID: id change test #2\n");
6212 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id
),
6213 "failed to query for ChangeID");
6214 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
6215 "failed to query Printer level 2");
6216 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex
),
6217 "failed to query for ChangeID");
6218 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info
),
6219 "failed to query for ChangeID");
6220 torture_assert_int_equal(tctx
, change_id
, change_id_ex
,
6221 "change_id should not have changed");
6222 torture_assert_int_equal(tctx
, change_id_ex
, change_id_info
,
6223 "change_id should not have changed");
6226 torture_comment(tctx
, "Testing ChangeID: id change test #3\n");
6228 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id
),
6229 "failed to query for ChangeID");
6230 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex
),
6231 "failed to query for ChangeID");
6232 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info
),
6233 "failed to query for ChangeID");
6234 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
6235 "failed to query Printer level 2");
6236 comment
= talloc_strdup(tctx
, info
.info2
.comment
);
6239 struct spoolss_SetPrinterInfoCtr info_ctr
;
6240 struct spoolss_DevmodeContainer devmode_ctr
;
6241 struct sec_desc_buf secdesc_ctr
;
6242 union spoolss_SetPrinterInfo sinfo
;
6244 ZERO_STRUCT(info_ctr
);
6245 ZERO_STRUCT(devmode_ctr
);
6246 ZERO_STRUCT(secdesc_ctr
);
6249 torture_assert(tctx
, PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
6250 sinfo
.info2
->comment
= "torture_comment";
6253 info_ctr
.info
= sinfo
;
6255 torture_assert(tctx
, test_SetPrinter(tctx
, b
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0),
6256 "failed to call SetPrinter");
6258 sinfo
.info2
->comment
= comment
;
6260 torture_assert(tctx
, test_SetPrinter(tctx
, b
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0),
6261 "failed to call SetPrinter");
6265 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id2
),
6266 "failed to query for ChangeID");
6267 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex2
),
6268 "failed to query for ChangeID");
6269 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info2
),
6270 "failed to query for ChangeID");
6272 torture_assert_int_equal(tctx
, change_id2
, change_id_ex2
,
6273 "change_ids should all be equal");
6274 torture_assert_int_equal(tctx
, change_id_ex2
, change_id_info2
,
6275 "change_ids should all be equal");
6277 torture_assert(tctx
, (change_id
< change_id2
),
6278 talloc_asprintf(tctx
, "change_id %d needs to be larger than change_id %d",
6279 change_id2
, change_id
));
6280 torture_assert(tctx
, (change_id_ex
< change_id_ex2
),
6281 talloc_asprintf(tctx
, "change_id %d needs to be larger than change_id %d",
6282 change_id_ex2
, change_id_ex
));
6283 torture_assert(tctx
, (change_id_info
< change_id_info2
),
6284 talloc_asprintf(tctx
, "change_id %d needs to be larger than change_id %d",
6285 change_id_info2
, change_id_info
));
6287 torture_comment(tctx
, "ChangeID tests succeeded\n\n");
6292 static bool test_SecondaryClosePrinter(struct torture_context
*tctx
,
6293 struct dcerpc_pipe
*p
,
6294 struct policy_handle
*handle
)
6297 struct cli_credentials
*anon_creds
;
6298 const struct dcerpc_binding
*binding2
;
6299 struct dcerpc_pipe
*p2
;
6300 struct spoolss_ClosePrinter cp
;
6302 /* only makes sense on SMB */
6303 if (p
->conn
->transport
.transport
!= NCACN_NP
) {
6307 torture_comment(tctx
, "Testing close on secondary pipe\n");
6309 anon_creds
= cli_credentials_init_anon(tctx
);
6310 torture_assert(tctx
, anon_creds
!= NULL
, "cli_credentials_init_anon failed");
6312 binding2
= p
->binding
;
6313 status
= dcerpc_secondary_auth_connection(p
, binding2
, &ndr_table_spoolss
,
6314 anon_creds
, tctx
->lp_ctx
,
6316 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create secondary connection");
6318 cp
.in
.handle
= handle
;
6319 cp
.out
.handle
= handle
;
6321 status
= dcerpc_spoolss_ClosePrinter_r(p2
->binding_handle
, tctx
, &cp
);
6322 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_RPC_SS_CONTEXT_MISMATCH
,
6323 "ERROR: Allowed close on secondary connection");
6330 static bool test_OpenPrinter_badname(struct torture_context
*tctx
,
6331 struct dcerpc_binding_handle
*b
, const char *name
)
6334 struct spoolss_OpenPrinter op
;
6335 struct spoolss_OpenPrinterEx opEx
;
6336 struct policy_handle handle
;
6339 op
.in
.printername
= name
;
6340 op
.in
.datatype
= NULL
;
6341 op
.in
.devmode_ctr
.devmode
= NULL
;
6342 op
.in
.access_mask
= 0;
6343 op
.out
.handle
= &handle
;
6345 torture_comment(tctx
, "Testing OpenPrinter(%s) with bad name\n", op
.in
.printername
);
6347 status
= dcerpc_spoolss_OpenPrinter_r(b
, tctx
, &op
);
6348 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
6349 torture_assert_werr_equal(tctx
, op
.out
.result
, WERR_INVALID_PRINTER_NAME
,
6350 "unexpected result");
6352 if (W_ERROR_IS_OK(op
.out
.result
)) {
6353 ret
&=test_ClosePrinter(tctx
, b
, &handle
);
6356 opEx
.in
.printername
= name
;
6357 opEx
.in
.datatype
= NULL
;
6358 opEx
.in
.devmode_ctr
.devmode
= NULL
;
6359 opEx
.in
.access_mask
= 0;
6360 opEx
.in
.userlevel_ctr
.level
= 1;
6361 opEx
.in
.userlevel_ctr
.user_info
.level1
= NULL
;
6362 opEx
.out
.handle
= &handle
;
6364 torture_comment(tctx
, "Testing OpenPrinterEx(%s) with bad name\n", opEx
.in
.printername
);
6366 status
= dcerpc_spoolss_OpenPrinterEx_r(b
, tctx
, &opEx
);
6367 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinterEx failed");
6368 torture_assert_werr_equal(tctx
, opEx
.out
.result
, WERR_INVALID_PARAMETER
,
6369 "unexpected result");
6371 if (W_ERROR_IS_OK(opEx
.out
.result
)) {
6372 ret
&=test_ClosePrinter(tctx
, b
, &handle
);
6378 static bool test_OpenPrinter_badname_list(struct torture_context
*tctx
,
6381 struct test_spoolss_context
*ctx
=
6382 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
6384 const char *badnames
[] = {
6385 "__INVALID_PRINTER__",
6386 "\\\\__INVALID_HOST__",
6389 "\\\\\\__INVALID_PRINTER__"
6391 const char *badname
;
6392 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
6393 const char *server_name
= dcerpc_server_name(p
);
6394 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6397 for (i
=0; i
< ARRAY_SIZE(badnames
); i
++) {
6398 torture_assert(tctx
,
6399 test_OpenPrinter_badname(tctx
, b
, badnames
[i
]),
6403 badname
= talloc_asprintf(tctx
, "\\\\%s\\", server_name
);
6404 torture_assert(tctx
,
6405 test_OpenPrinter_badname(tctx
, b
, badname
),
6408 badname
= talloc_asprintf(tctx
, "\\\\%s\\__INVALID_PRINTER__", server_name
);
6409 torture_assert(tctx
,
6410 test_OpenPrinter_badname(tctx
, b
, badname
),
6416 static bool test_OpenPrinter(struct torture_context
*tctx
,
6417 struct dcerpc_pipe
*p
,
6419 const char *environment
,
6423 struct spoolss_OpenPrinter r
;
6424 struct policy_handle handle
;
6426 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6428 r
.in
.printername
= name
;
6429 r
.in
.datatype
= NULL
;
6430 r
.in
.devmode_ctr
.devmode
= NULL
;
6431 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
6432 r
.out
.handle
= &handle
;
6434 torture_comment(tctx
, "Testing OpenPrinter(%s)\n", r
.in
.printername
);
6436 status
= dcerpc_spoolss_OpenPrinter_r(b
, tctx
, &r
);
6438 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
6440 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenPrinter failed");
6446 if (!test_GetPrinter(tctx
, b
, &handle
, environment
)) {
6450 if (!torture_setting_bool(tctx
, "samba3", false)) {
6451 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
6457 if (!test_ClosePrinter(tctx
, b
, &handle
)) {
6464 static bool test_OpenPrinterEx(struct torture_context
*tctx
,
6465 struct dcerpc_binding_handle
*b
,
6466 const char *printername
,
6467 const char *datatype
,
6468 struct spoolss_DeviceMode
*devmode
,
6469 uint32_t access_mask
,
6470 struct spoolss_UserLevelCtr
*userlevel_ctr
,
6471 struct policy_handle
*handle
,
6472 WERROR expected_result
)
6474 struct spoolss_OpenPrinterEx r
;
6476 r
.in
.printername
= printername
;
6477 r
.in
.datatype
= datatype
;
6478 r
.in
.devmode_ctr
.devmode
= devmode
;
6479 r
.in
.access_mask
= access_mask
;
6480 r
.in
.userlevel_ctr
= *userlevel_ctr
;
6481 r
.out
.handle
= handle
;
6483 torture_comment(tctx
, "Testing OpenPrinterEx(%s)\n", r
.in
.printername
);
6485 torture_assert_ntstatus_ok(tctx
,
6486 dcerpc_spoolss_OpenPrinterEx_r(b
, tctx
, &r
),
6487 "OpenPrinterEx failed");
6489 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
6490 "OpenPrinterEx failed");
6495 static bool call_OpenPrinterEx(struct torture_context
*tctx
,
6496 struct dcerpc_pipe
*p
,
6498 struct spoolss_DeviceMode
*devmode
,
6499 struct policy_handle
*handle
)
6501 struct spoolss_UserLevelCtr userlevel_ctr
;
6502 struct spoolss_UserLevel1 userlevel1
;
6503 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6505 userlevel1
.size
= 1234;
6506 userlevel1
.client
= "hello";
6507 userlevel1
.user
= "spottyfoot!";
6508 userlevel1
.build
= 1;
6509 userlevel1
.major
= 2;
6510 userlevel1
.minor
= 3;
6511 userlevel1
.processor
= 4;
6513 userlevel_ctr
.level
= 1;
6514 userlevel_ctr
.user_info
.level1
= &userlevel1
;
6516 return test_OpenPrinterEx(tctx
, b
, name
, NULL
, devmode
,
6517 SEC_FLAG_MAXIMUM_ALLOWED
,
6523 static bool test_printer_rename(struct torture_context
*tctx
,
6526 struct torture_printer_context
*t
=
6527 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
6528 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
6531 union spoolss_PrinterInfo info
;
6532 union spoolss_SetPrinterInfo sinfo
;
6533 struct spoolss_SetPrinterInfoCtr info_ctr
;
6534 struct spoolss_DevmodeContainer devmode_ctr
;
6535 struct sec_desc_buf secdesc_ctr
;
6536 const char *printer_name
;
6537 const char *printer_name_orig
;
6538 const char *printer_name_new
= "SAMBA smbtorture Test Printer (Copy 2)";
6539 struct policy_handle new_handle
;
6541 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6543 ZERO_STRUCT(devmode_ctr
);
6544 ZERO_STRUCT(secdesc_ctr
);
6546 torture_comment(tctx
, "Testing Printer rename operations\n");
6548 torture_assert(tctx
,
6549 test_GetPrinter_level(tctx
, b
, &t
->handle
, 2, &info
),
6550 "failed to call GetPrinter level 2");
6552 printer_name_orig
= talloc_strdup(tctx
, info
.info2
.printername
);
6554 q
= strrchr(info
.info2
.printername
, '\\');
6556 torture_warning(tctx
,
6557 "server returns printername %s incl. servername although we did not set servername", info
.info2
.printername
);
6560 torture_assert(tctx
,
6561 PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
6563 sinfo
.info2
->printername
= printer_name_new
;
6566 info_ctr
.info
= sinfo
;
6568 torture_assert(tctx
,
6569 test_SetPrinter(tctx
, b
, &t
->handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0),
6570 "failed to call SetPrinter level 2");
6572 torture_assert(tctx
,
6573 test_GetPrinter_level(tctx
, b
, &t
->handle
, 2, &info
),
6574 "failed to call GetPrinter level 2");
6576 printer_name
= talloc_strdup(tctx
, info
.info2
.printername
);
6578 q
= strrchr(info
.info2
.printername
, '\\');
6580 torture_warning(tctx
,
6581 "server returns printername %s incl. servername although we did not set servername", info
.info2
.printername
);
6586 torture_assert_str_equal(tctx
, printer_name
, printer_name_new
,
6587 "new printer name was not set");
6589 /* samba currently cannot fully rename printers */
6590 if (!torture_setting_bool(tctx
, "samba3", false)) {
6591 torture_assert(tctx
,
6592 test_OpenPrinter_badname(tctx
, b
, printer_name_orig
),
6593 "still can open printer with oldname after rename");
6595 torture_warning(tctx
, "*not* checking for open with oldname after rename for samba3");
6598 torture_assert(tctx
,
6599 call_OpenPrinterEx(tctx
, p
, printer_name_new
, NULL
, &new_handle
),
6600 "failed to open printer with new name");
6602 torture_assert(tctx
,
6603 test_GetPrinter_level(tctx
, b
, &new_handle
, 2, &info
),
6604 "failed to call GetPrinter level 2");
6606 torture_assert_str_equal(tctx
, info
.info2
.printername
, printer_name_new
,
6607 "new printer name was not set");
6609 torture_assert(tctx
,
6610 test_ClosePrinter(tctx
, b
, &new_handle
),
6611 "failed to close printer");
6613 torture_comment(tctx
, "Printer rename operations test succeeded\n\n");
6618 static bool test_openprinter(struct torture_context
*tctx
,
6619 struct dcerpc_binding_handle
*b
,
6620 const char *real_printername
)
6622 struct spoolss_UserLevelCtr userlevel_ctr
;
6623 struct policy_handle handle
;
6624 struct spoolss_UserLevel1 userlevel1
;
6625 const char *printername
= NULL
;
6630 WERROR expected_result
;
6633 .suffix
= "rubbish",
6634 .expected_result
= WERR_INVALID_PRINTER_NAME
6636 .suffix
= ", LocalOnl",
6637 .expected_result
= WERR_INVALID_PRINTER_NAME
6639 .suffix
= ", localOnly",
6640 .expected_result
= WERR_INVALID_PRINTER_NAME
6642 .suffix
= ", localonl",
6643 .expected_result
= WERR_INVALID_PRINTER_NAME
6645 .suffix
= ",LocalOnl",
6646 .expected_result
= WERR_INVALID_PRINTER_NAME
6648 .suffix
= ",localOnl2",
6649 .expected_result
= WERR_INVALID_PRINTER_NAME
6651 .suffix
= ", DrvConver2t",
6652 .expected_result
= WERR_INVALID_PRINTER_NAME
6654 .suffix
= ", drvconvert",
6655 .expected_result
= WERR_INVALID_PRINTER_NAME
6657 .suffix
= ",drvconvert",
6658 .expected_result
= WERR_INVALID_PRINTER_NAME
6660 .suffix
= ", DrvConvert",
6661 .expected_result
= WERR_OK
6663 .suffix
= " , DrvConvert",
6664 .expected_result
= WERR_INVALID_PRINTER_NAME
6666 .suffix
= ",DrvConvert",
6667 .expected_result
= WERR_OK
6669 .suffix
= ", DrvConvertsadfasdf",
6670 .expected_result
= WERR_OK
6672 .suffix
= ",DrvConvertasdfasd",
6673 .expected_result
= WERR_OK
6675 .suffix
= ", LocalOnly",
6676 .expected_result
= WERR_OK
6678 .suffix
= " , LocalOnly",
6679 .expected_result
= WERR_INVALID_PRINTER_NAME
6681 .suffix
= ",LocalOnly",
6682 .expected_result
= WERR_OK
6684 .suffix
= ", LocalOnlysagi4gjfkd",
6685 .expected_result
= WERR_OK
6687 .suffix
= ",LocalOnlysagi4gjfkd",
6688 .expected_result
= WERR_OK
6692 userlevel1
.size
= 1234;
6693 userlevel1
.client
= "hello";
6694 userlevel1
.user
= "spottyfoot!";
6695 userlevel1
.build
= 1;
6696 userlevel1
.major
= 2;
6697 userlevel1
.minor
= 3;
6698 userlevel1
.processor
= 4;
6700 userlevel_ctr
.level
= 1;
6701 userlevel_ctr
.user_info
.level1
= &userlevel1
;
6703 torture_comment(tctx
, "Testing openprinterex printername pattern\n");
6705 torture_assert(tctx
,
6706 test_OpenPrinterEx(tctx
, b
, real_printername
, NULL
, NULL
, 0,
6707 &userlevel_ctr
, &handle
,
6709 "OpenPrinterEx failed");
6710 test_ClosePrinter(tctx
, b
, &handle
);
6712 for (i
=0; i
< ARRAY_SIZE(tests
); i
++) {
6714 printername
= talloc_asprintf(tctx
, "%s%s",
6718 torture_assert(tctx
,
6719 test_OpenPrinterEx(tctx
, b
, printername
, NULL
, NULL
, 0,
6720 &userlevel_ctr
, &handle
,
6721 tests
[i
].expected_result
),
6722 "OpenPrinterEx failed");
6723 if (W_ERROR_IS_OK(tests
[i
].expected_result
)) {
6724 test_ClosePrinter(tctx
, b
, &handle
);
6732 static bool test_existing_printer_openprinterex(struct torture_context
*tctx
,
6733 struct dcerpc_pipe
*p
,
6735 const char *environment
)
6737 struct policy_handle handle
;
6739 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6741 if (!test_openprinter(tctx
, b
, name
)) {
6745 if (!call_OpenPrinterEx(tctx
, p
, name
, NULL
, &handle
)) {
6749 if (!test_PrinterInfo_SD(tctx
, b
, &handle
)) {
6753 if (!test_GetPrinter(tctx
, b
, &handle
, environment
)) {
6757 if (!test_EnumForms_all(tctx
, b
, &handle
, false)) {
6761 if (!test_Forms(tctx
, b
, &handle
, false, name
, NULL
, NULL
)) {
6765 if (!test_Forms_winreg(tctx
, b
, &handle
, false, name
)) {
6769 if (!test_EnumPrinterData_all(tctx
, p
, &handle
)) {
6773 if (!test_EnumPrinterDataEx(tctx
, b
, &handle
, "PrinterDriverData", NULL
, NULL
)) {
6777 if (!test_EnumPrinterData_consistency(tctx
, p
, &handle
)) {
6781 if (!test_printer_all_keys(tctx
, b
, &handle
)) {
6785 if (!test_PausePrinter(tctx
, b
, &handle
)) {
6789 if (!test_DoPrintTest(tctx
, b
, &handle
)) {
6793 if (!test_ResumePrinter(tctx
, b
, &handle
)) {
6797 if (!test_SetPrinterData_matrix(tctx
, b
, &handle
, name
, NULL
, NULL
)) {
6801 if (!test_SetPrinterDataEx_matrix(tctx
, p
, &handle
, name
, NULL
, NULL
)) {
6805 if (!torture_setting_bool(tctx
, "samba3", false)) {
6806 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
6811 if (!test_ClosePrinter(tctx
, b
, &handle
)) {
6818 static bool test_EnumPrinters_old(struct torture_context
*tctx
,
6821 struct test_spoolss_context
*ctx
=
6822 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
6823 struct spoolss_EnumPrinters r
;
6825 uint16_t levels
[] = {1, 2, 4, 5};
6828 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
6829 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6831 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
6832 union spoolss_PrinterInfo
*info
;
6837 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
6839 r
.in
.level
= levels
[i
];
6842 r
.out
.needed
= &needed
;
6843 r
.out
.count
= &count
;
6846 torture_comment(tctx
, "Testing EnumPrinters level %u\n", r
.in
.level
);
6848 status
= dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &r
);
6849 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
6851 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
6852 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
6853 r
.in
.buffer
= &blob
;
6854 r
.in
.offered
= needed
;
6855 status
= dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &r
);
6858 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
6860 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
6862 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters
, info
, r
.in
.level
, count
, needed
, 4);
6865 torture_comment(tctx
, "No printers returned\n");
6869 for (j
=0;j
<count
;j
++) {
6870 if (r
.in
.level
== 1) {
6871 char *unc
= talloc_strdup(tctx
, info
[j
].info1
.name
);
6872 char *slash
, *name
, *full_name
;
6874 if (unc
[0] == '\\' && unc
[1] == '\\') {
6877 slash
= strchr(unc
, '\\');
6882 full_name
= talloc_asprintf(tctx
, "\\\\%s\\%s",
6883 dcerpc_server_name(p
), name
);
6884 if (!test_OpenPrinter(tctx
, p
, name
, ctx
->environment
, true)) {
6887 if (!test_OpenPrinter(tctx
, p
, full_name
, ctx
->environment
, true)) {
6890 if (!test_OpenPrinter(tctx
, p
, name
, ctx
->environment
, false)) {
6893 if (!test_existing_printer_openprinterex(tctx
, p
, name
, ctx
->environment
)) {
6903 static bool test_EnumPrinters_level(struct torture_context
*tctx
,
6904 struct dcerpc_binding_handle
*b
,
6906 const char *servername
,
6909 union spoolss_PrinterInfo
**info_p
)
6911 struct spoolss_EnumPrinters r
;
6912 union spoolss_PrinterInfo
*info
;
6917 r
.in
.server
= servername
;
6921 r
.out
.needed
= &needed
;
6922 r
.out
.count
= &count
;
6925 torture_comment(tctx
, "Testing EnumPrinters(%s) level %u\n",
6926 r
.in
.server
, r
.in
.level
);
6928 torture_assert_ntstatus_ok(tctx
,
6929 dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &r
),
6930 "EnumPrinters failed");
6931 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
6932 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
6933 r
.in
.buffer
= &blob
;
6934 r
.in
.offered
= needed
;
6935 torture_assert_ntstatus_ok(tctx
,
6936 dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &r
),
6937 "EnumPrinters failed");
6940 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
6942 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters
, info
, r
.in
.level
, count
, needed
, 4);
6954 static const char *get_short_printername(struct torture_context
*tctx
,
6957 const char *short_name
;
6959 if (name
[0] == '\\' && name
[1] == '\\') {
6961 short_name
= strchr(name
, '\\');
6963 return talloc_strdup(tctx
, short_name
+1);
6970 static const char *get_full_printername(struct torture_context
*tctx
,
6973 const char *full_name
= talloc_strdup(tctx
, name
);
6976 if (name
&& name
[0] == '\\' && name
[1] == '\\') {
6978 p
= strchr(name
, '\\');
6987 static bool test_OnePrinter_servername(struct torture_context
*tctx
,
6988 struct dcerpc_pipe
*p
,
6989 struct dcerpc_binding_handle
*b
,
6990 const char *servername
,
6991 const char *printername
)
6993 union spoolss_PrinterInfo info
;
6994 const char *short_name
= get_short_printername(tctx
, printername
);
6995 const char *full_name
= get_full_printername(tctx
, printername
);
6998 struct policy_handle handle
;
6999 torture_assert(tctx
,
7000 call_OpenPrinterEx(tctx
, p
, short_name
, NULL
, &handle
),
7001 "failed to open printer");
7003 torture_assert(tctx
,
7004 test_GetPrinter_level(tctx
, b
, &handle
, 2, &info
),
7005 "failed to get printer info");
7007 torture_assert_casestr_equal(tctx
, info
.info2
.servername
, NULL
,
7008 "unexpected servername");
7009 torture_assert_casestr_equal(tctx
, info
.info2
.printername
, short_name
,
7010 "unexpected printername");
7012 if (info
.info2
.devmode
) {
7013 const char *expected_devicename
;
7014 expected_devicename
= talloc_strndup(tctx
, short_name
, MIN(strlen(short_name
), 31));
7015 torture_assert_casestr_equal(tctx
, info
.info2
.devmode
->devicename
, expected_devicename
,
7016 "unexpected devicemode devicename");
7019 torture_assert(tctx
,
7020 test_ClosePrinter(tctx
, b
, &handle
),
7021 "failed to close printer");
7025 struct policy_handle handle
;
7027 torture_assert(tctx
,
7028 call_OpenPrinterEx(tctx
, p
, full_name
, NULL
, &handle
),
7029 "failed to open printer");
7031 torture_assert(tctx
,
7032 test_GetPrinter_level(tctx
, b
, &handle
, 2, &info
),
7033 "failed to get printer info");
7035 torture_assert_casestr_equal(tctx
, info
.info2
.servername
, servername
,
7036 "unexpected servername");
7037 torture_assert_casestr_equal(tctx
, info
.info2
.printername
, full_name
,
7038 "unexpected printername");
7040 if (info
.info2
.devmode
) {
7041 const char *expected_devicename
;
7042 expected_devicename
= talloc_strndup(tctx
, full_name
, MIN(strlen(full_name
), 31));
7043 torture_assert_casestr_equal(tctx
, info
.info2
.devmode
->devicename
, expected_devicename
,
7044 "unexpected devicemode devicename");
7047 torture_assert(tctx
,
7048 test_ClosePrinter(tctx
, b
, &handle
),
7049 "failed to close printer");
7055 static bool test_EnumPrinters_servername(struct torture_context
*tctx
,
7058 struct test_spoolss_context
*ctx
=
7059 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
7061 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
7062 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7064 union spoolss_PrinterInfo
*info
;
7065 const char *servername
;
7066 uint32_t flags
= PRINTER_ENUM_NAME
|PRINTER_ENUM_LOCAL
;
7068 torture_comment(tctx
, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
7070 servername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
7072 torture_assert(tctx
,
7073 test_EnumPrinters_level(tctx
, b
, flags
, servername
, 2, &count
, &info
),
7074 "failed to enumerate printers");
7076 for (i
=0; i
< count
; i
++) {
7078 torture_assert_casestr_equal(tctx
, info
[i
].info2
.servername
, servername
,
7079 "unexpected servername");
7081 torture_assert(tctx
,
7082 test_OnePrinter_servername(tctx
, p
, b
, servername
, info
[i
].info2
.printername
),
7083 "failed to check printer");
7088 torture_assert(tctx
,
7089 test_EnumPrinters_level(tctx
, b
, flags
, servername
, 2, &count
, &info
),
7090 "failed to enumerate printers");
7092 for (i
=0; i
< count
; i
++) {
7094 torture_assert_casestr_equal(tctx
, info
[i
].info2
.servername
, NULL
,
7095 "unexpected servername");
7097 torture_assert(tctx
,
7098 test_OnePrinter_servername(tctx
, p
, b
, servername
, info
[i
].info2
.printername
),
7099 "failed to check printer");
7107 static bool test_GetPrinterDriver(struct torture_context
*tctx
,
7108 struct dcerpc_binding_handle
*b
,
7109 struct policy_handle
*handle
,
7110 const char *driver_name
)
7112 struct spoolss_GetPrinterDriver r
;
7115 r
.in
.handle
= handle
;
7116 r
.in
.architecture
= "W32X86";
7120 r
.out
.needed
= &needed
;
7122 torture_comment(tctx
, "Testing GetPrinterDriver level %d\n", r
.in
.level
);
7124 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver_r(b
, tctx
, &r
),
7125 "failed to call GetPrinterDriver");
7126 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
7127 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
7128 r
.in
.buffer
= &blob
;
7129 r
.in
.offered
= needed
;
7130 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver_r(b
, tctx
, &r
),
7131 "failed to call GetPrinterDriver");
7134 torture_assert_werr_ok(tctx
, r
.out
.result
,
7135 "failed to call GetPrinterDriver");
7137 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo
, r
.out
.info
, r
.in
.level
, needed
, 4);
7143 static bool test_GetPrinterDriver2_level(struct torture_context
*tctx
,
7144 struct dcerpc_binding_handle
*b
,
7145 struct policy_handle
*handle
,
7146 const char *driver_name
,
7147 const char *architecture
,
7149 uint32_t client_major_version
,
7150 uint32_t client_minor_version
,
7151 union spoolss_DriverInfo
*info_p
,
7155 struct spoolss_GetPrinterDriver2 r
;
7157 uint32_t server_major_version
;
7158 uint32_t server_minor_version
;
7160 r
.in
.handle
= handle
;
7161 r
.in
.architecture
= architecture
;
7162 r
.in
.client_major_version
= client_major_version
;
7163 r
.in
.client_minor_version
= client_minor_version
;
7167 r
.out
.needed
= &needed
;
7168 r
.out
.server_major_version
= &server_major_version
;
7169 r
.out
.server_minor_version
= &server_minor_version
;
7171 torture_comment(tctx
, "Testing GetPrinterDriver2(%s) level %d\n",
7172 driver_name
, r
.in
.level
);
7174 torture_assert_ntstatus_ok(tctx
,
7175 dcerpc_spoolss_GetPrinterDriver2_r(b
, tctx
, &r
),
7176 "failed to call GetPrinterDriver2");
7177 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
7178 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
7179 r
.in
.buffer
= &blob
;
7180 r
.in
.offered
= needed
;
7181 torture_assert_ntstatus_ok(tctx
,
7182 dcerpc_spoolss_GetPrinterDriver2_r(b
, tctx
, &r
),
7183 "failed to call GetPrinterDriver2");
7187 *result_p
= r
.out
.result
;
7190 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INVALID_LEVEL
)) {
7191 switch (r
.in
.level
) {
7194 torture_comment(tctx
,
7195 "level %d not implemented, not considering as an error\n",
7203 torture_assert_werr_ok(tctx
, r
.out
.result
,
7204 "failed to call GetPrinterDriver2");
7206 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo
, r
.out
.info
, r
.in
.level
, needed
, 4);
7209 *info_p
= *r
.out
.info
;
7215 static bool test_GetPrinterDriver2(struct torture_context
*tctx
,
7216 struct dcerpc_binding_handle
*b
,
7217 struct policy_handle
*handle
,
7218 const char *driver_name
,
7219 const char *architecture
)
7221 uint16_t levels
[] = {1, 2, 3, 4, 5, 6, 8, 101 };
7225 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
7227 torture_assert(tctx
,
7228 test_GetPrinterDriver2_level(tctx
, b
, handle
, driver_name
, architecture
, levels
[i
], 3, 0, NULL
, NULL
),
7235 static bool test_EnumPrinterDrivers_old(struct torture_context
*tctx
,
7238 struct test_spoolss_context
*ctx
=
7239 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
7240 uint16_t levels
[] = {1, 2, 3, 4, 5, 6};
7242 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
7243 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7244 const char *server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
7246 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
7249 union spoolss_DriverInfo
*info
;
7251 torture_assert(tctx
,
7252 test_EnumPrinterDrivers_args(tctx
, b
, server_name
, ctx
->environment
, levels
[i
], &count
, &info
),
7253 "failed to enumerate drivers");
7256 torture_comment(tctx
, "No printer drivers returned\n");
7264 static bool test_DeletePrinter(struct torture_context
*tctx
,
7265 struct dcerpc_binding_handle
*b
,
7266 struct policy_handle
*handle
)
7268 struct spoolss_DeletePrinter r
;
7270 torture_comment(tctx
, "Testing DeletePrinter\n");
7272 r
.in
.handle
= handle
;
7274 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_DeletePrinter_r(b
, tctx
, &r
),
7275 "failed to delete printer");
7276 torture_assert_werr_ok(tctx
, r
.out
.result
,
7277 "failed to delete printer");
7282 static bool test_EnumPrinters_findname(struct torture_context
*tctx
,
7283 struct dcerpc_binding_handle
*b
,
7289 struct spoolss_EnumPrinters e
;
7291 union spoolss_PrinterInfo
*info
;
7302 e
.out
.count
= &count
;
7304 e
.out
.needed
= &needed
;
7306 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &e
),
7307 "failed to enum printers");
7309 if (W_ERROR_EQUAL(e
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
7310 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
7311 e
.in
.buffer
= &blob
;
7312 e
.in
.offered
= needed
;
7314 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &e
),
7315 "failed to enum printers");
7318 torture_assert_werr_ok(tctx
, e
.out
.result
,
7319 "failed to enum printers");
7321 for (i
=0; i
< count
; i
++) {
7323 const char *current
= NULL
;
7328 current
= info
[i
].info1
.name
;
7332 if (strequal(current
, name
)) {
7337 q
= strrchr(current
, '\\');
7340 torture_warning(tctx
,
7341 "server returns printername %s incl. servername although we did not set servername", current
);
7344 if (strequal(q
, name
)) {
7354 static bool test_AddPrinter_wellknown(struct torture_context
*tctx
,
7355 struct dcerpc_pipe
*p
,
7356 const char *printername
,
7360 struct spoolss_AddPrinter r
;
7361 struct spoolss_AddPrinterEx rex
;
7362 struct spoolss_SetPrinterInfoCtr info_ctr
;
7363 struct spoolss_SetPrinterInfo1 info1
;
7364 struct spoolss_DevmodeContainer devmode_ctr
;
7365 struct sec_desc_buf secdesc_ctr
;
7366 struct spoolss_UserLevelCtr userlevel_ctr
;
7367 struct policy_handle handle
;
7369 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7371 ZERO_STRUCT(devmode_ctr
);
7372 ZERO_STRUCT(secdesc_ctr
);
7373 ZERO_STRUCT(userlevel_ctr
);
7376 torture_comment(tctx
, "Testing AddPrinter%s(%s) level 1\n",
7377 ex
? "Ex":"", printername
);
7379 /* try to add printer to wellknown printer list (level 1) */
7381 userlevel_ctr
.level
= 1;
7383 info_ctr
.info
.info1
= &info1
;
7386 rex
.in
.server
= NULL
;
7387 rex
.in
.info_ctr
= &info_ctr
;
7388 rex
.in
.devmode_ctr
= &devmode_ctr
;
7389 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
7390 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
7391 rex
.out
.handle
= &handle
;
7394 r
.in
.info_ctr
= &info_ctr
;
7395 r
.in
.devmode_ctr
= &devmode_ctr
;
7396 r
.in
.secdesc_ctr
= &secdesc_ctr
;
7397 r
.out
.handle
= &handle
;
7399 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7400 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7401 "failed to add printer");
7402 result
= ex
? rex
.out
.result
: r
.out
.result
;
7403 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
7404 "unexpected result code");
7406 info1
.name
= printername
;
7407 info1
.flags
= PRINTER_ATTRIBUTE_SHARED
;
7409 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7410 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7411 "failed to add printer");
7412 result
= ex
? rex
.out
.result
: r
.out
.result
;
7413 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
7414 "unexpected result code");
7416 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7417 better do a real check to see the printer is really there */
7419 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, b
,
7420 PRINTER_ENUM_NETWORK
, 1,
7423 "failed to enum printers");
7425 torture_assert(tctx
, found
, "failed to find newly added printer");
7429 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7430 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7431 "failed to add printer");
7432 result
= ex
? rex
.out
.result
: r
.out
.result
;
7433 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
7434 "unexpected result code");
7436 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7437 better do a real check to see the printer has really been removed
7438 from the well known printer list */
7442 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, b
,
7443 PRINTER_ENUM_NETWORK
, 1,
7446 "failed to enum printers");
7448 torture_assert(tctx
, !found
, "printer still in well known printer list");
7453 static bool test_AddPrinter_normal(struct torture_context
*tctx
,
7454 struct dcerpc_pipe
*p
,
7455 struct policy_handle
*handle_p
,
7456 const char *printername
,
7457 const char *drivername
,
7458 const char *portname
,
7459 struct spoolss_DeviceMode
*devmode
,
7463 struct spoolss_AddPrinter r
;
7464 struct spoolss_AddPrinterEx rex
;
7465 struct spoolss_SetPrinterInfoCtr info_ctr
;
7466 struct spoolss_SetPrinterInfo2 info2
;
7467 struct spoolss_DevmodeContainer devmode_ctr
;
7468 struct sec_desc_buf secdesc_ctr
;
7469 struct spoolss_UserLevelCtr userlevel_ctr
;
7470 struct policy_handle handle
;
7472 bool existing_printer_deleted
= false;
7473 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7475 ZERO_STRUCT(devmode_ctr
);
7476 ZERO_STRUCT(secdesc_ctr
);
7477 ZERO_STRUCT(userlevel_ctr
);
7479 torture_comment(tctx
, "Testing AddPrinter%s(%s) level 2\n",
7480 ex
? "Ex":"", printername
);
7482 devmode_ctr
.devmode
= devmode
;
7484 userlevel_ctr
.level
= 1;
7486 rex
.in
.server
= NULL
;
7487 rex
.in
.info_ctr
= &info_ctr
;
7488 rex
.in
.devmode_ctr
= &devmode_ctr
;
7489 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
7490 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
7491 rex
.out
.handle
= &handle
;
7494 r
.in
.info_ctr
= &info_ctr
;
7495 r
.in
.devmode_ctr
= &devmode_ctr
;
7496 r
.in
.secdesc_ctr
= &secdesc_ctr
;
7497 r
.out
.handle
= &handle
;
7501 /* try to add printer to printer list (level 2) */
7505 info_ctr
.info
.info2
= &info2
;
7508 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7509 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7510 "failed to add printer");
7511 result
= ex
? rex
.out
.result
: r
.out
.result
;
7512 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
7513 "unexpected result code");
7515 info2
.printername
= printername
;
7517 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7518 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7519 "failed to add printer");
7520 result
= ex
? rex
.out
.result
: r
.out
.result
;
7522 if (W_ERROR_EQUAL(result
, WERR_PRINTER_ALREADY_EXISTS
)) {
7523 struct policy_handle printer_handle
;
7525 if (existing_printer_deleted
) {
7526 torture_fail(tctx
, "already deleted printer still existing?");
7529 torture_assert(tctx
, call_OpenPrinterEx(tctx
, p
, printername
, NULL
, &printer_handle
),
7530 "failed to open printer handle");
7532 torture_assert(tctx
, test_DeletePrinter(tctx
, b
, &printer_handle
),
7533 "failed to delete printer");
7535 torture_assert(tctx
, test_ClosePrinter(tctx
, b
, &printer_handle
),
7536 "failed to close server handle");
7538 existing_printer_deleted
= true;
7543 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PORT
,
7544 "unexpected result code");
7546 info2
.portname
= portname
;
7548 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7549 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7550 "failed to add printer");
7551 result
= ex
? rex
.out
.result
: r
.out
.result
;
7552 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTER_DRIVER
,
7553 "unexpected result code");
7555 info2
.drivername
= drivername
;
7557 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7558 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7559 "failed to add printer");
7560 result
= ex
? rex
.out
.result
: r
.out
.result
;
7562 /* w2k8r2 allows one to add printer w/o defining printprocessor */
7564 if (!W_ERROR_IS_OK(result
)) {
7565 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTPROCESSOR
,
7566 "unexpected result code");
7568 info2
.printprocessor
= "winprint";
7570 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7571 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7572 "failed to add printer");
7573 result
= ex
? rex
.out
.result
: r
.out
.result
;
7574 torture_assert_werr_ok(tctx
, result
,
7575 "failed to add printer");
7580 /* we are paranoid, really check if the printer is there now */
7582 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, b
,
7583 PRINTER_ENUM_LOCAL
, 1,
7586 "failed to enum printers");
7587 torture_assert(tctx
, found
, "failed to find newly added printer");
7589 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7590 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7591 "failed to add printer");
7592 result
= ex
? rex
.out
.result
: r
.out
.result
;
7593 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
7594 "unexpected result code");
7599 static bool test_printer_info(struct torture_context
*tctx
,
7602 struct torture_printer_context
*t
=
7603 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
7604 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
7605 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7609 if (torture_setting_bool(tctx
, "samba3", false)) {
7610 torture_skip(tctx
, "skipping printer info cross tests against samba 3");
7613 if (!test_PrinterInfo(tctx
, b
, &t
->handle
)) {
7617 if (!test_SetPrinter_errors(tctx
, b
, &t
->handle
)) {
7624 static bool test_EnumPrinterKey(struct torture_context
*tctx
,
7625 struct dcerpc_binding_handle
*b
,
7626 struct policy_handle
*handle
,
7627 const char *key_name
,
7628 const char ***array
)
7630 struct spoolss_EnumPrinterKey r
;
7631 uint32_t needed
= 0;
7632 union spoolss_KeyNames key_buffer
;
7633 int32_t offered
[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7637 r
.in
.handle
= handle
;
7638 r
.in
.key_name
= key_name
;
7639 r
.out
.key_buffer
= &key_buffer
;
7640 r
.out
.needed
= &needed
;
7641 r
.out
._ndr_size
= &_ndr_size
;
7643 for (i
=0; i
< ARRAY_SIZE(offered
); i
++) {
7645 if (offered
[i
] < 0 && needed
) {
7649 r
.in
.offered
= needed
+ offered
[i
];
7651 r
.in
.offered
= offered
[i
];
7654 ZERO_STRUCT(key_buffer
);
7656 torture_comment(tctx
, "Testing EnumPrinterKey(%s) with %d offered\n", r
.in
.key_name
, r
.in
.offered
);
7658 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterKey_r(b
, tctx
, &r
),
7659 "failed to call EnumPrinterKey");
7660 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
7662 torture_assert(tctx
, (_ndr_size
== r
.in
.offered
/2),
7663 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7664 _ndr_size
, r
.in
.offered
/2));
7666 r
.in
.offered
= needed
;
7667 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterKey_r(b
, tctx
, &r
),
7668 "failed to call EnumPrinterKey");
7671 if (offered
[i
] > 0) {
7672 torture_assert_werr_ok(tctx
, r
.out
.result
,
7673 "failed to call EnumPrinterKey");
7676 torture_assert(tctx
, (_ndr_size
== r
.in
.offered
/2),
7677 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7678 _ndr_size
, r
.in
.offered
/2));
7680 torture_assert(tctx
, (*r
.out
.needed
<= r
.in
.offered
),
7681 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r
.out
.needed
, r
.in
.offered
));
7683 torture_assert(tctx
, (*r
.out
.needed
<= _ndr_size
* 2),
7684 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r
.out
.needed
, _ndr_size
));
7686 if (key_buffer
.string_array
) {
7687 uint32_t calc_needed
= 0;
7689 for (s
=0; key_buffer
.string_array
[s
]; s
++) {
7690 calc_needed
+= strlen_m_term(key_buffer
.string_array
[s
])*2;
7692 if (!key_buffer
.string_array
[0]) {
7697 torture_assert_int_equal(tctx
, *r
.out
.needed
, calc_needed
,
7698 "EnumPrinterKey unexpected size");
7703 *array
= key_buffer
.string_array
;
7709 bool test_printer_all_keys(struct torture_context
*tctx
,
7710 struct dcerpc_binding_handle
*b
,
7711 struct policy_handle
*handle
)
7713 const char **key_array
= NULL
;
7716 torture_comment(tctx
, "Testing Printer Keys\n");
7718 torture_assert(tctx
, test_EnumPrinterKey(tctx
, b
, handle
, "", &key_array
),
7719 "failed to call test_EnumPrinterKey");
7721 for (i
=0; key_array
&& key_array
[i
]; i
++) {
7722 torture_assert(tctx
, test_EnumPrinterKey(tctx
, b
, handle
, key_array
[i
], NULL
),
7723 "failed to call test_EnumPrinterKey");
7725 for (i
=0; key_array
&& key_array
[i
]; i
++) {
7726 torture_assert(tctx
, test_EnumPrinterDataEx(tctx
, b
, handle
, key_array
[i
], NULL
, NULL
),
7727 "failed to call test_EnumPrinterDataEx");
7730 torture_comment(tctx
, "Printer Keys test succeeded\n\n");
7735 static bool test_openprinter_wrap(struct torture_context
*tctx
,
7738 struct torture_printer_context
*t
=
7739 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
7740 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
7741 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7742 const char *printername
= t
->info2
.printername
;
7744 return test_openprinter(tctx
, b
, printername
);
7747 static bool test_csetprinter(struct torture_context
*tctx
,
7750 struct torture_printer_context
*t
=
7751 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
7752 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
7754 const char *printername
= talloc_asprintf(tctx
, "%s2", t
->info2
.printername
);
7755 const char *drivername
= t
->added_driver
? t
->driver
.info8
.driver_name
: t
->info2
.drivername
;
7756 const char *portname
= t
->info2
.portname
;
7758 union spoolss_PrinterInfo info
;
7759 struct policy_handle new_handle
, new_handle2
;
7760 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7762 torture_comment(tctx
, "Testing c_setprinter\n");
7764 torture_assert(tctx
,
7765 test_GetPrinter_level(tctx
, b
, &t
->handle
, 0, &info
),
7766 "failed to get level 0 printer info");
7767 torture_comment(tctx
, "csetprinter on initial printer handle: %d\n",
7768 info
.info0
.c_setprinter
);
7770 /* check if c_setprinter on 1st handle increases after a printer has
7773 torture_assert(tctx
,
7774 test_AddPrinter_normal(tctx
, p
, &new_handle
, printername
, drivername
, portname
, NULL
, false),
7775 "failed to add new printer");
7776 torture_assert(tctx
,
7777 test_GetPrinter_level(tctx
, b
, &t
->handle
, 0, &info
),
7778 "failed to get level 0 printer info");
7779 torture_comment(tctx
, "csetprinter on initial printer handle (after add): %d\n",
7780 info
.info0
.c_setprinter
);
7782 /* check if c_setprinter on new handle increases after a printer has
7785 torture_assert(tctx
,
7786 test_GetPrinter_level(tctx
, b
, &new_handle
, 0, &info
),
7787 "failed to get level 0 printer info");
7788 torture_comment(tctx
, "csetprinter on created handle: %d\n",
7789 info
.info0
.c_setprinter
);
7791 /* open the new printer and check if c_setprinter increases */
7793 torture_assert(tctx
,
7794 call_OpenPrinterEx(tctx
, p
, printername
, NULL
, &new_handle2
),
7795 "failed to open created printer");
7796 torture_assert(tctx
,
7797 test_GetPrinter_level(tctx
, b
, &new_handle2
, 0, &info
),
7798 "failed to get level 0 printer info");
7799 torture_comment(tctx
, "csetprinter on new handle (after openprinter): %d\n",
7800 info
.info0
.c_setprinter
);
7804 torture_assert(tctx
,
7805 test_ClosePrinter(tctx
, b
, &new_handle2
),
7806 "failed to close printer");
7807 torture_assert(tctx
,
7808 test_DeletePrinter(tctx
, b
, &new_handle
),
7809 "failed to delete new printer");
7814 static bool compose_local_driver_directory(struct torture_context
*tctx
,
7815 const char *environment
,
7816 const char *local_dir
,
7821 p
= strrchr(local_dir
, '/');
7827 if (strequal(environment
, SPOOLSS_ARCHITECTURE_x64
)) {
7828 if (!strequal(p
, "x64")) {
7829 *path
= talloc_asprintf(tctx
, "%s/x64", local_dir
);
7831 } else if (strequal(environment
, SPOOLSS_ARCHITECTURE_NT_X86
)) {
7832 if (!strequal(p
, "i386")) {
7833 *path
= talloc_asprintf(tctx
, "%s/i386", local_dir
);
7836 torture_assert(tctx
, "unknown environment: '%s'\n", environment
);
7843 static struct spoolss_DeviceMode
*torture_devicemode(TALLOC_CTX
*mem_ctx
,
7844 const char *devicename
)
7846 struct spoolss_DeviceMode
*r
;
7848 r
= talloc_zero(mem_ctx
, struct spoolss_DeviceMode
);
7853 r
->devicename
= talloc_strdup(r
, devicename
);
7854 r
->specversion
= DMSPEC_NT4_AND_ABOVE
;
7855 r
->driverversion
= 0x0600;
7857 r
->__driverextra_length
= 0;
7858 r
->fields
= DEVMODE_FORMNAME
|
7860 DEVMODE_PRINTQUALITY
|
7861 DEVMODE_DEFAULTSOURCE
|
7865 DEVMODE_ORIENTATION
;
7866 r
->orientation
= DMORIENT_PORTRAIT
;
7867 r
->papersize
= DMPAPER_LETTER
;
7872 r
->defaultsource
= DMBIN_FORMSOURCE
;
7873 r
->printquality
= DMRES_HIGH
;
7874 r
->color
= DMRES_MONOCHROME
;
7875 r
->duplex
= DMDUP_SIMPLEX
;
7877 r
->ttoption
= DMTT_SUBDEV
;
7878 r
->collate
= DMCOLLATE_FALSE
;
7879 r
->formname
= talloc_strdup(r
, "Letter");
7885 static bool test_architecture_buffer(struct torture_context
*tctx
,
7888 struct test_spoolss_context
*ctx
=
7889 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
7891 struct spoolss_OpenPrinterEx r
;
7892 struct spoolss_UserLevel1 u1
;
7893 struct policy_handle handle
;
7894 uint32_t architectures
[] = {
7895 PROCESSOR_ARCHITECTURE_INTEL
,
7896 PROCESSOR_ARCHITECTURE_IA64
,
7897 PROCESSOR_ARCHITECTURE_AMD64
7901 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
7902 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7904 for (i
=0; i
< ARRAY_SIZE(architectures
); i
++) {
7906 torture_comment(tctx
, "Testing OpenPrinterEx with architecture %d\n", architectures
[i
]);
7914 u1
.processor
= architectures
[i
];
7916 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
7917 r
.in
.datatype
= NULL
;
7918 r
.in
.devmode_ctr
.devmode
= NULL
;
7919 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
7920 r
.in
.userlevel_ctr
.level
= 1;
7921 r
.in
.userlevel_ctr
.user_info
.level1
= &u1
;
7922 r
.out
.handle
= &handle
;
7924 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_OpenPrinterEx_r(b
, tctx
, &r
), "");
7925 torture_assert_werr_ok(tctx
, r
.out
.result
, "");
7928 struct spoolss_EnumPrinters e
;
7930 union spoolss_PrinterInfo
*info
;
7932 e
.in
.flags
= PRINTER_ENUM_LOCAL
;
7937 e
.out
.count
= &count
;
7939 e
.out
.needed
= &needed
[i
];
7941 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &e
), "");
7943 torture_comment(tctx
, "needed was %d\n", needed
[i
]);
7947 torture_assert(tctx
, test_ClosePrinter(tctx
, b
, &handle
), "");
7950 for (i
=1; i
< ARRAY_SIZE(architectures
); i
++) {
7951 if (needed
[i
-1] != needed
[i
]) {
7953 talloc_asprintf(tctx
, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7954 needed
[i
-1], architectures
[i
-1], needed
[i
], architectures
[i
]));
7961 static bool test_get_core_printer_drivers_arch_guid(struct torture_context
*tctx
,
7962 struct dcerpc_pipe
*p
,
7963 const char *architecture
,
7964 const char *guid_str
,
7965 const char **package_id
)
7967 struct spoolss_GetCorePrinterDrivers r
;
7968 struct spoolss_CorePrinterDriver core_printer_drivers
;
7971 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7974 s
= talloc_zero_array(tctx
, const char *, 2);
7976 r
.in
.servername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
7977 r
.in
.architecture
= "foobar";
7978 r
.in
.core_driver_size
= 0;
7979 r
.in
.core_driver_dependencies
= "";
7980 r
.in
.core_printer_driver_count
= 0;
7981 r
.out
.core_printer_drivers
= &core_printer_drivers
;
7983 torture_assert_ntstatus_ok(tctx
,
7984 dcerpc_spoolss_GetCorePrinterDrivers_r(b
, tctx
, &r
),
7985 "spoolss_GetCorePrinterDrivers failed");
7986 torture_assert_hresult_equal(tctx
, r
.out
.result
, HRES_E_INVALIDARG
,
7987 "spoolss_GetCorePrinterDrivers failed");
7989 guid
= GUID_random();
7990 s
[0] = GUID_string2(tctx
, &guid
);
7992 torture_assert(tctx
,
7993 push_reg_multi_sz(tctx
, &blob
, s
),
7994 "push_reg_multi_sz failed");
7996 r
.in
.core_driver_size
= blob
.length
;
7997 r
.in
.core_driver_dependencies
= s
[0];
7998 r
.in
.core_printer_driver_count
= 1;
7999 r
.out
.core_printer_drivers
= talloc_zero_array(tctx
, struct spoolss_CorePrinterDriver
, r
.in
.core_printer_driver_count
);
8001 torture_assert_ntstatus_ok(tctx
,
8002 dcerpc_spoolss_GetCorePrinterDrivers_r(b
, tctx
, &r
),
8003 "spoolss_GetCorePrinterDrivers failed");
8004 torture_assert_werr_equal(tctx
,
8005 W_ERROR(WIN32_FROM_HRESULT(r
.out
.result
)), WERR_INVALID_ENVIRONMENT
,
8006 "spoolss_GetCorePrinterDrivers failed");
8008 r
.in
.architecture
= architecture
;
8010 torture_assert_ntstatus_ok(tctx
,
8011 dcerpc_spoolss_GetCorePrinterDrivers_r(b
, tctx
, &r
),
8012 "spoolss_GetCorePrinterDrivers failed");
8013 torture_assert_werr_equal(tctx
,
8014 W_ERROR(WIN32_FROM_HRESULT(r
.out
.result
)), WERR_NOT_FOUND
,
8015 "spoolss_GetCorePrinterDrivers failed");
8017 s
[0] = talloc_strdup(s
, guid_str
);
8019 torture_assert(tctx
,
8020 push_reg_multi_sz(tctx
, &blob
, s
),
8021 "push_reg_multi_sz failed");
8023 r
.in
.core_driver_size
= blob
.length
;
8024 r
.in
.core_driver_dependencies
= s
[0];
8025 r
.in
.core_printer_driver_count
= 1;
8026 r
.out
.core_printer_drivers
= talloc_zero_array(tctx
, struct spoolss_CorePrinterDriver
, r
.in
.core_printer_driver_count
);
8028 torture_assert_ntstatus_ok(tctx
,
8029 dcerpc_spoolss_GetCorePrinterDrivers_r(b
, tctx
, &r
),
8030 "spoolss_GetCorePrinterDrivers failed");
8031 torture_assert_hresult_ok(tctx
, r
.out
.result
,
8032 "spoolss_GetCorePrinterDrivers failed");
8035 *package_id
= r
.out
.core_printer_drivers
[0].szPackageID
;
8041 static bool test_get_core_printer_drivers(struct torture_context
*tctx
,
8044 struct test_spoolss_context
*ctx
=
8045 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
8047 const char *architectures
[] = {
8048 SPOOLSS_ARCHITECTURE_NT_X86
,
8049 SPOOLSS_ARCHITECTURE_x64
8052 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
8054 for (i
=0; i
< ARRAY_SIZE(architectures
); i
++) {
8056 torture_comment(tctx
, "Testing GetCorePrinterDrivers(\"%s\",\"%s\")\n",
8058 SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV
);
8060 torture_assert(tctx
,
8061 test_get_core_printer_drivers_arch_guid(tctx
, p
,
8063 SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV
,
8071 static bool test_get_printer_driver_package_path(struct torture_context
*tctx
,
8074 struct test_spoolss_context
*ctx
=
8075 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
8077 const char *architectures
[] = {
8078 SPOOLSS_ARCHITECTURE_NT_X86
,
8079 SPOOLSS_ARCHITECTURE_x64
8082 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
8083 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8085 for (i
=0; i
< ARRAY_SIZE(architectures
); i
++) {
8086 struct spoolss_GetPrinterDriverPackagePath r
;
8087 uint32_t required
= 0;
8088 const char *package_id
= NULL
;
8090 test_get_core_printer_drivers_arch_guid(tctx
, p
,
8092 SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV
,
8095 torture_comment(tctx
, "Testing GetPrinterDriverPackagePath(\"%s\",\"%s\")\n",
8096 architectures
[i
], package_id
);
8098 r
.in
.servername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
8099 r
.in
.architecture
= "foobar";
8100 r
.in
.language
= NULL
;
8101 r
.in
.package_id
= "";
8102 r
.in
.driver_package_cab_size
= 0;
8103 r
.in
.driver_package_cab
= NULL
;
8105 r
.out
.required
= &required
;
8106 r
.out
.driver_package_cab
= NULL
;
8108 torture_assert_ntstatus_ok(tctx
,
8109 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b
, tctx
, &r
),
8110 "spoolss_GetPrinterDriverPackagePath failed");
8111 torture_assert_werr_equal(tctx
,
8112 W_ERROR(WIN32_FROM_HRESULT(r
.out
.result
)), WERR_INVALID_ENVIRONMENT
,
8113 "spoolss_GetPrinterDriverPackagePath failed");
8115 r
.in
.architecture
= architectures
[i
];
8117 torture_assert_ntstatus_ok(tctx
,
8118 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b
, tctx
, &r
),
8119 "spoolss_GetPrinterDriverPackagePath failed");
8120 torture_assert_werr_equal(tctx
,
8121 W_ERROR(WIN32_FROM_HRESULT(r
.out
.result
)), WERR_FILE_NOT_FOUND
,
8122 "spoolss_GetPrinterDriverPackagePath failed");
8124 r
.in
.package_id
= package_id
;
8126 torture_assert_ntstatus_ok(tctx
,
8127 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b
, tctx
, &r
),
8128 "spoolss_GetPrinterDriverPackagePath failed");
8129 torture_assert_hresult_ok(tctx
, r
.out
.result
,
8130 "spoolss_GetPrinterDriverPackagePath failed");
8132 r
.in
.driver_package_cab_size
= required
;
8133 r
.in
.driver_package_cab
= talloc_zero_array(tctx
, char, required
);
8134 r
.out
.driver_package_cab
= talloc_zero_array(tctx
, char, required
);
8136 torture_assert_ntstatus_ok(tctx
,
8137 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b
, tctx
, &r
),
8138 "spoolss_GetPrinterDriverPackagePath failed");
8139 torture_assert_hresult_ok(tctx
, r
.out
.result
,
8140 "spoolss_GetPrinterDriverPackagePath failed");
8142 r
.in
.servername
= NULL
;
8144 torture_assert_ntstatus_ok(tctx
,
8145 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b
, tctx
, &r
),
8146 "spoolss_GetPrinterDriverPackagePath failed");
8147 torture_assert_werr_equal(tctx
,
8148 W_ERROR(WIN32_FROM_HRESULT(r
.out
.result
)), WERR_INSUFFICIENT_BUFFER
,
8149 "spoolss_GetPrinterDriverPackagePath failed");
8151 r
.in
.driver_package_cab_size
= required
;
8152 r
.in
.driver_package_cab
= talloc_zero_array(tctx
, char, required
);
8153 r
.out
.driver_package_cab
= talloc_zero_array(tctx
, char, required
);
8155 torture_assert_ntstatus_ok(tctx
,
8156 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b
, tctx
, &r
),
8157 "spoolss_GetPrinterDriverPackagePath failed");
8158 torture_assert_hresult_ok(tctx
, r
.out
.result
,
8159 "spoolss_GetPrinterDriverPackagePath failed");
8166 static bool test_get_printer_printserverhandle(struct torture_context
*tctx
,
8169 struct test_spoolss_context
*ctx
=
8170 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
8172 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
8173 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8174 uint32_t levels
[] = {0, 1, 2, /* 3,*/ 4, 5, 6, 7, 8};
8177 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
8179 torture_assert(tctx
,
8180 test_GetPrinter_level_exp(tctx
, b
, &ctx
->server_handle
,
8181 levels
[i
], WERR_INVALID_LEVEL
,
8183 "failed to call GetPrinter");
8186 torture_assert(tctx
,
8187 test_GetPrinter_level(tctx
, b
, &ctx
->server_handle
, 3, NULL
),
8188 "failed to call GetPrinter");
8193 #define TEST_SID "S-1-5-21-1234567890-1234567890-1234567890-500"
8195 static bool test_set_printer_printserverhandle(struct torture_context
*tctx
,
8198 struct test_spoolss_context
*ctx
=
8199 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
8201 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
8202 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8203 union spoolss_PrinterInfo info
;
8204 struct spoolss_SetPrinterInfoCtr info_ctr
;
8205 struct spoolss_SetPrinterInfo3 info3
;
8206 struct spoolss_DevmodeContainer devmode_ctr
;
8207 struct sec_desc_buf secdesc_ctr
;
8208 struct security_descriptor
*sd
;
8209 struct security_ace
*ace
;
8213 torture_assert(tctx
,
8214 test_GetPrinter_level(tctx
, b
, &ctx
->server_handle
, 3, &info
),
8215 "failed to call GetPrinter");
8217 secdesc_ctr
.sd
= info
.info3
.secdesc
;
8218 secdesc_ctr
.sd
->owner_sid
= NULL
;
8219 secdesc_ctr
.sd
->group_sid
= NULL
;
8221 sd
= security_descriptor_copy(tctx
, secdesc_ctr
.sd
);
8226 ace
= security_ace_create(tctx
,
8228 SEC_ACE_TYPE_ACCESS_ALLOWED
,
8230 SEC_ACE_FLAG_CONTAINER_INHERIT
);
8231 torture_assert(tctx
, ace
, "failed to create ace");
8233 torture_assert_ntstatus_ok(tctx
,
8234 security_descriptor_dacl_add(sd
, ace
),
8235 "failed to add ace");
8237 secdesc_ctr
.sd
= sd
;
8239 info3
.sec_desc_ptr
= 0;
8242 info_ctr
.info
.info3
= &info3
;
8244 ZERO_STRUCT(devmode_ctr
);
8246 torture_assert(tctx
,
8247 test_SetPrinter(tctx
, b
, &ctx
->server_handle
, &info_ctr
,
8248 &devmode_ctr
, &secdesc_ctr
, 0),
8249 "failed to call SetPrinter");
8251 torture_assert(tctx
,
8252 test_GetPrinter_level(tctx
, b
, &ctx
->server_handle
, 3, &info
),
8253 "failed to call GetPrinter");
8255 for (i
= 0; i
< info
.info3
.secdesc
->dacl
->num_aces
; i
++) {
8256 if (security_ace_equal(&info
.info3
.secdesc
->dacl
->aces
[i
], ace
)) {
8261 if (i
== info
.info3
.secdesc
->dacl
->num_aces
) {
8262 torture_fail(tctx
, "ace not present");
8265 torture_assert(tctx
,
8266 dom_sid_parse(TEST_SID
, &sid
),
8267 "failed to parse sid");
8269 torture_assert_ntstatus_ok(tctx
,
8270 security_descriptor_dacl_del(info
.info3
.secdesc
, &sid
),
8271 "failed to remove ace from sd");
8273 secdesc_ctr
.sd
= info
.info3
.secdesc
;
8275 torture_assert(tctx
,
8276 test_SetPrinter(tctx
, b
, &ctx
->server_handle
, &info_ctr
,
8277 &devmode_ctr
, &secdesc_ctr
, 0),
8278 "failed to call SetPrinter");
8280 torture_assert(tctx
,
8281 test_GetPrinter_level(tctx
, b
, &ctx
->server_handle
, 3, &info
),
8282 "failed to call GetPrinter");
8284 for (i
= 0; i
< info
.info3
.secdesc
->dacl
->num_aces
; i
++) {
8285 if (security_ace_equal(&info
.info3
.secdesc
->dacl
->aces
[i
], ace
)) {
8286 torture_fail(tctx
, "ace still present");
8294 static bool test_PrintServer_Forms_Winreg(struct torture_context
*tctx
,
8297 struct test_spoolss_context
*ctx
=
8298 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
8299 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
8300 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8302 return test_Forms_winreg(tctx
, b
, &ctx
->server_handle
, true, NULL
);
8305 static bool test_PrintServer_Forms(struct torture_context
*tctx
,
8308 struct test_spoolss_context
*ctx
=
8309 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
8310 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
8311 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8313 return test_Forms(tctx
, b
, &ctx
->server_handle
, true, NULL
, NULL
, NULL
);
8316 static bool test_PrintServer_EnumForms(struct torture_context
*tctx
,
8319 struct test_spoolss_context
*ctx
=
8320 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
8321 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
8322 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8324 return test_EnumForms_all(tctx
, b
, &ctx
->server_handle
, true);
8327 static bool torture_rpc_spoolss_setup_common(struct torture_context
*tctx
, struct test_spoolss_context
*t
)
8331 status
= torture_rpc_connection(tctx
, &t
->spoolss_pipe
, &ndr_table_spoolss
);
8333 torture_assert_ntstatus_ok(tctx
, status
, "Error connecting to server");
8335 torture_assert(tctx
,
8336 test_OpenPrinter_server(tctx
, t
->spoolss_pipe
, &t
->server_handle
),
8337 "failed to open printserver");
8338 torture_assert(tctx
,
8339 test_get_environment(tctx
, t
->spoolss_pipe
->binding_handle
, &t
->server_handle
, &t
->environment
),
8340 "failed to get environment");
8345 static bool torture_rpc_spoolss_setup(struct torture_context
*tctx
, void **data
)
8347 struct test_spoolss_context
*t
;
8349 *data
= t
= talloc_zero(tctx
, struct test_spoolss_context
);
8351 return torture_rpc_spoolss_setup_common(tctx
, t
);
8354 static bool torture_rpc_spoolss_teardown_common(struct torture_context
*tctx
, struct test_spoolss_context
*t
)
8356 test_ClosePrinter(tctx
, t
->spoolss_pipe
->binding_handle
, &t
->server_handle
);
8361 static bool torture_rpc_spoolss_teardown(struct torture_context
*tctx
, void *data
)
8363 struct test_spoolss_context
*t
= talloc_get_type(data
, struct test_spoolss_context
);
8366 ret
= torture_rpc_spoolss_teardown_common(tctx
, t
);
8372 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context
*tctx
, struct torture_printer_context
*t
)
8374 struct dcerpc_pipe
*p
;
8375 struct dcerpc_binding_handle
*b
;
8376 const char *server_name_slash
;
8377 const char *driver_name
;
8378 const char *printer_name
;
8379 const char *port_name
;
8381 torture_assert_ntstatus_ok(tctx
,
8382 torture_rpc_connection(tctx
, &t
->spoolss_pipe
, &ndr_table_spoolss
),
8383 "Error connecting to server");
8385 p
= t
->spoolss_pipe
;
8386 b
= p
->binding_handle
;
8387 server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
8389 t
->driver
.info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
8390 t
->driver
.info8
.driver_name
= TORTURE_DRIVER
;
8391 t
->driver
.info8
.driver_path
= "pscript5.dll";
8392 t
->driver
.info8
.data_file
= "cups6.ppd";
8393 t
->driver
.info8
.config_file
= "ps5ui.dll";
8394 t
->driver
.info8
.help_file
= "pscript.hlp";
8395 t
->driver
.info8
.default_datatype
= "RAW";
8396 t
->driver
.info8
.dependent_files
= talloc_zero(t
, struct spoolss_StringArray
);
8397 t
->driver
.info8
.dependent_files
->string
= talloc_zero_array(t
, const char *, 8 + 1);
8398 t
->driver
.info8
.dependent_files
->string
[0] = "pscript5.dll";
8399 t
->driver
.info8
.dependent_files
->string
[1] = "cups6.ppd";
8400 t
->driver
.info8
.dependent_files
->string
[2] = "ps5ui.dll";
8401 t
->driver
.info8
.dependent_files
->string
[3] = "pscript.hlp";
8402 t
->driver
.info8
.dependent_files
->string
[4] = "pscript.ntf";
8403 t
->driver
.info8
.dependent_files
->string
[5] = "cups6.ini";
8404 t
->driver
.info8
.dependent_files
->string
[6] = "cupsps6.dll";
8405 t
->driver
.info8
.dependent_files
->string
[7] = "cupsui6.dll";
8407 t
->driver
.local
.driver_directory
= "/usr/share/cups/drivers";
8409 t
->info2
.portname
= "LPT1:";
8411 printer_name
= t
->info2
.printername
;
8412 port_name
= t
->info2
.portname
;
8414 torture_assert(tctx
,
8415 fillup_printserver_info(tctx
, p
, &t
->driver
),
8416 "failed to fillup printserver info");
8418 t
->driver
.info8
.architecture
= talloc_strdup(t
, t
->driver
.remote
.environment
);
8420 torture_assert(tctx
,
8421 compose_local_driver_directory(tctx
, t
->driver
.remote
.environment
,
8422 t
->driver
.local
.driver_directory
,
8423 &t
->driver
.local
.driver_directory
),
8424 "failed to compose local driver directory");
8426 t
->info2
.drivername
= "Microsoft XPS Document Writer";
8428 if (test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, t
->driver
.remote
.environment
, 3, t
->info2
.drivername
, NULL
)) {
8429 torture_comment(tctx
, "driver '%s' (architecture: %s, version: 3) is present on server\n",
8430 t
->info2
.drivername
, t
->driver
.remote
.environment
);
8431 t
->have_driver
= true;
8435 torture_comment(tctx
, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
8436 t
->info2
.drivername
, t
->driver
.remote
.environment
);
8438 t
->info2
.drivername
= "Microsoft XPS Document Writer v4";
8440 if (test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, t
->driver
.remote
.environment
, 3, t
->info2
.drivername
, NULL
)) {
8441 torture_comment(tctx
, "driver '%s' (architecture: %s, version: 4) is present on server\n",
8442 t
->info2
.drivername
, t
->driver
.remote
.environment
);
8443 t
->have_driver
= true;
8447 torture_comment(tctx
, "trying to upload own driver\n");
8449 if (!directory_exist(t
->driver
.local
.driver_directory
)) {
8450 torture_warning(tctx
, "no local driver is available!");
8451 t
->have_driver
= false;
8455 torture_assert(tctx
,
8456 upload_printer_driver(tctx
, dcerpc_server_name(p
), &t
->driver
),
8457 "failed to upload printer driver");
8459 torture_assert(tctx
,
8460 test_AddPrinterDriver_args_level_3(tctx
, b
, server_name_slash
, &t
->driver
.info8
, 0, false, NULL
),
8461 "failed to add driver");
8463 t
->added_driver
= true;
8464 t
->have_driver
= true;
8467 driver_name
= t
->added_driver
? t
->driver
.info8
.driver_name
: t
->info2
.drivername
;
8470 torture_assert(tctx
,
8471 test_AddPrinter_wellknown(tctx
, p
, printer_name
, t
->ex
),
8472 "failed to add wellknown printer");
8474 torture_assert(tctx
,
8475 test_AddPrinter_normal(tctx
, p
, &t
->handle
, printer_name
, driver_name
, port_name
, t
->devmode
, t
->ex
),
8476 "failed to add printer");
8482 static bool torture_rpc_spoolss_printer_setup(struct torture_context
*tctx
, void **data
)
8484 struct torture_printer_context
*t
;
8486 *data
= t
= talloc_zero(tctx
, struct torture_printer_context
);
8489 t
->wellknown
= false;
8490 t
->info2
.printername
= TORTURE_PRINTER
;
8493 return torture_rpc_spoolss_printer_setup_common(tctx
, t
);
8496 static bool torture_rpc_spoolss_printerex_setup(struct torture_context
*tctx
, void **data
)
8498 struct torture_printer_context
*t
;
8500 *data
= t
= talloc_zero(tctx
, struct torture_printer_context
);
8503 t
->wellknown
= false;
8504 t
->info2
.printername
= TORTURE_PRINTER_EX
;
8507 return torture_rpc_spoolss_printer_setup_common(tctx
, t
);
8510 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context
*tctx
, void **data
)
8512 struct torture_printer_context
*t
;
8514 *data
= t
= talloc_zero(tctx
, struct torture_printer_context
);
8517 t
->wellknown
= true;
8518 t
->info2
.printername
= TORTURE_WELLKNOWN_PRINTER
;
8523 torture_skip(tctx
, "skipping AddPrinter level 1");
8526 return torture_rpc_spoolss_printer_setup_common(tctx
, t
);
8529 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context
*tctx
, void **data
)
8531 struct torture_printer_context
*t
;
8533 *data
= t
= talloc_zero(tctx
, struct torture_printer_context
);
8536 t
->wellknown
= true;
8537 t
->info2
.printername
= TORTURE_WELLKNOWN_PRINTER_EX
;
8542 torture_skip(tctx
, "skipping AddPrinterEx level 1");
8545 return torture_rpc_spoolss_printer_setup_common(tctx
, t
);
8549 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context
*tctx
, void **data
)
8551 struct torture_printer_context
*t
;
8553 *data
= t
= talloc_zero(tctx
, struct torture_printer_context
);
8556 t
->wellknown
= false;
8557 t
->info2
.printername
= TORTURE_PRINTER_EX
;
8558 t
->devmode
= torture_devicemode(t
, TORTURE_PRINTER_EX
);
8560 return torture_rpc_spoolss_printer_setup_common(tctx
, t
);
8564 static bool test_DeletePrinterDriverEx_exp(struct torture_context
*tctx
,
8565 struct dcerpc_binding_handle
*b
,
8568 const char *environment
,
8569 uint32_t delete_flags
,
8571 WERROR expected_result
);
8573 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context
*tctx
, struct torture_printer_context
*t
)
8576 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8577 struct dcerpc_binding_handle
*b
= NULL
;
8578 const char *server_name_slash
;
8584 b
= p
->binding_handle
;
8586 server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
8588 if (!t
->wellknown
) {
8589 const char *printer_name
= t
->info2
.printername
;
8591 torture_assert_goto(tctx
,
8592 test_DeletePrinter(tctx
, b
, &t
->handle
),
8595 "failed to delete printer");
8597 torture_assert_goto(tctx
,
8598 test_EnumPrinters_findname(tctx
, b
, PRINTER_ENUM_LOCAL
, 1,
8599 printer_name
, &found
),
8602 "failed to enumerate printers");
8604 torture_assert_goto(tctx
,
8608 "deleted printer still there");
8613 if (t
->added_driver
) {
8614 ok
= remove_printer_driver(tctx
,
8615 dcerpc_server_name(p
),
8618 torture_warning(tctx
,
8619 "failed to remove printer driver\n");
8622 ok
= test_DeletePrinterDriverEx_exp(tctx
, b
,
8624 t
->driver
.info8
.driver_name
,
8625 t
->driver
.info8
.architecture
,
8626 DPD_DELETE_ALL_FILES
,
8627 t
->driver
.info8
.version
,
8630 torture_warning(tctx
,
8631 "failed to delete printer driver via "
8639 static bool torture_rpc_spoolss_printer_teardown(struct torture_context
*tctx
, void *data
)
8641 struct torture_printer_context
*t
= talloc_get_type(data
, struct torture_printer_context
);
8644 ret
= torture_rpc_spoolss_printer_teardown_common(tctx
, t
);
8650 static bool test_print_test(struct torture_context
*tctx
,
8653 struct torture_printer_context
*t
=
8654 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8655 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8656 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8658 torture_assert(tctx
,
8659 test_PausePrinter(tctx
, b
, &t
->handle
),
8660 "failed to pause printer");
8662 torture_assert(tctx
,
8663 test_DoPrintTest(tctx
, b
, &t
->handle
),
8664 "failed to do print test");
8666 torture_assert(tctx
,
8667 test_ResumePrinter(tctx
, b
, &t
->handle
),
8668 "failed to resume printer");
8673 static bool test_print_test_extended(struct torture_context
*tctx
,
8676 struct torture_printer_context
*t
=
8677 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8678 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8679 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8682 torture_assert(tctx
,
8683 test_PausePrinter(tctx
, b
, &t
->handle
),
8684 "failed to pause printer");
8686 ret
= test_DoPrintTest_extended(tctx
, b
, &t
->handle
);
8688 torture_comment(tctx
, "WARNING! failed to do extended print test\n");
8689 if (torture_setting_bool(tctx
, "samba3", false)) {
8690 torture_comment(tctx
, "non-critical for samba3\n");
8692 tctx
->last_result
= TORTURE_SKIP
;
8696 torture_assert(tctx
,
8697 test_ResumePrinter(tctx
, b
, &t
->handle
),
8698 "failed to resume printer");
8703 static bool test_print_test_properties(struct torture_context
*tctx
,
8706 struct torture_printer_context
*t
=
8707 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8708 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8709 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8711 if (torture_setting_bool(tctx
, "samba3", false)) {
8712 torture_skip(tctx
, "skip printer job property tests against samba");
8715 torture_assert(tctx
,
8716 test_PausePrinter(tctx
, b
, &t
->handle
),
8717 "failed to pause printer");
8719 torture_assert(tctx
,
8720 test_DoPrintTest_properties(tctx
, b
, &t
->handle
),
8721 "failed to test print job properties");
8723 torture_assert(tctx
,
8724 test_ResumePrinter(tctx
, b
, &t
->handle
),
8725 "failed to resume printer");
8730 /* use smbd file IO to spool a print job */
8731 static bool test_print_test_smbd(struct torture_context
*tctx
,
8734 struct torture_printer_context
*t
=
8735 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8736 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8737 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8740 union spoolss_JobInfo
*info
= NULL
;
8743 struct smb2_tree
*tree
;
8744 struct smb2_handle job_h
;
8745 struct smbcli_options options
;
8746 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
8748 * Do not test against the dynamically added printers, printing via
8749 * smbd means that a different spoolss process may handle the
8750 * OpenPrinter request to the one that handled the AddPrinter request.
8751 * This currently leads to an ugly race condition where one process
8752 * sees the new printer and one doesn't.
8754 const char *share
= TORTURE_PRINTER_STATIC1
;
8756 torture_comment(tctx
, "Testing smbd job spooling\n");
8757 lpcfg_smbcli_options(tctx
->lp_ctx
, &options
);
8759 status
= smb2_connect(mem_ctx
,
8760 torture_setting_string(tctx
, "host", NULL
),
8761 lpcfg_smb_ports(tctx
->lp_ctx
),
8763 lpcfg_resolve_context(tctx
->lp_ctx
),
8764 popt_get_cmdline_credentials(),
8768 lpcfg_socket_options(tctx
->lp_ctx
),
8769 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
));
8770 if (!NT_STATUS_IS_OK(status
)) {
8771 printf("Failed to connect to SMB2 printer %s - %s\n",
8772 share
, nt_errstr(status
));
8776 status
= torture_smb2_testfile(tree
, "smbd_spooler_job", &job_h
);
8777 torture_assert_ntstatus_ok(tctx
, status
, "smbd spool job create");
8779 status
= smb2_util_write(tree
, job_h
, "exciting print job data", 0,
8780 sizeof("exciting print job data"));
8781 torture_assert_ntstatus_ok(tctx
, status
, "smbd spool job write");
8783 /* check back end spoolss job was created */
8784 torture_assert(tctx
,
8785 test_EnumJobs_args(tctx
, b
, &t
->handle
, 1, WERR_OK
,
8787 "EnumJobs level 1 failed");
8789 for (i
= 0; i
< count
; i
++) {
8790 if (!strcmp(info
[i
].info1
.document_name
, "smbd_spooler_job")) {
8794 torture_assert(tctx
, (i
!= count
), "smbd_spooler_job not found");
8796 status
= smb2_util_close(tree
, job_h
);
8797 torture_assert_ntstatus_ok(tctx
, status
, "smbd spool job close");
8799 /* disconnect from printer share */
8800 talloc_free(mem_ctx
);
8805 static bool test_print_test_purge(struct torture_context
*tctx
,
8808 struct torture_printer_context
*t
=
8809 (struct torture_printer_context
*)talloc_get_type_abort(private_data
,
8810 struct torture_printer_context
);
8811 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8812 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8813 uint32_t num_jobs
= 8;
8818 union spoolss_JobInfo
*info
;
8820 torture_assert(tctx
,
8821 test_PausePrinter(tctx
, b
, &t
->handle
),
8822 "failed to pause printer");
8824 job_ids
= talloc_zero_array(tctx
, uint32_t, num_jobs
);
8825 for (i
=0; i
< num_jobs
; i
++) {
8826 ret
= test_DoPrintTest_add_one_job(tctx
, b
, &t
->handle
,
8829 torture_assert(tctx
, ret
, "failed to add print job");
8832 torture_assert(tctx
,
8833 test_EnumJobs_args(tctx
, b
, &t
->handle
, 1, WERR_OK
,
8835 "EnumJobs level 1 failed");
8837 torture_assert_int_equal(tctx
, count
, num_jobs
,
8838 "unexpected number of jobs in queue");
8840 torture_assert(tctx
,
8841 test_printer_purge(tctx
, b
, &t
->handle
),
8842 "failed to purge printer");
8844 torture_assert(tctx
,
8845 test_EnumJobs_args(tctx
, b
, &t
->handle
, 1, WERR_OK
,
8847 "EnumJobs level 1 failed");
8849 torture_assert_int_equal(tctx
, count
, 0,
8850 "unexpected number of jobs in queue");
8852 torture_assert(tctx
,
8853 test_ResumePrinter(tctx
, b
, &t
->handle
),
8854 "failed to resume printer");
8859 static bool test_printer_sd(struct torture_context
*tctx
,
8862 struct torture_printer_context
*t
=
8863 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8864 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8865 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8867 torture_assert(tctx
,
8868 test_PrinterInfo_SD(tctx
, b
, &t
->handle
),
8869 "failed to test security descriptors");
8874 static bool test_printer_dm(struct torture_context
*tctx
,
8877 struct torture_printer_context
*t
=
8878 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8879 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8881 torture_assert(tctx
,
8882 test_PrinterInfo_DevMode(tctx
, p
, &t
->handle
, t
->info2
.printername
, t
->devmode
),
8883 "failed to test devicemodes");
8888 static bool test_printer_info_winreg(struct torture_context
*tctx
,
8891 struct torture_printer_context
*t
=
8892 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8893 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8895 torture_assert(tctx
,
8896 test_PrinterInfo_winreg(tctx
, p
, &t
->handle
, t
->info2
.printername
),
8897 "failed to test printer info winreg");
8902 static bool test_printserver_info_winreg(struct torture_context
*tctx
,
8905 struct test_spoolss_context
*t
=
8906 (struct test_spoolss_context
*)talloc_get_type_abort(private_data
, struct test_spoolss_context
);
8907 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8909 torture_assert(tctx
,
8910 test_PrintserverInfo_winreg(tctx
, p
, &t
->server_handle
),
8911 "failed to test printserver info winreg");
8917 static bool test_printer_change_id(struct torture_context
*tctx
,
8920 struct torture_printer_context
*t
=
8921 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8922 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8924 torture_assert(tctx
,
8925 test_ChangeID(tctx
, p
, &t
->handle
),
8926 "failed to test change id");
8931 static bool test_printer_keys(struct torture_context
*tctx
,
8934 struct torture_printer_context
*t
=
8935 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8936 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8937 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8939 torture_assert(tctx
,
8940 test_printer_all_keys(tctx
, b
, &t
->handle
),
8941 "failed to test printer keys");
8946 static bool test_printer_data_consistency(struct torture_context
*tctx
,
8949 struct torture_printer_context
*t
=
8950 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8951 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8953 torture_assert(tctx
,
8954 test_EnumPrinterData_consistency(tctx
, p
, &t
->handle
),
8955 "failed to test printer data consistency");
8960 static bool test_printer_data_keys(struct torture_context
*tctx
,
8963 struct torture_printer_context
*t
=
8964 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8965 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8967 torture_assert(tctx
,
8968 test_SetPrinterDataEx_keys(tctx
, p
, &t
->handle
),
8969 "failed to test printer data keys");
8974 static bool test_printer_data_values(struct torture_context
*tctx
,
8977 struct torture_printer_context
*t
=
8978 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8979 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8981 torture_assert(tctx
,
8982 test_SetPrinterDataEx_values(tctx
, p
, &t
->handle
),
8983 "failed to test printer data values");
8988 static bool test_printer_data_set(struct torture_context
*tctx
,
8991 struct torture_printer_context
*t
=
8992 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8993 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8995 torture_assert(tctx
,
8996 test_SetPrinterDataEx_matrix(tctx
, p
, &t
->handle
, t
->info2
.printername
, NULL
, NULL
),
8997 "failed to test printer data set");
9002 static bool test_printer_data_winreg(struct torture_context
*tctx
,
9005 struct torture_printer_context
*t
=
9006 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
9007 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9009 torture_assert(tctx
,
9010 test_PrinterData_winreg(tctx
, p
, &t
->handle
, t
->info2
.printername
),
9011 "failed to test printer data winreg");
9016 static bool test_printer_data_dsspooler(struct torture_context
*tctx
,
9019 struct torture_printer_context
*t
=
9020 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
9021 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9023 torture_assert(tctx
,
9024 test_PrinterData_DsSpooler(tctx
, p
, &t
->handle
, t
->info2
.printername
),
9025 "failed to test printer data winreg dsspooler");
9030 static bool test_printer_ic(struct torture_context
*tctx
,
9033 struct torture_printer_context
*t
=
9034 talloc_get_type_abort(private_data
,
9035 struct torture_printer_context
);
9036 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9037 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
9038 struct policy_handle gdi_handle
;
9040 if (torture_setting_bool(tctx
, "samba3", false)) {
9041 torture_skip(tctx
, "skip printer information context tests against samba");
9045 struct spoolss_CreatePrinterIC r
;
9046 struct spoolss_DevmodeContainer devmode_ctr
;
9048 ZERO_STRUCT(devmode_ctr
);
9050 r
.in
.handle
= &t
->handle
;
9051 r
.in
.devmode_ctr
= &devmode_ctr
;
9052 r
.out
.gdi_handle
= &gdi_handle
;
9054 torture_assert_ntstatus_ok(tctx
,
9055 dcerpc_spoolss_CreatePrinterIC_r(b
, tctx
, &r
),
9056 "CreatePrinterIC failed");
9057 torture_assert_werr_ok(tctx
, r
.out
.result
,
9058 "CreatePrinterIC failed");
9062 struct spoolss_PlayGDIScriptOnPrinterIC r
;
9065 uint32_t num_fonts
= 0;
9067 in
= data_blob_string_const("");
9069 r
.in
.gdi_handle
= &gdi_handle
;
9071 r
.in
.cIn
= in
.length
;
9074 for (i
= 0; i
< 4; i
++) {
9076 out
= data_blob_talloc_zero(tctx
, i
);
9078 r
.in
.cOut
= out
.length
;
9079 r
.out
.pOut
= out
.data
;
9081 torture_assert_ntstatus_ok(tctx
,
9082 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b
, tctx
, &r
),
9083 "PlayGDIScriptOnPrinterIC failed");
9084 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_NOT_ENOUGH_MEMORY
,
9085 "PlayGDIScriptOnPrinterIC failed");
9088 out
= data_blob_talloc_zero(tctx
, 4);
9090 r
.in
.cOut
= out
.length
;
9091 r
.out
.pOut
= out
.data
;
9093 torture_assert_ntstatus_ok(tctx
,
9094 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b
, tctx
, &r
),
9095 "PlayGDIScriptOnPrinterIC failed");
9096 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_OK
,
9097 "PlayGDIScriptOnPrinterIC failed");
9099 /* now we should have the required length, so retry with a
9100 * buffer which is large enough to carry all font ids */
9102 num_fonts
= IVAL(r
.out
.pOut
, 0);
9104 torture_comment(tctx
, "PlayGDIScriptOnPrinterIC gave font count of %d\n", num_fonts
);
9106 out
= data_blob_talloc_zero(tctx
,
9107 num_fonts
* sizeof(struct UNIVERSAL_FONT_ID
) + 4);
9109 r
.in
.cOut
= out
.length
;
9110 r
.out
.pOut
= out
.data
;
9112 torture_assert_ntstatus_ok(tctx
,
9113 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b
, tctx
, &r
),
9114 "PlayGDIScriptOnPrinterIC failed");
9115 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_OK
,
9116 "PlayGDIScriptOnPrinterIC failed");
9121 struct spoolss_DeletePrinterIC r
;
9123 r
.in
.gdi_handle
= &gdi_handle
;
9124 r
.out
.gdi_handle
= &gdi_handle
;
9126 torture_assert_ntstatus_ok(tctx
,
9127 dcerpc_spoolss_DeletePrinterIC_r(b
, tctx
, &r
),
9128 "DeletePrinterIC failed");
9129 torture_assert_werr_ok(tctx
, r
.out
.result
,
9130 "DeletePrinterIC failed");
9137 static bool test_printer_bidi(struct torture_context
*tctx
,
9140 struct torture_printer_context
*t
=
9141 talloc_get_type_abort(private_data
,
9142 struct torture_printer_context
);
9143 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9144 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
9145 struct spoolss_SendRecvBidiData r
;
9146 struct RPC_BIDI_REQUEST_CONTAINER bidi_req
;
9147 struct RPC_BIDI_RESPONSE_CONTAINER
*bidi_rep
= NULL
;
9149 if (torture_setting_bool(tctx
, "samba3", false)) {
9150 torture_skip(tctx
, "skip printer bidirectional tests against samba");
9153 ZERO_STRUCT(bidi_req
);
9155 r
.in
.hPrinter
= t
->handle
;
9156 r
.in
.pAction
= "foobar";
9157 r
.in
.pReqData
= &bidi_req
;
9158 r
.out
.ppRespData
= &bidi_rep
;
9160 torture_assert_ntstatus_ok(tctx
,
9161 dcerpc_spoolss_SendRecvBidiData_r(b
, tctx
, &r
),
9162 "SendRecvBidiData failed");
9163 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_NOT_SUPPORTED
,
9164 "SendRecvBidiData failed");
9166 if (!(t
->info2
.attributes
& PRINTER_ATTRIBUTE_ENABLE_BIDI
)) {
9167 torture_skip(tctx
, "skipping further tests as printer is not BIDI enabled");
9170 r
.in
.pAction
= BIDI_ACTION_ENUM_SCHEMA
;
9172 torture_assert_ntstatus_ok(tctx
,
9173 dcerpc_spoolss_SendRecvBidiData_r(b
, tctx
, &r
),
9174 "SendRecvBidiData failed");
9175 torture_assert_werr_ok(tctx
, r
.out
.result
,
9176 "SendRecvBidiData failed");
9181 static bool test_printer_set_publish(struct torture_context
*tctx
,
9182 struct dcerpc_binding_handle
*b
,
9183 struct policy_handle
*handle
)
9185 union spoolss_PrinterInfo info
;
9186 struct spoolss_SetPrinterInfo7 info7
;
9187 struct spoolss_SetPrinterInfoCtr info_ctr
;
9188 struct spoolss_DevmodeContainer devmode_ctr
;
9189 struct sec_desc_buf secdesc_ctr
;
9192 info7
.action
= DSPRINT_PUBLISH
;
9194 ZERO_STRUCT(info_ctr
);
9195 ZERO_STRUCT(devmode_ctr
);
9196 ZERO_STRUCT(secdesc_ctr
);
9198 info_ctr
.info
.info7
= &info7
;
9200 torture_assert(tctx
,
9201 test_SetPrinter(tctx
, b
, handle
, &info_ctr
,
9202 &devmode_ctr
, &secdesc_ctr
, 0), "");
9204 torture_assert(tctx
,
9205 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
9207 torture_assert(tctx
,
9208 (info
.info2
.attributes
& PRINTER_ATTRIBUTE_PUBLISHED
),
9209 "info2 publish flag not set");
9210 torture_assert(tctx
,
9211 test_GetPrinter_level(tctx
, b
, handle
, 7, &info
),
9213 if (info
.info7
.action
& DSPRINT_PENDING
) {
9214 torture_comment(tctx
, "publish is pending\n");
9215 torture_assert_int_equal(tctx
,
9217 (DSPRINT_PENDING
| DSPRINT_PUBLISH
),
9218 "info7 publish flag not set");
9222 torture_assert_int_equal(tctx
,
9225 "info7 publish flag not set");
9227 /* GUID_from_string is able to parse both plain and
9228 * curly-braced guids */
9229 torture_assert_ntstatus_ok(tctx
,
9230 GUID_from_string(info
.info7
.guid
,
9232 "invalid published printer GUID");
9234 /* Build reference GUID string */
9235 ref_guid
= GUID_string2(tctx
, &guid
);
9236 torture_assert_not_null(tctx
, ref_guid
, "ENOMEM");
9237 ref_guid
= talloc_strdup_upper(tctx
, ref_guid
);
9238 torture_assert_not_null(tctx
, ref_guid
, "ENOMEM");
9239 torture_assert_str_equal(tctx
, info
.info7
.guid
, ref_guid
,
9240 "invalid GUID format");
9246 static bool test_printer_set_unpublish(struct torture_context
*tctx
,
9247 struct dcerpc_binding_handle
*b
,
9248 struct policy_handle
*handle
)
9250 union spoolss_PrinterInfo info
;
9251 struct spoolss_SetPrinterInfo7 info7
;
9252 struct spoolss_SetPrinterInfoCtr info_ctr
;
9253 struct spoolss_DevmodeContainer devmode_ctr
;
9254 struct sec_desc_buf secdesc_ctr
;
9256 info7
.action
= DSPRINT_UNPUBLISH
;
9259 ZERO_STRUCT(info_ctr
);
9260 ZERO_STRUCT(devmode_ctr
);
9261 ZERO_STRUCT(secdesc_ctr
);
9263 info_ctr
.info
.info7
= &info7
;
9265 torture_assert(tctx
,
9266 test_SetPrinter(tctx
, b
, handle
, &info_ctr
,
9267 &devmode_ctr
, &secdesc_ctr
, 0), "");
9269 torture_assert(tctx
,
9270 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
9272 torture_assert(tctx
,
9273 !(info
.info2
.attributes
& PRINTER_ATTRIBUTE_PUBLISHED
),
9274 "info2 publish flag still set");
9275 torture_assert(tctx
,
9276 test_GetPrinter_level(tctx
, b
, handle
, 7, &info
),
9279 if (info
.info7
.action
& DSPRINT_PENDING
) {
9281 torture_comment(tctx
, "unpublish is pending\n");
9282 torture_assert_int_equal(tctx
,
9284 (DSPRINT_PENDING
| DSPRINT_UNPUBLISH
),
9285 "info7 unpublish flag not set");
9286 torture_assert_ntstatus_ok(tctx
,
9287 GUID_from_string(info
.info7
.guid
,
9289 "invalid printer GUID");
9291 torture_assert_int_equal(tctx
,
9292 info
.info7
.action
, DSPRINT_UNPUBLISH
,
9293 "info7 unpublish flag not set");
9299 static bool test_printer_publish_toggle(struct torture_context
*tctx
,
9302 struct torture_printer_context
*t
=
9303 talloc_get_type_abort(private_data
,
9304 struct torture_printer_context
);
9305 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9306 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
9307 struct policy_handle
*handle
= &t
->handle
;
9308 union spoolss_PrinterInfo info7
;
9309 union spoolss_PrinterInfo info2
;
9311 /* check publish status via level 7 and level 2 */
9312 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 7, &info7
),
9314 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info2
),
9317 if (info2
.info2
.attributes
& PRINTER_ATTRIBUTE_PUBLISHED
) {
9318 torture_assert_int_equal(tctx
,
9319 info7
.info7
.action
, DSPRINT_PUBLISH
,
9320 "info7 publish flag not set");
9321 torture_assert(tctx
, test_printer_set_unpublish(tctx
, b
, handle
), "");
9322 torture_assert(tctx
, test_printer_set_publish(tctx
, b
, handle
), "");
9324 torture_assert_int_equal(tctx
,
9325 info7
.info7
.action
, DSPRINT_UNPUBLISH
,
9326 "info7 unpublish flag not set");
9327 torture_assert(tctx
, test_printer_set_publish(tctx
, b
, handle
), "");
9328 torture_assert(tctx
, test_printer_set_unpublish(tctx
, b
, handle
), "");
9334 static bool test_driver_info_winreg(struct torture_context
*tctx
,
9337 struct torture_printer_context
*t
=
9338 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
9339 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9340 const char *driver_name
= t
->added_driver
? t
->driver
.info8
.driver_name
: t
->info2
.drivername
;
9342 if (!t
->have_driver
) {
9343 torture_skip(tctx
, "skipping driver info winreg test as we don't have a driver");
9346 torture_assert(tctx
,
9347 test_DriverInfo_winreg(tctx
, p
, &t
->handle
, t
->info2
.printername
, driver_name
, t
->driver
.remote
.environment
, 3),
9348 "failed to test driver info winreg");
9353 static bool test_print_job_enum(struct torture_context
*tctx
,
9356 struct torture_printer_context
*t
=
9357 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
9358 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9359 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
9361 uint32_t num_jobs
= 8;
9364 union spoolss_JobInfo
*info
= NULL
;
9367 torture_assert(tctx
,
9368 test_PausePrinter(tctx
, b
, &t
->handle
),
9369 "failed to pause printer");
9371 /* purge in case of any jobs from previous tests */
9372 torture_assert(tctx
,
9373 test_printer_purge(tctx
, b
, &t
->handle
),
9374 "failed to purge printer");
9376 /* enum before jobs, valid level */
9377 torture_assert(tctx
,
9378 test_EnumJobs_args(tctx
, b
, &t
->handle
, 1, WERR_OK
,
9380 "EnumJobs with valid level");
9381 torture_assert_int_equal(tctx
, count
, 0, "EnumJobs count");
9382 torture_assert(tctx
,
9383 test_EnumJobs_args(tctx
, b
, &t
->handle
, 2, WERR_OK
,
9385 "EnumJobs with valid level");
9386 torture_assert_int_equal(tctx
, count
, 0, "EnumJobs count");
9387 /* enum before jobs, invalid level - expect failure */
9388 torture_assert(tctx
,
9389 test_EnumJobs_args(tctx
, b
, &t
->handle
, 100,
9392 "EnumJobs with invalid level");
9394 job_ids
= talloc_zero_array(tctx
, uint32_t, num_jobs
);
9396 for (i
= 0; i
< num_jobs
; i
++) {
9397 ret
= test_DoPrintTest_add_one_job(tctx
, b
, &t
->handle
,
9400 torture_assert(tctx
, ret
, "failed to add print job");
9403 /* enum after jobs, valid level */
9404 torture_assert(tctx
,
9405 test_EnumJobs_args(tctx
, b
, &t
->handle
, 1, WERR_OK
,
9407 "EnumJobs with valid level");
9408 torture_assert_int_equal(tctx
, count
, num_jobs
, "EnumJobs count");
9409 torture_assert(tctx
,
9410 test_EnumJobs_args(tctx
, b
, &t
->handle
, 2, WERR_OK
,
9412 "EnumJobs with valid level");
9413 torture_assert_int_equal(tctx
, count
, num_jobs
, "EnumJobs count");
9414 /* enum after jobs, invalid level - expect failure */
9415 torture_assert(tctx
,
9416 test_EnumJobs_args(tctx
, b
, &t
->handle
, 100,
9419 "EnumJobs with invalid level");
9421 for (i
= 0; i
< num_jobs
; i
++) {
9422 test_SetJob(tctx
, b
, &t
->handle
, job_ids
[i
], NULL
,
9423 SPOOLSS_JOB_CONTROL_DELETE
);
9426 torture_assert(tctx
,
9427 test_ResumePrinter(tctx
, b
, &t
->handle
),
9428 "failed to resume printer");
9433 static bool test_printer_log_jobinfo(struct torture_context
*tctx
,
9436 struct torture_printer_context
*t
=
9437 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
9438 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9439 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
9440 struct spoolss_BranchOfficeJobDataContainer info
;
9443 struct spoolss_LogJobInfoForBranchOffice r
;
9445 torture_comment(tctx
, "Testing LogJobInfoForBranchOffice\n");
9447 info
.cJobDataEntries
= 0;
9448 info
.JobData
= NULL
;
9450 r
.in
.hPrinter
= &t
->handle
;
9451 r
.in
.pBranchOfficeJobDataContainer
= &info
;
9453 torture_assert_ntstatus_ok(tctx
,
9454 dcerpc_spoolss_LogJobInfoForBranchOffice_r(b
, tctx
, &r
),
9455 "LogJobInfoForBranchOffice failed");
9456 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAMETER
,
9457 "LogJobInfoForBranchOffice failed");
9459 info
.cJobDataEntries
= 1;
9460 info
.JobData
= talloc_zero_array(tctx
, struct spoolss_BranchOfficeJobData
, info
.cJobDataEntries
);
9462 info
.JobData
[0].eEventType
= kLogOfflineFileFull
;
9463 info
.JobData
[0].JobId
= 42;
9464 info
.JobData
[0].JobInfo
.LogOfflineFileFull
.pMachineName
= talloc_strdup(tctx
, "mthelena");
9466 torture_assert_ntstatus_ok(tctx
,
9467 dcerpc_spoolss_LogJobInfoForBranchOffice_r(b
, tctx
, &r
),
9468 "LogJobInfoForBranchOffice failed");
9469 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_OK
,
9470 "LogJobInfoForBranchOffice failed");
9472 info
.cJobDataEntries
= 42;
9473 info
.JobData
= talloc_zero_array(tctx
, struct spoolss_BranchOfficeJobData
, info
.cJobDataEntries
);
9475 for (i
=0; i
< info
.cJobDataEntries
; i
++) {
9476 info
.JobData
[i
].eEventType
= kLogOfflineFileFull
;
9477 info
.JobData
[i
].JobId
= i
;
9478 info
.JobData
[i
].JobInfo
.LogOfflineFileFull
.pMachineName
= talloc_asprintf(tctx
, "torture_%d", i
);
9481 torture_assert_ntstatus_ok(tctx
,
9482 dcerpc_spoolss_LogJobInfoForBranchOffice_r(b
, tctx
, &r
),
9483 "LogJobInfoForBranchOffice failed");
9484 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_OK
,
9485 "LogJobInfoForBranchOffice failed");
9490 static bool test_printer_os_versions(struct torture_context
*tctx
,
9493 struct torture_printer_context
*t
=
9494 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
9495 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9496 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
9497 union spoolss_PrinterInfo info
;
9501 struct spoolss_OSVersion osversion
;
9502 uint8_t os_major
, os_minor
;
9504 struct policy_handle server_handle
;
9506 torture_comment(tctx
, "Testing OSVersion vs. PRINTER_INFO_STRESS\n");
9508 torture_assert(tctx
,
9509 test_GetPrinter_level(tctx
, b
, &t
->handle
, 0, &info
),
9510 "failed to get level 0 printer info");
9512 torture_assert(tctx
,
9513 test_OpenPrinter_server(tctx
, p
, &server_handle
),
9514 "failed to open printserver");
9516 torture_assert(tctx
,
9517 test_GetPrinterData_checktype(tctx
, b
, &server_handle
, "OSVersion",
9518 NULL
, NULL
, &data
, &length
),
9519 "failed to fetch OSVersion printer data");
9521 test_ClosePrinter(tctx
, b
, &server_handle
);
9523 blob
= data_blob_const(data
, length
);
9525 torture_assert_ndr_success(tctx
,
9526 ndr_pull_struct_blob(&blob
, tctx
, &osversion
,
9527 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_OSVersion
),
9528 "failed to pull OSVersion");
9530 os_major
= CVAL(&info
.info0
.version
, 0);
9531 os_minor
= CVAL(&info
.info0
.version
, 1);
9532 os_build
= SVAL(&info
.info0
.version
, 2);
9534 torture_assert_int_equal(tctx
, os_major
, osversion
.major
, "major");
9535 torture_assert_int_equal(tctx
, os_minor
, osversion
.minor
, "minor");
9536 torture_assert_int_equal(tctx
, os_build
, osversion
.build
, "build");
9542 void torture_tcase_printer(struct torture_tcase
*tcase
)
9544 torture_tcase_add_simple_test(tcase
, "openprinter", test_openprinter_wrap
);
9545 torture_tcase_add_simple_test(tcase
, "csetprinter", test_csetprinter
);
9546 torture_tcase_add_simple_test(tcase
, "print_test", test_print_test
);
9547 torture_tcase_add_simple_test(tcase
, "print_test_extended", test_print_test_extended
);
9548 torture_tcase_add_simple_test(tcase
, "print_test_smbd", test_print_test_smbd
);
9549 torture_tcase_add_simple_test(tcase
, "print_test_properties", test_print_test_properties
);
9550 torture_tcase_add_simple_test(tcase
, "print_test_purge", test_print_test_purge
);
9551 torture_tcase_add_simple_test(tcase
, "printer_info", test_printer_info
);
9552 torture_tcase_add_simple_test(tcase
, "sd", test_printer_sd
);
9553 torture_tcase_add_simple_test(tcase
, "dm", test_printer_dm
);
9554 torture_tcase_add_simple_test(tcase
, "printer_info_winreg", test_printer_info_winreg
);
9555 torture_tcase_add_simple_test(tcase
, "change_id", test_printer_change_id
);
9556 torture_tcase_add_simple_test(tcase
, "keys", test_printer_keys
);
9557 torture_tcase_add_simple_test(tcase
, "printerdata_consistency", test_printer_data_consistency
);
9558 torture_tcase_add_simple_test(tcase
, "printerdata_keys", test_printer_data_keys
);
9559 torture_tcase_add_simple_test(tcase
, "printerdata_values", test_printer_data_values
);
9560 torture_tcase_add_simple_test(tcase
, "printerdata_set", test_printer_data_set
);
9561 torture_tcase_add_simple_test(tcase
, "printerdata_winreg", test_printer_data_winreg
);
9562 torture_tcase_add_simple_test(tcase
, "printerdata_dsspooler", test_printer_data_dsspooler
);
9563 torture_tcase_add_simple_test(tcase
, "driver_info_winreg", test_driver_info_winreg
);
9564 torture_tcase_add_simple_test(tcase
, "printer_rename", test_printer_rename
);
9565 torture_tcase_add_simple_test(tcase
, "printer_ic", test_printer_ic
);
9566 torture_tcase_add_simple_test(tcase
, "bidi", test_printer_bidi
);
9567 torture_tcase_add_simple_test(tcase
, "publish_toggle",
9568 test_printer_publish_toggle
);
9569 torture_tcase_add_simple_test(tcase
, "print_job_enum", test_print_job_enum
);
9570 torture_tcase_add_simple_test(tcase
, "log_jobinfo", test_printer_log_jobinfo
);
9571 torture_tcase_add_simple_test(tcase
, "os_versions", test_printer_os_versions
);
9574 struct torture_suite
*torture_rpc_spoolss_printer(TALLOC_CTX
*mem_ctx
)
9576 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "printer");
9577 struct torture_tcase
*tcase
;
9579 tcase
= torture_suite_add_tcase(suite
, "addprinter");
9581 torture_tcase_set_fixture(tcase
,
9582 torture_rpc_spoolss_printer_setup
,
9583 torture_rpc_spoolss_printer_teardown
);
9585 torture_tcase_printer(tcase
);
9587 tcase
= torture_suite_add_tcase(suite
, "addprinterex");
9589 torture_tcase_set_fixture(tcase
,
9590 torture_rpc_spoolss_printerex_setup
,
9591 torture_rpc_spoolss_printer_teardown
);
9593 torture_tcase_printer(tcase
);
9595 tcase
= torture_suite_add_tcase(suite
, "addprinterwkn");
9597 torture_tcase_set_fixture(tcase
,
9598 torture_rpc_spoolss_printerwkn_setup
,
9599 torture_rpc_spoolss_printer_teardown
);
9601 tcase
= torture_suite_add_tcase(suite
, "addprinterexwkn");
9603 torture_tcase_set_fixture(tcase
,
9604 torture_rpc_spoolss_printerexwkn_setup
,
9605 torture_rpc_spoolss_printer_teardown
);
9608 /* test is not correct */
9609 tcase
= torture_suite_add_tcase(suite
, "addprinterdm");
9611 torture_tcase_set_fixture(tcase
,
9612 torture_rpc_spoolss_printerdm_setup
,
9613 torture_rpc_spoolss_printer_teardown
);
9615 torture_tcase_printer(tcase
);
9620 struct torture_suite
*torture_rpc_spoolss(TALLOC_CTX
*mem_ctx
)
9622 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "spoolss");
9623 struct torture_tcase
*tcase
= torture_suite_add_tcase(suite
, "printserver");
9625 torture_tcase_set_fixture(tcase
,
9626 torture_rpc_spoolss_setup
,
9627 torture_rpc_spoolss_teardown
);
9629 torture_tcase_add_simple_test(tcase
, "openprinter_badnamelist", test_OpenPrinter_badname_list
);
9630 torture_tcase_add_simple_test(tcase
, "printer_data_list", test_GetPrinterData_list
);
9631 torture_tcase_add_simple_test(tcase
, "enum_forms", test_PrintServer_EnumForms
);
9632 torture_tcase_add_simple_test(tcase
, "forms", test_PrintServer_Forms
);
9633 torture_tcase_add_simple_test(tcase
, "forms_winreg", test_PrintServer_Forms_Winreg
);
9634 torture_tcase_add_simple_test(tcase
, "enum_ports", test_EnumPorts
);
9635 torture_tcase_add_simple_test(tcase
, "add_port", test_AddPort
);
9636 torture_tcase_add_simple_test(tcase
, "get_printer_driver_directory", test_GetPrinterDriverDirectory
);
9637 torture_tcase_add_simple_test(tcase
, "get_print_processor_directory", test_GetPrintProcessorDirectory
);
9638 torture_tcase_add_simple_test(tcase
, "enum_printer_drivers", test_EnumPrinterDrivers
);
9639 torture_tcase_add_simple_test(tcase
, "enum_monitors", test_EnumMonitors
);
9640 torture_tcase_add_simple_test(tcase
, "enum_print_processors", test_EnumPrintProcessors
);
9641 torture_tcase_add_simple_test(tcase
, "print_processors_winreg", test_print_processors_winreg
);
9642 torture_tcase_add_simple_test(tcase
, "add_processor", test_add_print_processor
);
9643 torture_tcase_add_simple_test(tcase
, "enum_printprocdata", test_EnumPrintProcessorDataTypes
);
9644 torture_tcase_add_simple_test(tcase
, "enum_printers", test_EnumPrinters
);
9645 torture_tcase_add_simple_test(tcase
, "enum_ports_old", test_EnumPorts_old
);
9646 torture_tcase_add_simple_test(tcase
, "enum_printers_old", test_EnumPrinters_old
);
9647 torture_tcase_add_simple_test(tcase
, "enum_printers_servername", test_EnumPrinters_servername
);
9648 torture_tcase_add_simple_test(tcase
, "enum_printer_drivers_old", test_EnumPrinterDrivers_old
);
9649 torture_tcase_add_simple_test(tcase
, "architecture_buffer", test_architecture_buffer
);
9650 torture_tcase_add_simple_test(tcase
, "get_core_printer_drivers", test_get_core_printer_drivers
);
9651 torture_tcase_add_simple_test(tcase
, "get_printer_driver_package_path", test_get_printer_driver_package_path
);
9652 torture_tcase_add_simple_test(tcase
, "get_printer", test_get_printer_printserverhandle
);
9653 torture_tcase_add_simple_test(tcase
, "set_printer", test_set_printer_printserverhandle
);
9654 torture_tcase_add_simple_test(tcase
, "printserver_info_winreg", test_printserver_info_winreg
);
9656 torture_suite_add_suite(suite
, torture_rpc_spoolss_printer(suite
));
9661 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context
*tctx
,
9662 struct dcerpc_binding_handle
*b
,
9664 const char *environment
,
9667 struct spoolss_GetPrinterDriverDirectory r
;
9670 r
.in
.server
= server
;
9671 r
.in
.environment
= environment
;
9675 r
.out
.needed
= &needed
;
9677 torture_assert_ntstatus_ok(tctx
,
9678 dcerpc_spoolss_GetPrinterDriverDirectory_r(b
, tctx
, &r
),
9679 "failed to query driver directory");
9681 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
9682 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
9683 r
.in
.buffer
= &blob
;
9684 r
.in
.offered
= needed
;
9686 torture_assert_ntstatus_ok(tctx
,
9687 dcerpc_spoolss_GetPrinterDriverDirectory_r(b
, tctx
, &r
),
9688 "failed to query driver directory");
9691 torture_assert_werr_ok(tctx
, r
.out
.result
,
9692 "failed to query driver directory");
9695 *dir_p
= r
.out
.info
->info1
.directory_name
;
9701 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr
*info_ctr
)
9703 if (info_ctr
== NULL
) {
9707 switch (info_ctr
->level
) {
9709 return info_ctr
->info
.info1
->driver_name
;
9711 return info_ctr
->info
.info2
->driver_name
;
9713 return info_ctr
->info
.info3
->driver_name
;
9715 return info_ctr
->info
.info4
->driver_name
;
9717 return info_ctr
->info
.info6
->driver_name
;
9719 return info_ctr
->info
.info8
->driver_name
;
9725 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr
*info_ctr
)
9727 if (info_ctr
== NULL
) {
9731 switch (info_ctr
->level
) {
9733 return info_ctr
->info
.info2
->architecture
;
9735 return info_ctr
->info
.info3
->architecture
;
9737 return info_ctr
->info
.info4
->architecture
;
9739 return info_ctr
->info
.info6
->architecture
;
9741 return info_ctr
->info
.info8
->architecture
;
9748 static bool test_AddPrinterDriver_exp(struct torture_context
*tctx
,
9749 struct dcerpc_binding_handle
*b
,
9750 const char *servername
,
9751 struct spoolss_AddDriverInfoCtr
*info_ctr
,
9752 WERROR expected_result
)
9754 struct spoolss_AddPrinterDriver r
;
9755 const char *drivername
= get_driver_from_info(info_ctr
);
9756 const char *environment
= get_environment_from_info(info_ctr
);
9758 r
.in
.servername
= servername
;
9759 r
.in
.info_ctr
= info_ctr
;
9761 torture_comment(tctx
, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
9762 drivername
, info_ctr
->level
, environment
);
9764 torture_assert_ntstatus_ok(tctx
,
9765 dcerpc_spoolss_AddPrinterDriver_r(b
, tctx
, &r
),
9766 "spoolss_AddPrinterDriver failed");
9767 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
9768 "spoolss_AddPrinterDriver failed with unexpected result");
9774 static bool test_AddPrinterDriverEx_exp(struct torture_context
*tctx
,
9775 struct dcerpc_binding_handle
*b
,
9776 const char *servername
,
9777 struct spoolss_AddDriverInfoCtr
*info_ctr
,
9779 WERROR expected_result
)
9781 struct spoolss_AddPrinterDriverEx r
;
9782 const char *drivername
= get_driver_from_info(info_ctr
);
9783 const char *environment
= get_environment_from_info(info_ctr
);
9785 r
.in
.servername
= servername
;
9786 r
.in
.info_ctr
= info_ctr
;
9789 torture_comment(tctx
, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
9790 drivername
, info_ctr
->level
, environment
);
9792 torture_assert_ntstatus_ok(tctx
,
9793 dcerpc_spoolss_AddPrinterDriverEx_r(b
, tctx
, &r
),
9794 "AddPrinterDriverEx failed");
9795 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
9796 "AddPrinterDriverEx failed with unexpected result");
9801 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
9802 if (path && strlen(path)) {\
9803 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
9806 static bool test_AddPrinterDriver_args_level_1(struct torture_context
*tctx
,
9807 struct dcerpc_binding_handle
*b
,
9808 const char *server_name
,
9809 struct spoolss_AddDriverInfo8
*r
,
9812 const char *remote_driver_dir
)
9814 struct spoolss_AddDriverInfoCtr info_ctr
;
9815 struct spoolss_AddDriverInfo1 info1
;
9820 info_ctr
.info
.info1
= &info1
;
9823 torture_assert(tctx
,
9824 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_LEVEL
),
9825 "failed to test AddPrinterDriverEx level 1");
9827 torture_assert(tctx
,
9828 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_LEVEL
),
9829 "failed to test AddPrinterDriver level 1");
9832 info1
.driver_name
= r
->driver_name
;
9835 torture_assert(tctx
,
9836 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_LEVEL
),
9837 "failed to test AddPrinterDriverEx level 1");
9839 torture_assert(tctx
,
9840 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_LEVEL
),
9841 "failed to test AddPrinterDriver level 1");
9847 static bool test_AddPrinterDriver_args_level_2(struct torture_context
*tctx
,
9848 struct dcerpc_binding_handle
*b
,
9849 const char *server_name
,
9850 struct spoolss_AddDriverInfo8
*r
,
9853 const char *remote_driver_dir
)
9855 struct spoolss_AddDriverInfoCtr info_ctr
;
9856 struct spoolss_AddDriverInfo2 info2
;
9857 union spoolss_DriverInfo info
;
9862 info_ctr
.info
.info2
= &info2
;
9865 torture_assert(tctx
,
9866 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAMETER
),
9867 "failed to test AddPrinterDriverEx level 2");
9869 torture_assert(tctx
,
9870 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAMETER
),
9871 "failed to test AddPrinterDriver level 2");
9874 info2
.driver_name
= r
->driver_name
;
9877 torture_assert(tctx
,
9878 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAMETER
),
9879 "failed to test AddPrinterDriverEx level 2");
9881 torture_assert(tctx
,
9882 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAMETER
),
9883 "failed to test AddPrinterDriver level 2");
9886 info2
.version
= r
->version
;
9889 torture_assert(tctx
,
9890 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAMETER
),
9891 "failed to test AddPrinterDriverEx level 2");
9893 torture_assert(tctx
,
9894 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAMETER
),
9895 "failed to test AddPrinterDriver level 2");
9898 info2
.architecture
= r
->architecture
;
9901 torture_assert(tctx
,
9902 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAMETER
),
9903 "failed to test AddPrinterDriverEx level 2");
9905 torture_assert(tctx
,
9906 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAMETER
),
9907 "failed to test AddPrinterDriver level 2");
9910 info2
.driver_path
= r
->driver_path
;
9913 torture_assert(tctx
,
9914 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAMETER
),
9915 "failed to test AddPrinterDriverEx level 2");
9917 torture_assert(tctx
,
9918 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAMETER
),
9919 "failed to test AddPrinterDriver level 2");
9922 info2
.data_file
= r
->data_file
;
9925 torture_assert(tctx
,
9926 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAMETER
),
9927 "failed to test AddPrinterDriverEx level 2");
9929 torture_assert(tctx
,
9930 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAMETER
),
9931 "failed to test AddPrinterDriver level 2");
9934 info2
.config_file
= r
->config_file
;
9937 torture_assert(tctx
,
9938 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, 0, WERR_INVALID_PARAMETER
),
9939 "failed to test AddPrinterDriverEx");
9943 torture_assert(tctx
,
9944 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_OK
),
9945 "failed to test AddPrinterDriverEx level 2");
9947 torture_assert(tctx
,
9948 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_OK
),
9949 "failed to test AddPrinterDriver level 2");
9952 torture_assert(tctx
,
9953 test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, r
->architecture
, 2, r
->driver_name
, &info
),
9954 "failed to find added printer driver");
9956 if (remote_driver_dir
) {
9957 ASSERT_DRIVER_PATH(tctx
, info
.info2
.driver_path
, remote_driver_dir
, "unexpected path");
9958 ASSERT_DRIVER_PATH(tctx
, info
.info2
.data_file
, remote_driver_dir
, "unexpected path");
9959 ASSERT_DRIVER_PATH(tctx
, info
.info2
.config_file
, remote_driver_dir
, "unexpected path");
9965 static bool test_AddPrinterDriver_args_level_3(struct torture_context
*tctx
,
9966 struct dcerpc_binding_handle
*b
,
9967 const char *server_name
,
9968 struct spoolss_AddDriverInfo8
*r
,
9971 const char *remote_driver_dir
)
9973 struct spoolss_AddDriverInfoCtr info_ctr
;
9974 struct spoolss_AddDriverInfo3 info3
;
9975 union spoolss_DriverInfo info
;
9977 info3
.driver_name
= r
->driver_name
;
9978 info3
.version
= r
->version
;
9979 info3
.architecture
= r
->architecture
;
9980 info3
.driver_path
= r
->driver_path
;
9981 info3
.data_file
= r
->data_file
;
9982 info3
.config_file
= r
->config_file
;
9983 info3
.help_file
= r
->help_file
;
9984 info3
.monitor_name
= r
->monitor_name
;
9985 info3
.default_datatype
= r
->default_datatype
;
9986 info3
._ndr_size_dependent_files
= r
->_ndr_size_dependent_files
;
9987 info3
.dependent_files
= r
->dependent_files
;
9990 info_ctr
.info
.info3
= &info3
;
9993 torture_assert(tctx
,
9994 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_OK
),
9995 "failed to test AddPrinterDriverEx level 3");
9997 torture_assert(tctx
,
9998 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_OK
),
9999 "failed to test AddPrinterDriver level 3");
10002 torture_assert(tctx
,
10003 test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, r
->architecture
, 3, r
->driver_name
, &info
),
10004 "failed to find added printer driver");
10006 if (remote_driver_dir
) {
10008 ASSERT_DRIVER_PATH(tctx
, info
.info3
.driver_path
, remote_driver_dir
, "unexpected path");
10009 ASSERT_DRIVER_PATH(tctx
, info
.info3
.data_file
, remote_driver_dir
, "unexpected path");
10010 ASSERT_DRIVER_PATH(tctx
, info
.info3
.config_file
, remote_driver_dir
, "unexpected path");
10011 ASSERT_DRIVER_PATH(tctx
, info
.info3
.help_file
, remote_driver_dir
, "unexpected path");
10012 for (i
=0; info
.info3
.dependent_files
&& info
.info3
.dependent_files
[i
] != NULL
; i
++) {
10013 ASSERT_DRIVER_PATH(tctx
, info
.info3
.dependent_files
[i
], remote_driver_dir
, "unexpected path");
10020 static bool test_AddPrinterDriver_args_level_4(struct torture_context
*tctx
,
10021 struct dcerpc_binding_handle
*b
,
10022 const char *server_name
,
10023 struct spoolss_AddDriverInfo8
*r
,
10026 const char *remote_driver_dir
)
10028 struct spoolss_AddDriverInfoCtr info_ctr
;
10029 struct spoolss_AddDriverInfo4 info4
;
10030 union spoolss_DriverInfo info
;
10032 info4
.version
= r
->version
;
10033 info4
.driver_name
= r
->driver_name
;
10034 info4
.architecture
= r
->architecture
;
10035 info4
.driver_path
= r
->driver_path
;
10036 info4
.data_file
= r
->data_file
;
10037 info4
.config_file
= r
->config_file
;
10038 info4
.help_file
= r
->help_file
;
10039 info4
.monitor_name
= r
->monitor_name
;
10040 info4
.default_datatype
= r
->default_datatype
;
10041 info4
._ndr_size_dependent_files
= r
->_ndr_size_dependent_files
;
10042 info4
.dependent_files
= r
->dependent_files
;
10043 info4
._ndr_size_previous_names
= r
->_ndr_size_previous_names
;
10044 info4
.previous_names
= r
->previous_names
;
10046 info_ctr
.level
= 4;
10047 info_ctr
.info
.info4
= &info4
;
10050 torture_assert(tctx
,
10051 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_OK
),
10052 "failed to test AddPrinterDriverEx level 4");
10054 torture_assert(tctx
,
10055 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_OK
),
10056 "failed to test AddPrinterDriver level 4");
10059 torture_assert(tctx
,
10060 test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, r
->architecture
, 4, r
->driver_name
, &info
),
10061 "failed to find added printer driver");
10063 if (remote_driver_dir
) {
10065 ASSERT_DRIVER_PATH(tctx
, info
.info4
.driver_path
, remote_driver_dir
, "unexpected path");
10066 ASSERT_DRIVER_PATH(tctx
, info
.info4
.data_file
, remote_driver_dir
, "unexpected path");
10067 ASSERT_DRIVER_PATH(tctx
, info
.info4
.config_file
, remote_driver_dir
, "unexpected path");
10068 ASSERT_DRIVER_PATH(tctx
, info
.info4
.help_file
, remote_driver_dir
, "unexpected path");
10069 for (i
=0; info
.info4
.dependent_files
&& info
.info4
.dependent_files
[i
] != NULL
; i
++) {
10070 ASSERT_DRIVER_PATH(tctx
, info
.info4
.dependent_files
[i
], remote_driver_dir
, "unexpected path");
10077 static bool test_AddPrinterDriver_args_level_6(struct torture_context
*tctx
,
10078 struct dcerpc_binding_handle
*b
,
10079 const char *server_name
,
10080 struct spoolss_AddDriverInfo8
*r
,
10083 const char *remote_driver_dir
)
10085 struct spoolss_AddDriverInfoCtr info_ctr
;
10086 struct spoolss_AddDriverInfo6 info6
;
10087 union spoolss_DriverInfo info
;
10089 info6
.version
= r
->version
;
10090 info6
.driver_name
= r
->driver_name
;
10091 info6
.architecture
= r
->architecture
;
10092 info6
.driver_path
= r
->driver_path
;
10093 info6
.data_file
= r
->data_file
;
10094 info6
.config_file
= r
->config_file
;
10095 info6
.help_file
= r
->help_file
;
10096 info6
.monitor_name
= r
->monitor_name
;
10097 info6
.default_datatype
= r
->default_datatype
;
10098 info6
._ndr_size_dependent_files
= r
->_ndr_size_dependent_files
;
10099 info6
.dependent_files
= r
->dependent_files
;
10100 info6
._ndr_size_previous_names
= r
->_ndr_size_previous_names
;
10101 info6
.previous_names
= r
->previous_names
;
10102 info6
.driver_date
= r
->driver_date
;
10103 info6
.driver_version
= r
->driver_version
;
10104 info6
.manufacturer_name
= r
->manufacturer_name
;
10105 info6
.manufacturer_url
= r
->manufacturer_url
;
10106 info6
.hardware_id
= r
->hardware_id
;
10107 info6
.provider
= r
->provider
;
10109 info_ctr
.level
= 6;
10110 info_ctr
.info
.info6
= &info6
;
10113 torture_assert(tctx
,
10114 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_OK
),
10115 "failed to test AddPrinterDriverEx level 6");
10117 torture_assert(tctx
,
10118 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_LEVEL
),
10119 "failed to test AddPrinterDriver level 6");
10122 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
10128 torture_assert(tctx
,
10129 test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, r
->architecture
, 6, r
->driver_name
, &info
),
10130 "failed to find added printer driver");
10132 if (remote_driver_dir
) {
10134 ASSERT_DRIVER_PATH(tctx
, info
.info6
.driver_path
, remote_driver_dir
, "unexpected path");
10135 ASSERT_DRIVER_PATH(tctx
, info
.info6
.data_file
, remote_driver_dir
, "unexpected path");
10136 ASSERT_DRIVER_PATH(tctx
, info
.info6
.config_file
, remote_driver_dir
, "unexpected path");
10137 ASSERT_DRIVER_PATH(tctx
, info
.info6
.help_file
, remote_driver_dir
, "unexpected path");
10138 for (i
=0; info
.info6
.dependent_files
&& info
.info6
.dependent_files
[i
] != NULL
; i
++) {
10139 ASSERT_DRIVER_PATH(tctx
, info
.info6
.dependent_files
[i
], remote_driver_dir
, "unexpected path");
10143 torture_assert_nttime_equal(tctx
, info
.info6
.driver_date
, info6
.driver_date
, "driverdate mismatch");
10144 torture_assert_u64_equal(tctx
, info
.info6
.driver_version
, info6
.driver_version
, "driverversion mismatch");
10149 static bool test_AddPrinterDriver_args_level_8(struct torture_context
*tctx
,
10150 struct dcerpc_binding_handle
*b
,
10151 const char *server_name
,
10152 struct spoolss_AddDriverInfo8
*r
,
10155 const char *remote_driver_dir
)
10157 struct spoolss_AddDriverInfoCtr info_ctr
;
10158 union spoolss_DriverInfo info
;
10160 info_ctr
.level
= 8;
10161 info_ctr
.info
.info8
= r
;
10164 torture_assert(tctx
,
10165 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_OK
),
10166 "failed to test AddPrinterDriverEx level 8");
10168 torture_assert(tctx
,
10169 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_LEVEL
),
10170 "failed to test AddPrinterDriver level 8");
10173 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
10179 torture_assert(tctx
,
10180 test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, r
->architecture
, 8, r
->driver_name
, &info
),
10181 "failed to find added printer driver");
10183 if (remote_driver_dir
) {
10185 ASSERT_DRIVER_PATH(tctx
, info
.info8
.driver_path
, remote_driver_dir
, "unexpected path");
10186 ASSERT_DRIVER_PATH(tctx
, info
.info8
.data_file
, remote_driver_dir
, "unexpected path");
10187 ASSERT_DRIVER_PATH(tctx
, info
.info8
.config_file
, remote_driver_dir
, "unexpected path");
10188 ASSERT_DRIVER_PATH(tctx
, info
.info8
.help_file
, remote_driver_dir
, "unexpected path");
10189 for (i
=0; info
.info8
.dependent_files
&& info
.info8
.dependent_files
[i
] != NULL
; i
++) {
10190 ASSERT_DRIVER_PATH(tctx
, info
.info8
.dependent_files
[i
], remote_driver_dir
, "unexpected path");
10194 torture_assert_nttime_equal(tctx
, info
.info8
.driver_date
, r
->driver_date
, "driverdate mismatch");
10195 torture_assert_u64_equal(tctx
, info
.info8
.driver_version
, r
->driver_version
, "driverversion mismatch");
10200 #undef ASSERT_DRIVER_PATH
10202 static bool test_DeletePrinterDriver_exp(struct torture_context
*tctx
,
10203 struct dcerpc_binding_handle
*b
,
10204 const char *server
,
10205 const char *driver
,
10206 const char *environment
,
10207 WERROR expected_result
)
10209 struct spoolss_DeletePrinterDriver r
;
10211 r
.in
.server
= server
;
10212 r
.in
.architecture
= environment
;
10213 r
.in
.driver
= driver
;
10215 torture_comment(tctx
, "Testing DeletePrinterDriver(%s)\n", driver
);
10217 torture_assert_ntstatus_ok(tctx
,
10218 dcerpc_spoolss_DeletePrinterDriver_r(b
, tctx
, &r
),
10219 "DeletePrinterDriver failed");
10220 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
10221 "DeletePrinterDriver failed with unexpected result");
10226 static bool test_DeletePrinterDriverEx_exp(struct torture_context
*tctx
,
10227 struct dcerpc_binding_handle
*b
,
10228 const char *server
,
10229 const char *driver
,
10230 const char *environment
,
10231 uint32_t delete_flags
,
10233 WERROR expected_result
)
10235 struct spoolss_DeletePrinterDriverEx r
;
10237 r
.in
.server
= server
;
10238 r
.in
.architecture
= environment
;
10239 r
.in
.driver
= driver
;
10240 r
.in
.delete_flags
= delete_flags
;
10241 r
.in
.version
= version
;
10243 torture_comment(tctx
, "Testing DeletePrinterDriverEx(%s)\n", driver
);
10245 torture_assert_ntstatus_ok(tctx
,
10246 dcerpc_spoolss_DeletePrinterDriverEx_r(b
, tctx
, &r
),
10247 "DeletePrinterDriverEx failed");
10248 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
10249 "DeletePrinterDriverEx failed with unexpected result");
10254 static bool test_DeletePrinterDriver(struct torture_context
*tctx
,
10255 struct dcerpc_binding_handle
*b
,
10256 const char *server_name
,
10257 const char *driver
,
10258 const char *environment
)
10260 torture_assert(tctx
,
10261 test_DeletePrinterDriver_exp(tctx
, b
, server_name
, driver
, "FOOBAR", WERR_INVALID_ENVIRONMENT
),
10262 "failed to delete driver");
10264 torture_assert(tctx
,
10265 test_DeletePrinterDriver_exp(tctx
, b
, server_name
, driver
, environment
, WERR_OK
),
10266 "failed to delete driver");
10268 if (test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, environment
, 1, driver
, NULL
)) {
10269 torture_fail(tctx
, "deleted driver still enumerated");
10272 torture_assert(tctx
,
10273 test_DeletePrinterDriver_exp(tctx
, b
, server_name
, driver
, environment
, WERR_UNKNOWN_PRINTER_DRIVER
),
10274 "2nd delete failed");
10279 static bool test_DeletePrinterDriverEx(struct torture_context
*tctx
,
10280 struct dcerpc_binding_handle
*b
,
10281 const char *server_name
,
10282 const char *driver
,
10283 const char *environment
,
10284 uint32_t delete_flags
,
10287 torture_assert(tctx
,
10288 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name
, driver
, "FOOBAR", delete_flags
, version
, WERR_INVALID_ENVIRONMENT
),
10289 "failed to delete driver");
10291 torture_assert(tctx
,
10292 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name
, driver
, environment
, delete_flags
, version
, WERR_OK
),
10293 "failed to delete driver");
10295 if (test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, environment
, 1, driver
, NULL
)) {
10296 torture_fail(tctx
, "deleted driver still enumerated");
10299 torture_assert(tctx
,
10300 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name
, driver
, environment
, delete_flags
, version
, WERR_UNKNOWN_PRINTER_DRIVER
),
10301 "2nd delete failed");
10306 static bool test_PrinterDriver_args(struct torture_context
*tctx
,
10307 struct dcerpc_binding_handle
*b
,
10308 const char *server_name
,
10310 struct spoolss_AddDriverInfo8
*r
,
10311 uint32_t add_flags
,
10312 uint32_t delete_flags
,
10313 uint32_t delete_version
,
10315 const char *remote_driver_dir
)
10321 ret
= test_AddPrinterDriver_args_level_1(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
10324 ret
= test_AddPrinterDriver_args_level_2(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
10327 ret
= test_AddPrinterDriver_args_level_3(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
10330 ret
= test_AddPrinterDriver_args_level_4(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
10333 ret
= test_AddPrinterDriver_args_level_6(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
10336 ret
= test_AddPrinterDriver_args_level_8(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
10342 if (ret
== false) {
10350 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
10352 if (!ex
&& (level
== 6 || level
== 8)) {
10357 struct dcerpc_pipe
*p2
;
10358 struct policy_handle hive_handle
;
10359 struct dcerpc_binding_handle
*b2
;
10361 torture_assert_ntstatus_ok(tctx
,
10362 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
10363 "could not open winreg pipe");
10364 b2
= p2
->binding_handle
;
10366 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
10368 ret
= test_GetDriverInfo_winreg(tctx
, b
, NULL
, NULL
, r
->driver_name
, r
->architecture
, r
->version
, b2
, &hive_handle
, server_name
);
10370 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
10376 return test_DeletePrinterDriverEx(tctx
, b
, server_name
, r
->driver_name
, r
->architecture
, delete_flags
, r
->version
);
10378 return test_DeletePrinterDriver(tctx
, b
, server_name
, r
->driver_name
, r
->architecture
);
10382 static bool fillup_printserver_info(struct torture_context
*tctx
,
10383 struct dcerpc_pipe
*p
,
10384 struct torture_driver_context
*d
)
10386 struct policy_handle server_handle
;
10387 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
10388 const char *server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
10390 torture_assert(tctx
,
10391 test_OpenPrinter_server(tctx
, p
, &server_handle
),
10392 "failed to open printserver");
10393 torture_assert(tctx
,
10394 test_get_environment(tctx
, b
, &server_handle
, &d
->remote
.environment
),
10395 "failed to get environment");
10396 torture_assert(tctx
,
10397 test_ClosePrinter(tctx
, b
, &server_handle
),
10398 "failed to close printserver");
10400 torture_assert(tctx
,
10401 test_GetPrinterDriverDirectory_getdir(tctx
, b
, server_name_slash
,
10402 d
->local
.environment
? d
->local
.environment
: d
->remote
.environment
,
10403 &d
->remote
.driver_directory
),
10404 "failed to get driver directory");
10409 static const char *driver_directory_dir(const char *driver_directory
)
10413 p
= strrchr(driver_directory
, '\\');
10421 static const char *driver_directory_share(struct torture_context
*tctx
,
10422 const char *driver_directory
)
10427 if (driver_directory
[0] == '\\' && driver_directory
[1] == '\\') {
10428 driver_directory
+= 2;
10431 p
= talloc_strdup(tctx
, driver_directory
);
10433 torture_assert(tctx
,
10434 next_token_talloc(tctx
, &p
, &tok
, "\\"),
10435 "cannot explode uri");
10436 torture_assert(tctx
,
10437 next_token_talloc(tctx
, &p
, &tok
, "\\"),
10438 "cannot explode uri");
10443 #define CREATE_PRINTER_DRIVER_PATH(_d, _file) \
10444 talloc_asprintf((_d), "%s\\%s\\%s", (_d)->remote.driver_directory, (_d)->remote.driver_upload_directory, (_file))
10447 static bool create_printer_driver_directory(struct torture_context
*tctx
,
10448 struct smbcli_state
*cli
,
10449 struct torture_driver_context
*d
)
10453 if (d
->remote
.driver_upload_directory
== NULL
) {
10457 driver_dir
= talloc_asprintf(tctx
,
10459 driver_directory_dir(d
->remote
.driver_directory
),
10460 d
->remote
.driver_upload_directory
);
10461 torture_assert_not_null(tctx
, driver_dir
, "ENOMEM");
10463 torture_comment(tctx
,
10464 "Create remote driver directory: %s\n",
10467 torture_assert_ntstatus_ok(tctx
,
10468 smbcli_mkdir(cli
->tree
,
10470 "Failed to create driver directory");
10475 static bool upload_printer_driver_file(struct torture_context
*tctx
,
10476 struct smbcli_state
*cli
,
10477 struct torture_driver_context
*d
,
10478 const char *file_name
)
10483 int maxwrite
= 64512;
10486 const char *remote_dir
= driver_directory_dir(d
->remote
.driver_directory
);
10487 const char *remote_name
;
10488 const char *local_name
;
10491 if (!file_name
|| strlen(file_name
) == 0) {
10495 p
= strrchr(file_name
, '\\');
10502 local_name
= talloc_asprintf(tctx
, "%s/%s", d
->local
.driver_directory
, p
);
10503 torture_assert_not_null(tctx
, local_name
, "ENOMEM");
10504 if (d
->remote
.driver_upload_directory
!= NULL
) {
10505 remote_name
= talloc_asprintf(tctx
,
10508 d
->remote
.driver_upload_directory
,
10511 remote_name
= talloc_asprintf(tctx
, "%s\\%s", remote_dir
, p
);
10513 torture_assert_not_null(tctx
, remote_name
, "ENOMEM");
10515 torture_comment(tctx
, "Uploading %s to %s\n", local_name
, remote_name
);
10517 fnum
= smbcli_open(cli
->tree
, remote_name
, O_RDWR
|O_CREAT
|O_TRUNC
, DENY_NONE
);
10519 torture_fail(tctx
, talloc_asprintf(tctx
, "failed to open remote file: %s\n", remote_name
));
10522 f
= fopen(local_name
, "r");
10524 torture_fail(tctx
, talloc_asprintf(tctx
, "failed to open local file: %s\n", local_name
));
10527 buf
= talloc_array(tctx
, uint8_t, maxwrite
);
10537 if ((n
= fread(buf
, 1, n
, f
)) < 1) {
10538 if((n
== 0) && feof(f
))
10539 break; /* Empty local file. */
10541 torture_warning(tctx
,
10542 "failed to read file: %s\n", strerror(errno
));
10546 ret
= smbcli_write(cli
->tree
, fnum
, 0, buf
, nread
+ start
, n
);
10549 torture_warning(tctx
,
10550 "failed to write file: %s\n", smbcli_errstr(cli
->tree
));
10559 torture_assert_ntstatus_ok(tctx
,
10560 smbcli_close(cli
->tree
, fnum
),
10561 "failed to close file");
10566 static bool connect_printer_driver_share(struct torture_context
*tctx
,
10567 const char *server_name
,
10568 const char *share_name
,
10569 struct smbcli_state
**cli
)
10571 struct smbcli_options smb_options
;
10572 struct smbcli_session_options smb_session_options
;
10574 torture_comment(tctx
, "Connecting printer driver share '%s' on '%s'\n",
10575 share_name
, server_name
);
10577 lpcfg_smbcli_options(tctx
->lp_ctx
, &smb_options
);
10578 lpcfg_smbcli_session_options(tctx
->lp_ctx
, &smb_session_options
);
10580 torture_assert_ntstatus_ok(tctx
,
10581 smbcli_full_connection(tctx
, cli
, server_name
,
10582 lpcfg_smb_ports(tctx
->lp_ctx
),
10584 lpcfg_socket_options(tctx
->lp_ctx
),
10585 popt_get_cmdline_credentials(),
10586 lpcfg_resolve_context(tctx
->lp_ctx
),
10589 &smb_session_options
,
10590 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
)),
10591 "failed to open driver share");
10596 static bool upload_printer_driver(struct torture_context
*tctx
,
10597 const char *server_name
,
10598 struct torture_driver_context
*d
)
10600 struct smbcli_state
*cli
;
10601 const char *share_name
= driver_directory_share(tctx
, d
->remote
.driver_directory
);
10604 torture_assert(tctx
,
10605 connect_printer_driver_share(tctx
, server_name
, share_name
, &cli
),
10606 "failed to connect to driver share");
10608 torture_comment(tctx
, "Uploading printer driver files to \\\\%s\\%s\n",
10609 server_name
, share_name
);
10611 torture_assert(tctx
,
10612 create_printer_driver_directory(tctx
, cli
, d
),
10613 "failed to create driver directory");
10615 torture_assert(tctx
,
10616 upload_printer_driver_file(tctx
, cli
, d
, d
->info8
.driver_path
),
10617 "failed to upload driver_path");
10618 torture_assert(tctx
,
10619 upload_printer_driver_file(tctx
, cli
, d
, d
->info8
.data_file
),
10620 "failed to upload data_file");
10621 torture_assert(tctx
,
10622 upload_printer_driver_file(tctx
, cli
, d
, d
->info8
.config_file
),
10623 "failed to upload config_file");
10624 torture_assert(tctx
,
10625 upload_printer_driver_file(tctx
, cli
, d
, d
->info8
.help_file
),
10626 "failed to upload help_file");
10627 if (d
->info8
.dependent_files
) {
10628 for (i
=0; d
->info8
.dependent_files
->string
&& d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
10629 torture_assert(tctx
,
10630 upload_printer_driver_file(tctx
, cli
, d
, d
->info8
.dependent_files
->string
[i
]),
10631 "failed to upload dependent_files");
10640 static bool check_printer_driver_file(struct torture_context
*tctx
,
10641 struct smbcli_state
*cli
,
10642 struct torture_driver_context
*d
,
10643 const char *file_name
)
10645 const char *remote_arch_dir
= driver_directory_dir(d
->remote
.driver_directory
);
10646 const char *remote_name
= talloc_asprintf(tctx
, "%s\\%d\\%s",
10652 torture_assert(tctx
, (file_name
&& strlen(file_name
) != 0), "invalid filename");
10654 torture_comment(tctx
, "checking for driver file at %s\n", remote_name
);
10656 fnum
= smbcli_open(cli
->tree
, remote_name
, O_RDONLY
, DENY_NONE
);
10661 torture_assert_ntstatus_ok(tctx
,
10662 smbcli_close(cli
->tree
, fnum
),
10663 "failed to close driver file");
10668 static bool check_printer_driver_files(struct torture_context
*tctx
,
10669 const char *server_name
,
10670 struct torture_driver_context
*d
,
10673 struct smbcli_state
*cli
;
10674 const char *share_name
= driver_directory_share(tctx
, d
->remote
.driver_directory
);
10677 torture_assert(tctx
,
10678 connect_printer_driver_share(tctx
, server_name
, share_name
, &cli
),
10679 "failed to connect to driver share");
10681 torture_comment(tctx
, "checking %sexistent driver files at \\\\%s\\%s\n",
10682 (expect_exist
? "": "non-"),
10683 server_name
, share_name
);
10685 if (d
->info8
.driver_path
&& d
->info8
.driver_path
[0]) {
10686 torture_assert(tctx
,
10687 check_printer_driver_file(tctx
, cli
, d
, d
->info8
.driver_path
) == expect_exist
,
10688 "failed driver_path check");
10690 if (d
->info8
.data_file
&& d
->info8
.data_file
[0]) {
10691 torture_assert(tctx
,
10692 check_printer_driver_file(tctx
, cli
, d
, d
->info8
.data_file
) == expect_exist
,
10693 "failed data_file check");
10695 if (d
->info8
.config_file
&& d
->info8
.config_file
[0]) {
10696 torture_assert(tctx
,
10697 check_printer_driver_file(tctx
, cli
, d
, d
->info8
.config_file
) == expect_exist
,
10698 "failed config_file check");
10700 if (d
->info8
.help_file
&& d
->info8
.help_file
[0]) {
10701 torture_assert(tctx
,
10702 check_printer_driver_file(tctx
, cli
, d
, d
->info8
.help_file
) == expect_exist
,
10703 "failed help_file check");
10705 if (d
->info8
.dependent_files
) {
10706 for (i
=0; d
->info8
.dependent_files
->string
&& d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
10707 torture_assert(tctx
,
10708 check_printer_driver_file(tctx
, cli
, d
, d
->info8
.dependent_files
->string
[i
]) == expect_exist
,
10709 "failed dependent_files check");
10718 static bool remove_printer_driver_file(struct torture_context
*tctx
,
10719 struct smbcli_state
*cli
,
10720 struct torture_driver_context
*d
,
10721 const char *file_name
)
10723 const char *remote_name
;
10724 const char *remote_dir
= driver_directory_dir(d
->remote
.driver_directory
);
10726 if (!file_name
|| strlen(file_name
) == 0) {
10730 remote_name
= talloc_asprintf(tctx
, "%s\\%s", remote_dir
, file_name
);
10732 torture_comment(tctx
, "Removing %s\n", remote_name
);
10734 torture_assert_ntstatus_ok(tctx
,
10735 smbcli_unlink(cli
->tree
, remote_name
),
10736 "failed to unlink");
10741 static bool remove_printer_driver(struct torture_context
*tctx
,
10742 const char *server_name
,
10743 struct torture_driver_context
*d
)
10745 struct smbcli_state
*cli
;
10746 const char *share_name
= driver_directory_share(tctx
, d
->remote
.driver_directory
);
10749 torture_assert(tctx
,
10750 connect_printer_driver_share(tctx
, server_name
, share_name
, &cli
),
10751 "failed to connect to driver share");
10753 torture_comment(tctx
, "Removing printer driver files from \\\\%s\\%s\n",
10754 server_name
, share_name
);
10756 torture_assert(tctx
,
10757 remove_printer_driver_file(tctx
, cli
, d
, d
->info8
.driver_path
),
10758 "failed to remove driver_path");
10759 torture_assert(tctx
,
10760 remove_printer_driver_file(tctx
, cli
, d
, d
->info8
.data_file
),
10761 "failed to remove data_file");
10762 if (!strequal(d
->info8
.config_file
, d
->info8
.driver_path
)) {
10763 torture_assert(tctx
,
10764 remove_printer_driver_file(tctx
, cli
, d
, d
->info8
.config_file
),
10765 "failed to remove config_file");
10767 torture_assert(tctx
,
10768 remove_printer_driver_file(tctx
, cli
, d
, d
->info8
.help_file
),
10769 "failed to remove help_file");
10770 if (d
->info8
.dependent_files
) {
10771 for (i
=0; d
->info8
.dependent_files
->string
&& d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
10772 if (strequal(d
->info8
.dependent_files
->string
[i
], d
->info8
.driver_path
) ||
10773 strequal(d
->info8
.dependent_files
->string
[i
], d
->info8
.data_file
) ||
10774 strequal(d
->info8
.dependent_files
->string
[i
], d
->info8
.config_file
) ||
10775 strequal(d
->info8
.dependent_files
->string
[i
], d
->info8
.help_file
)) {
10778 torture_assert(tctx
,
10779 remove_printer_driver_file(tctx
, cli
, d
, d
->info8
.dependent_files
->string
[i
]),
10780 "failed to remove dependent_files");
10790 static bool test_add_driver_arg(struct torture_context
*tctx
,
10791 struct dcerpc_pipe
*p
,
10792 struct torture_driver_context
*d
)
10795 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
10796 const char *server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
10797 uint32_t levels
[] = { 1, 2, 3, 4, 6, 8 };
10799 struct spoolss_AddDriverInfo8 info8
;
10800 uint32_t add_flags
= APD_COPY_NEW_FILES
;
10801 uint32_t delete_flags
= 0;
10803 ZERO_STRUCT(info8
);
10805 torture_comment(tctx
, "Testing PrinterDriver%s '%s' for environment '%s'\n",
10806 d
->ex
? "Ex" : "", d
->info8
.driver_name
, d
->local
.environment
);
10808 torture_assert(tctx
,
10809 fillup_printserver_info(tctx
, p
, d
),
10810 "failed to fillup printserver info");
10812 if (!directory_exist(d
->local
.driver_directory
)) {
10813 torture_skip(tctx
, "Skipping Printer Driver test as no local driver is available");
10816 torture_assert(tctx
,
10817 upload_printer_driver(tctx
, dcerpc_server_name(p
), d
),
10818 "failed to upload printer driver");
10821 if (d
->info8
.dependent_files
) {
10822 info8
.dependent_files
= talloc_zero(tctx
, struct spoolss_StringArray
);
10823 if (d
->info8
.dependent_files
->string
) {
10824 for (i
=0; d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
10826 info8
.dependent_files
->string
= talloc_zero_array(info8
.dependent_files
, const char *, i
+1);
10827 for (i
=0; d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
10828 info8
.dependent_files
->string
[i
] = talloc_strdup(info8
.dependent_files
->string
, d
->info8
.dependent_files
->string
[i
]);
10833 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
10835 if (torture_setting_bool(tctx
, "samba3", false)) {
10836 switch (levels
[i
]) {
10839 torture_comment(tctx
, "skipping level %d against samba\n", levels
[i
]);
10845 if (torture_setting_bool(tctx
, "w2k3", false)) {
10846 switch (levels
[i
]) {
10848 torture_comment(tctx
, "skipping level %d against w2k3\n", levels
[i
]);
10855 torture_comment(tctx
,
10856 "Testing PrinterDriver%s '%s' add & delete level %d\n",
10857 d
->ex
? "Ex" : "", info8
.driver_name
, levels
[i
]);
10859 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
);
10862 info8
.driver_path
= talloc_asprintf(tctx
, "%s\\%s", d
->remote
.driver_directory
, d
->info8
.driver_path
);
10863 info8
.data_file
= talloc_asprintf(tctx
, "%s\\%s", d
->remote
.driver_directory
, d
->info8
.data_file
);
10864 if (d
->info8
.config_file
) {
10865 info8
.config_file
= talloc_asprintf(tctx
, "%s\\%s", d
->remote
.driver_directory
, d
->info8
.config_file
);
10867 if (d
->info8
.help_file
) {
10868 info8
.help_file
= talloc_asprintf(tctx
, "%s\\%s", d
->remote
.driver_directory
, d
->info8
.help_file
);
10870 if (d
->info8
.dependent_files
&& d
->info8
.dependent_files
->string
) {
10871 for (i
=0; d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
10872 info8
.dependent_files
->string
[i
] = talloc_asprintf(tctx
, "%s\\%s", d
->remote
.driver_directory
, d
->info8
.dependent_files
->string
[i
]);
10876 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
10878 if (torture_setting_bool(tctx
, "samba3", false)) {
10879 switch (levels
[i
]) {
10887 if (torture_setting_bool(tctx
, "w2k3", false)) {
10888 switch (levels
[i
]) {
10890 torture_comment(tctx
, "skipping level %d against w2k3\n", levels
[i
]);
10897 torture_comment(tctx
,
10898 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
10899 d
->ex
? "Ex" : "", info8
.driver_name
, levels
[i
]);
10901 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
);
10904 torture_assert(tctx
,
10905 remove_printer_driver(tctx
, dcerpc_server_name(p
), d
),
10906 "failed to remove printer driver");
10908 torture_comment(tctx
, "\n");
10913 static bool test_add_driver_ex_64(struct torture_context
*tctx
,
10914 struct dcerpc_pipe
*p
)
10916 struct torture_driver_context
*d
;
10918 d
= talloc_zero(tctx
, struct torture_driver_context
);
10920 d
->local
.environment
= talloc_strdup(d
, SPOOLSS_ARCHITECTURE_x64
);
10921 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/x64");
10923 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
10924 d
->info8
.driver_name
= TORTURE_DRIVER_EX
;
10925 d
->info8
.architecture
= d
->local
.environment
;
10926 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
10927 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
10928 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
10931 return test_add_driver_arg(tctx
, p
, d
);
10934 static bool test_add_driver_ex_32(struct torture_context
*tctx
,
10935 struct dcerpc_pipe
*p
)
10937 struct torture_driver_context
*d
;
10939 d
= talloc_zero(tctx
, struct torture_driver_context
);
10941 d
->local
.environment
= talloc_strdup(d
, SPOOLSS_ARCHITECTURE_NT_X86
);
10942 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/i386");
10944 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
10945 d
->info8
.driver_name
= TORTURE_DRIVER_EX
;
10946 d
->info8
.architecture
= d
->local
.environment
;
10947 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
10948 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
10949 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
10952 return test_add_driver_arg(tctx
, p
, d
);
10955 static bool test_add_driver_64(struct torture_context
*tctx
,
10956 struct dcerpc_pipe
*p
)
10958 struct torture_driver_context
*d
;
10960 d
= talloc_zero(tctx
, struct torture_driver_context
);
10962 d
->local
.environment
= talloc_strdup(d
, SPOOLSS_ARCHITECTURE_x64
);
10963 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/x64");
10965 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
10966 d
->info8
.driver_name
= TORTURE_DRIVER_ADD
;
10967 d
->info8
.architecture
= d
->local
.environment
;
10968 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
10969 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
10970 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
10973 return test_add_driver_arg(tctx
, p
, d
);
10976 static bool test_add_driver_32(struct torture_context
*tctx
,
10977 struct dcerpc_pipe
*p
)
10979 struct torture_driver_context
*d
;
10981 d
= talloc_zero(tctx
, struct torture_driver_context
);
10983 d
->local
.environment
= talloc_strdup(d
, SPOOLSS_ARCHITECTURE_NT_X86
);
10984 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/i386");
10986 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
10987 d
->info8
.driver_name
= TORTURE_DRIVER_ADD
;
10988 d
->info8
.architecture
= d
->local
.environment
;
10989 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
10990 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
10991 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
10994 return test_add_driver_arg(tctx
, p
, d
);
10997 static bool test_add_driver_adobe(struct torture_context
*tctx
,
10998 struct dcerpc_pipe
*p
)
11000 struct torture_driver_context
*d
;
11002 if (!torture_setting_bool(tctx
, "samba3", false)) {
11003 torture_skip(tctx
, "skipping adobe test which only works against samba3");
11006 d
= talloc_zero(tctx
, struct torture_driver_context
);
11008 d
->local
.environment
= talloc_strdup(d
, "Windows 4.0");
11009 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/adobe/");
11011 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_9X
;
11012 d
->info8
.driver_name
= TORTURE_DRIVER_ADOBE
;
11013 d
->info8
.architecture
= d
->local
.environment
;
11014 d
->info8
.driver_path
= talloc_strdup(d
, "ADOBEPS4.DRV");
11015 d
->info8
.data_file
= talloc_strdup(d
, "DEFPRTR2.PPD");
11016 d
->info8
.config_file
= talloc_strdup(d
, "ADOBEPS4.DRV");
11018 d
->info8
.help_file
= talloc_strdup(d
, "ADOBEPS4.HLP");
11019 d
->info8
.monitor_name
= talloc_strdup(d
, "PSMON.DLL");
11023 return test_add_driver_arg(tctx
, p
, d
);
11026 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context
*tctx
,
11027 struct dcerpc_pipe
*p
)
11029 struct torture_driver_context
*d
;
11030 struct spoolss_StringArray
*a
;
11032 if (!torture_setting_bool(tctx
, "samba3", false)) {
11033 torture_skip(tctx
, "skipping cupsaddsmb test which only works against samba3");
11036 d
= talloc_zero(tctx
, struct torture_driver_context
);
11038 d
->local
.environment
= talloc_strdup(d
, "Windows 4.0");
11039 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/adobe/");
11041 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_9X
;
11042 d
->info8
.driver_name
= TORTURE_DRIVER_ADOBE_CUPSADDSMB
;
11043 d
->info8
.architecture
= d
->local
.environment
;
11044 d
->info8
.driver_path
= talloc_strdup(d
, "ADOBEPS4.DRV");
11045 d
->info8
.data_file
= talloc_strdup(d
, "DEFPRTR2.PPD");
11046 d
->info8
.config_file
= NULL
;
11047 d
->info8
.help_file
= talloc_strdup(d
, "ADOBEPS4.HLP");
11048 d
->info8
.monitor_name
= talloc_strdup(d
, "PSMON.DLL");
11049 d
->info8
.default_datatype
= talloc_strdup(d
, "RAW");
11051 a
= talloc_zero(d
, struct spoolss_StringArray
);
11052 a
->string
= talloc_zero_array(a
, const char *, 7);
11053 a
->string
[0] = talloc_strdup(a
->string
, "ADOBEPS4.DRV");
11054 a
->string
[1] = talloc_strdup(a
->string
, "DEFPRTR2.PPD");
11055 a
->string
[2] = talloc_strdup(a
->string
, "ADOBEPS4.HLP");
11056 a
->string
[3] = talloc_strdup(a
->string
, "PSMON.DLL");
11057 a
->string
[4] = talloc_strdup(a
->string
, "ADFONTS.MFM");
11058 a
->string
[5] = talloc_strdup(a
->string
, "ICONLIB.DLL");
11060 d
->info8
.dependent_files
= a
;
11063 return test_add_driver_arg(tctx
, p
, d
);
11066 static bool test_add_driver_timestamps(struct torture_context
*tctx
,
11067 struct dcerpc_pipe
*p
)
11069 struct torture_driver_context
*d
;
11070 struct timeval t
= timeval_current();
11072 d
= talloc_zero(tctx
, struct torture_driver_context
);
11074 d
->local
.environment
= talloc_strdup(d
, SPOOLSS_ARCHITECTURE_NT_X86
);
11075 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/i386");
11077 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
11078 d
->info8
.driver_name
= TORTURE_DRIVER_TIMESTAMPS
;
11079 d
->info8
.architecture
= d
->local
.environment
;
11080 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
11081 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
11082 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
11083 d
->info8
.driver_date
= timeval_to_nttime(&t
);
11086 torture_assert(tctx
,
11087 test_add_driver_arg(tctx
, p
, d
),
11090 unix_to_nt_time(&d
->info8
.driver_date
, 1);
11092 torture_assert(tctx
,
11093 test_add_driver_arg(tctx
, p
, d
),
11099 static bool test_multiple_drivers(struct torture_context
*tctx
,
11100 struct dcerpc_pipe
*p
)
11102 struct torture_driver_context
*d
;
11103 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
11104 const char *server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
11106 struct spoolss_AddDriverInfo8 info8
;
11107 uint32_t add_flags
= APD_COPY_NEW_FILES
;
11108 uint32_t delete_flags
= 0;
11110 d
= talloc_zero(tctx
, struct torture_driver_context
);
11112 d
->local
.environment
= talloc_strdup(d
, SPOOLSS_ARCHITECTURE_NT_X86
);
11113 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/i386");
11115 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
11116 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
11117 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
11118 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
11119 d
->info8
.architecture
= d
->local
.environment
;
11122 torture_assert(tctx
,
11123 fillup_printserver_info(tctx
, p
, d
),
11124 "failed to fillup printserver info");
11126 if (!directory_exist(d
->local
.driver_directory
)) {
11127 torture_skip(tctx
, "Skipping Printer Driver test as no local driver is available");
11130 torture_assert(tctx
,
11131 upload_printer_driver(tctx
, dcerpc_server_name(p
), d
),
11132 "failed to upload printer driver");
11136 for (i
=0; i
< 3; i
++) {
11137 info8
.driver_name
= talloc_asprintf(d
, "torture_test_driver_%d", i
);
11139 torture_assert(tctx
,
11140 test_AddPrinterDriver_args_level_3(tctx
, b
, server_name_slash
, &info8
, add_flags
, true, NULL
),
11141 "failed to add driver");
11144 torture_assert(tctx
,
11145 test_DeletePrinterDriverEx(tctx
, b
, server_name_slash
, "torture_test_driver_0", info8
.architecture
, delete_flags
, info8
.version
),
11146 "failed to delete driver");
11148 torture_assert(tctx
,
11149 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, info8
.architecture
, 3, "torture_test_driver_1", NULL
),
11150 "torture_test_driver_1 no longer on the server");
11152 torture_assert(tctx
,
11153 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, info8
.architecture
, 3, "torture_test_driver_2", NULL
),
11154 "torture_test_driver_2 no longer on the server");
11156 torture_assert(tctx
,
11157 test_DeletePrinterDriverEx(tctx
, b
, server_name_slash
, "torture_test_driver_1", info8
.architecture
, delete_flags
, info8
.version
),
11158 "failed to delete driver");
11160 torture_assert(tctx
,
11161 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, info8
.architecture
, 3, "torture_test_driver_2", NULL
),
11162 "torture_test_driver_2 no longer on the server");
11164 torture_assert(tctx
,
11165 test_DeletePrinterDriverEx(tctx
, b
, server_name_slash
, "torture_test_driver_2", info8
.architecture
, delete_flags
, info8
.version
),
11166 "failed to delete driver");
11168 torture_assert(tctx
,
11169 remove_printer_driver(tctx
, dcerpc_server_name(p
), d
),
11170 "failed to remove printer driver");
11175 static bool test_driver_copy_from_directory(struct torture_context
*tctx
,
11176 struct dcerpc_pipe
*p
,
11177 const char *architecture
)
11179 struct torture_driver_context
*d
;
11180 struct spoolss_StringArray
*a
;
11181 uint32_t add_flags
= APD_COPY_NEW_FILES
|APD_COPY_FROM_DIRECTORY
|APD_RETURN_BLOCKING_STATUS_CODE
;
11182 uint32_t delete_flags
= DPD_DELETE_ALL_FILES
;
11183 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
11184 const char *server_name_slash
= talloc_asprintf(tctx
,
11186 dcerpc_server_name(p
));
11187 struct GUID guid
= GUID_random();
11190 d
= talloc_zero(tctx
, struct torture_driver_context
);
11191 torture_assert_not_null(tctx
, d
, "ENOMEM");
11193 d
->local
.environment
= talloc_strdup(d
, architecture
);
11194 torture_assert_not_null_goto(tctx
, d
->local
.environment
, ok
, done
, "ENOMEM");
11196 if (strequal(architecture
, SPOOLSS_ARCHITECTURE_x64
)) {
11197 d
->local
.driver_directory
=
11198 talloc_strdup(d
, "/usr/share/cups/drivers/x64");
11200 d
->local
.driver_directory
=
11201 talloc_strdup(d
, "/usr/share/cups/drivers/i386");
11203 torture_assert_not_null_goto(tctx
, d
->local
.driver_directory
, ok
, done
, "ENOMEM");
11205 d
->remote
.driver_upload_directory
= GUID_string2(d
, &guid
);
11206 torture_assert_not_null_goto(tctx
, d
->remote
.driver_upload_directory
, ok
, done
, "ENOMEM");
11208 torture_assert(tctx
,
11209 fillup_printserver_info(tctx
, p
, d
),
11210 "failed to fillup printserver info");
11213 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
11214 d
->info8
.driver_name
= TORTURE_DRIVER_COPY_DIR
;
11215 d
->info8
.architecture
= d
->local
.environment
;
11217 d
->info8
.driver_path
= CREATE_PRINTER_DRIVER_PATH(d
, "pscript5.dll");
11218 torture_assert_not_null_goto(tctx
, d
->info8
.driver_path
, ok
, done
, "ENOMEM");
11219 d
->info8
.data_file
= CREATE_PRINTER_DRIVER_PATH(d
, "cups6.ppd");
11220 torture_assert_not_null_goto(tctx
, d
->info8
.data_file
, ok
, done
, "ENOMEM");
11221 d
->info8
.config_file
= CREATE_PRINTER_DRIVER_PATH(d
, "cupsui6.dll");
11222 torture_assert_not_null_goto(tctx
, d
->info8
.config_file
, ok
, done
, "ENOMEM");
11223 d
->info8
.help_file
= CREATE_PRINTER_DRIVER_PATH(d
, "pscript.hlp");
11224 torture_assert_not_null_goto(tctx
, d
->info8
.help_file
, ok
, done
, "ENOMEM");
11226 a
= talloc_zero(d
, struct spoolss_StringArray
);
11227 torture_assert_not_null_goto(tctx
, a
, ok
, done
, "ENOMEM");
11228 a
->string
= talloc_zero_array(a
, const char *, 3);
11229 torture_assert_not_null_goto(tctx
, a
->string
, ok
, done
, "ENOMEM");
11230 a
->string
[0] = CREATE_PRINTER_DRIVER_PATH(d
, "cups6.inf");
11231 torture_assert_not_null_goto(tctx
, a
->string
[0], ok
, done
, "ENOMEM");
11232 a
->string
[1] = CREATE_PRINTER_DRIVER_PATH(d
, "cups6.ini");
11233 torture_assert_not_null_goto(tctx
, a
->string
[1], ok
, done
, "ENOMEM");
11235 d
->info8
.dependent_files
= a
;
11237 if (!directory_exist(d
->local
.driver_directory
)) {
11239 "Skipping Printer Driver test as no local drivers "
11243 torture_assert(tctx
,
11244 upload_printer_driver(tctx
, dcerpc_server_name(p
), d
),
11245 "failed to upload printer driver");
11247 torture_assert(tctx
,
11248 test_AddPrinterDriver_args_level_3(tctx
,
11255 "failed to add driver");
11257 torture_assert(tctx
,
11258 test_DeletePrinterDriverEx(tctx
,
11261 d
->info8
.driver_name
,
11262 d
->local
.environment
,
11265 "failed to delete driver");
11267 torture_assert(tctx
,
11268 check_printer_driver_files(tctx
,
11269 dcerpc_server_name(p
),
11272 "printer driver file check failed");
11280 static bool test_driver_copy_from_directory_64(struct torture_context
*tctx
,
11281 struct dcerpc_pipe
*p
)
11283 return test_driver_copy_from_directory(tctx
, p
, SPOOLSS_ARCHITECTURE_x64
);
11286 static bool test_driver_copy_from_directory_32(struct torture_context
*tctx
,
11287 struct dcerpc_pipe
*p
)
11289 return test_driver_copy_from_directory(tctx
, p
, SPOOLSS_ARCHITECTURE_NT_X86
);
11292 static bool test_del_driver_all_files(struct torture_context
*tctx
,
11293 struct dcerpc_pipe
*p
)
11295 struct torture_driver_context
*d
;
11296 struct spoolss_StringArray
*a
;
11297 uint32_t add_flags
= APD_COPY_NEW_FILES
;
11298 uint32_t delete_flags
= DPD_DELETE_ALL_FILES
;
11299 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
11300 const char *server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
11302 d
= talloc_zero(tctx
, struct torture_driver_context
);
11304 d
->local
.environment
= talloc_strdup(d
, SPOOLSS_ARCHITECTURE_x64
);
11305 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/x64");
11308 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
11309 d
->info8
.driver_name
= TORTURE_DRIVER_DELETER
;
11310 d
->info8
.architecture
= d
->local
.environment
;
11311 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
11312 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
11313 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
11314 d
->info8
.help_file
= talloc_strdup(d
, "pscript.hlp");
11316 a
= talloc_zero(d
, struct spoolss_StringArray
);
11317 a
->string
= talloc_zero_array(a
, const char *, 3);
11318 a
->string
[0] = talloc_strdup(a
->string
, "cups6.inf");
11319 a
->string
[1] = talloc_strdup(a
->string
, "cups6.ini");
11321 d
->info8
.dependent_files
= a
;
11323 torture_assert(tctx
,
11324 fillup_printserver_info(tctx
, p
, d
),
11325 "failed to fillup printserver info");
11327 if (!directory_exist(d
->local
.driver_directory
)) {
11328 torture_skip(tctx
, "Skipping Printer Driver test as no local driver is available");
11331 torture_assert(tctx
,
11332 upload_printer_driver(tctx
, dcerpc_server_name(p
), d
),
11333 "failed to upload printer driver");
11335 torture_assert(tctx
,
11336 test_AddPrinterDriver_args_level_3(tctx
, b
, server_name_slash
, &d
->info8
, add_flags
, true, NULL
),
11337 "failed to add driver");
11339 torture_assert(tctx
,
11340 test_DeletePrinterDriverEx(tctx
, b
, server_name_slash
,
11341 d
->info8
.driver_name
,
11342 d
->info8
.architecture
,
11345 "failed to delete driver");
11347 torture_assert(tctx
,
11348 check_printer_driver_files(tctx
, dcerpc_server_name(p
), d
, false),
11349 "printer driver file check failed");
11355 static bool test_del_driver_unused_files(struct torture_context
*tctx
,
11356 struct dcerpc_pipe
*p
)
11358 struct torture_driver_context
*d1
;
11359 struct torture_driver_context
*d2
;
11360 uint32_t add_flags
= APD_COPY_NEW_FILES
;
11361 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
11362 const char *server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
11364 d1
= talloc_zero(tctx
, struct torture_driver_context
);
11367 d1
->local
.environment
= talloc_strdup(d1
, SPOOLSS_ARCHITECTURE_x64
);
11368 d1
->local
.driver_directory
= talloc_strdup(d1
, "/usr/share/cups/drivers/x64");
11370 d1
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
11371 d1
->info8
.driver_name
= TORTURE_DRIVER_DELETER
;
11372 d1
->info8
.architecture
= NULL
;
11373 d1
->info8
.driver_path
= talloc_strdup(d1
, "pscript5.dll");
11374 d1
->info8
.data_file
= talloc_strdup(d1
, "cups6.ppd");
11375 d1
->info8
.config_file
= talloc_strdup(d1
, "cupsui6.dll");
11376 d1
->info8
.help_file
= talloc_strdup(d1
, "pscript.hlp");
11377 d1
->info8
.architecture
= d1
->local
.environment
;
11379 d2
= talloc_zero(tctx
, struct torture_driver_context
);
11382 d2
->local
.environment
= talloc_strdup(d2
, SPOOLSS_ARCHITECTURE_x64
);
11383 d2
->local
.driver_directory
= talloc_strdup(d2
, "/usr/share/cups/drivers/x64");
11385 d2
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
11386 d2
->info8
.driver_name
= TORTURE_DRIVER_DELETERIN
;
11387 d2
->info8
.architecture
= NULL
;
11388 d2
->info8
.driver_path
= talloc_strdup(d2
, "pscript5.dll"); /* overlapping */
11389 d2
->info8
.data_file
= talloc_strdup(d2
, "cupsps6.dll");
11390 d2
->info8
.config_file
= talloc_strdup(d2
, "cups6.ini");
11391 d2
->info8
.help_file
= talloc_strdup(d2
, "pscript.hlp"); /* overlapping */
11392 d2
->info8
.architecture
= d2
->local
.environment
;
11394 torture_assert(tctx
,
11395 fillup_printserver_info(tctx
, p
, d1
),
11396 "failed to fillup printserver info");
11397 torture_assert(tctx
,
11398 fillup_printserver_info(tctx
, p
, d2
),
11399 "failed to fillup printserver info");
11401 if (!directory_exist(d1
->local
.driver_directory
)) {
11402 torture_skip(tctx
, "Skipping Printer Driver test as no local driver is available");
11405 torture_assert(tctx
,
11406 upload_printer_driver(tctx
, dcerpc_server_name(p
), d1
),
11407 "failed to upload printer driver");
11408 torture_assert(tctx
,
11409 test_AddPrinterDriver_args_level_3(tctx
, b
, server_name_slash
, &d1
->info8
, add_flags
, true, NULL
),
11410 "failed to add driver");
11412 torture_assert(tctx
,
11413 upload_printer_driver(tctx
, dcerpc_server_name(p
), d2
),
11414 "failed to upload printer driver");
11415 torture_assert(tctx
,
11416 test_AddPrinterDriver_args_level_3(tctx
, b
, server_name_slash
, &d2
->info8
, add_flags
, true, NULL
),
11417 "failed to add driver");
11419 /* some files are in use by a separate driver, should fail */
11420 torture_assert(tctx
,
11421 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name_slash
,
11422 d1
->info8
.driver_name
,
11423 d1
->info8
.architecture
,
11424 DPD_DELETE_ALL_FILES
,
11426 WERR_PRINTER_DRIVER_IN_USE
),
11427 "invalid delete driver response");
11429 /* should only delete files not in use by other driver */
11430 torture_assert(tctx
,
11431 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name_slash
,
11432 d1
->info8
.driver_name
,
11433 d1
->info8
.architecture
,
11434 DPD_DELETE_UNUSED_FILES
,
11437 "failed to delete driver (unused files)");
11439 /* check non-overlapping were deleted */
11440 d1
->info8
.driver_path
= NULL
;
11441 d1
->info8
.help_file
= NULL
;
11442 torture_assert(tctx
,
11443 check_printer_driver_files(tctx
, dcerpc_server_name(p
), d1
, false),
11444 "printer driver file check failed");
11445 /* d2 files should be uneffected */
11446 torture_assert(tctx
,
11447 check_printer_driver_files(tctx
, dcerpc_server_name(p
), d2
, true),
11448 "printer driver file check failed");
11450 torture_assert(tctx
,
11451 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name_slash
,
11452 d2
->info8
.driver_name
,
11453 d2
->info8
.architecture
,
11454 DPD_DELETE_ALL_FILES
,
11457 "failed to delete driver");
11459 torture_assert(tctx
,
11460 check_printer_driver_files(tctx
, dcerpc_server_name(p
), d2
, false),
11461 "printer driver file check failed");
11468 struct torture_suite
*torture_rpc_spoolss_driver(TALLOC_CTX
*mem_ctx
)
11470 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "spoolss.driver");
11472 struct torture_rpc_tcase
*tcase
= torture_suite_add_rpc_iface_tcase(suite
,
11473 "driver", &ndr_table_spoolss
);
11474 torture_rpc_tcase_add_test(tcase
, "add_driver_64", test_add_driver_64
);
11475 torture_rpc_tcase_add_test(tcase
, "add_driver_ex_64", test_add_driver_ex_64
);
11477 torture_rpc_tcase_add_test(tcase
, "add_driver_32", test_add_driver_32
);
11478 torture_rpc_tcase_add_test(tcase
, "add_driver_ex_32", test_add_driver_ex_32
);
11480 torture_rpc_tcase_add_test(tcase
, "add_driver_adobe", test_add_driver_adobe
);
11482 torture_rpc_tcase_add_test(tcase
, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb
);
11484 torture_rpc_tcase_add_test(tcase
, "add_driver_timestamps", test_add_driver_timestamps
);
11486 torture_rpc_tcase_add_test(tcase
, "multiple_drivers", test_multiple_drivers
);
11488 torture_rpc_tcase_add_test(tcase
,
11489 "test_driver_copy_from_directory_64",
11490 test_driver_copy_from_directory_64
);
11492 torture_rpc_tcase_add_test(tcase
,
11493 "test_driver_copy_from_directory_32",
11494 test_driver_copy_from_directory_32
);
11496 torture_rpc_tcase_add_test(tcase
, "del_driver_all_files", test_del_driver_all_files
);
11498 torture_rpc_tcase_add_test(tcase
, "del_driver_unused_files", test_del_driver_unused_files
);