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_EX "torture_driver_ex"
51 #define TORTURE_DRIVER_ADOBE "torture_driver_adobe"
52 #define TORTURE_DRIVER_EX_ADOBE "torture_driver_ex_adobe"
53 #define TORTURE_DRIVER_ADOBE_CUPSADDSMB "torture_driver_adobe_cupsaddsmb"
54 #define TORTURE_DRIVER_TIMESTAMPS "torture_driver_timestamps"
55 #define TORTURE_DRIVER_DELETER "torture_driver_deleter"
56 #define TORTURE_DRIVER_DELETERIN "torture_driver_deleterin"
57 #define TORTURE_PRINTER_STATIC1 "print1"
59 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
60 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
61 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
62 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
63 #define TOP_LEVEL_CONTROL_PRINTERS_KEY TOP_LEVEL_CONTROL_KEY "\\Printers"
64 #define TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY TOP_LEVEL_CONTROL_KEY "\\Environments"
66 struct test_spoolss_context
{
67 struct dcerpc_pipe
*spoolss_pipe
;
69 /* server environment */
70 const char *environment
;
72 /* print server handle */
73 struct policy_handle server_handle
;
76 uint32_t port_count
[3];
77 union spoolss_PortInfo
*ports
[3];
79 /* for EnumPrinterDrivers */
80 uint32_t driver_count
[9];
81 union spoolss_DriverInfo
*drivers
[9];
83 /* for EnumMonitors */
84 uint32_t monitor_count
[3];
85 union spoolss_MonitorInfo
*monitors
[3];
87 /* for EnumPrintProcessors */
88 uint32_t print_processor_count
[2];
89 union spoolss_PrintProcessorInfo
*print_processors
[2];
91 /* for EnumPrinters */
92 uint32_t printer_count
[6];
93 union spoolss_PrinterInfo
*printers
[6];
96 struct torture_driver_context
{
98 const char *driver_directory
;
99 const char *environment
;
102 const char *driver_directory
;
103 const char *environment
;
105 struct spoolss_AddDriverInfo8 info8
;
109 struct torture_printer_context
{
110 struct dcerpc_pipe
*spoolss_pipe
;
111 struct spoolss_SetPrinterInfo2 info2
;
112 struct torture_driver_context driver
;
117 struct spoolss_DeviceMode
*devmode
;
118 struct policy_handle handle
;
121 static bool upload_printer_driver(struct torture_context
*tctx
,
122 const char *server_name
,
123 struct torture_driver_context
*d
);
124 static bool remove_printer_driver(struct torture_context
*tctx
,
125 const char *server_name
,
126 struct torture_driver_context
*d
);
127 static bool fillup_printserver_info(struct torture_context
*tctx
,
128 struct dcerpc_pipe
*p
,
129 struct torture_driver_context
*d
);
130 static bool test_AddPrinterDriver_args_level_3(struct torture_context
*tctx
,
131 struct dcerpc_binding_handle
*b
,
132 const char *server_name
,
133 struct spoolss_AddDriverInfo8
*r
,
136 const char *remote_driver_dir
);
138 #define COMPARE_STRING(tctx, c,r,e) \
139 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
141 /* not every compiler supports __typeof__() */
143 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
144 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
145 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
147 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
148 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
152 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
155 #define COMPARE_UINT32(tctx, c, r, e) do {\
156 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
157 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
160 #define COMPARE_UINT64(tctx, c, r, e) do {\
161 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
162 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
166 #define COMPARE_NTTIME(tctx, c, r, e) do {\
167 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
168 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
171 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
173 if (!c.e && !r.e) { \
177 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
180 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
182 for (__i=0;c.e[__i] != NULL; __i++) { \
183 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
187 #define CHECK_ALIGN(size, n) do {\
189 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
190 size, n, size + n - (size % n));\
194 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
196 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, needed, align) do { \
197 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
198 uint32_t size = ndr_size_##fn##_info(tctx, level, count, info);\
199 uint32_t round_size = DO_ROUND(size, align);\
200 if (round_size != needed) {\
201 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
202 CHECK_ALIGN(size, align);\
207 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, needed, align) do { \
208 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
209 uint32_t size = ndr_size_##fn##_info(tctx, count, info);\
210 uint32_t round_size = DO_ROUND(size, align);\
211 if (round_size != needed) {\
212 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
213 CHECK_ALIGN(size, align);\
218 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, needed, align) do { \
219 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
220 uint32_t size = ndr_size_##fn(info, level, 0);\
221 uint32_t round_size = DO_ROUND(size, align);\
222 if (round_size != needed) {\
223 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
224 CHECK_ALIGN(size, align);\
229 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context
*tctx
,
230 const union spoolss_PrinterInfo
*i
,
232 union spoolss_SetPrinterInfo
*s
)
236 s
->info0
= talloc(tctx
, struct spoolss_SetPrinterInfo0
);
239 s
->info2
= talloc(tctx
, struct spoolss_SetPrinterInfo2
);
240 s
->info2
->servername
= i
->info2
.servername
;
241 s
->info2
->printername
= i
->info2
.printername
;
242 s
->info2
->sharename
= i
->info2
.sharename
;
243 s
->info2
->portname
= i
->info2
.portname
;
244 s
->info2
->drivername
= i
->info2
.drivername
;
245 s
->info2
->comment
= i
->info2
.comment
;
246 s
->info2
->location
= i
->info2
.location
;
247 s
->info2
->devmode_ptr
= NULL
;
248 s
->info2
->sepfile
= i
->info2
.sepfile
;
249 s
->info2
->printprocessor
= i
->info2
.printprocessor
;
250 s
->info2
->datatype
= i
->info2
.datatype
;
251 s
->info2
->parameters
= i
->info2
.parameters
;
252 s
->info2
->secdesc_ptr
= NULL
;
253 s
->info2
->attributes
= i
->info2
.attributes
;
254 s
->info2
->priority
= i
->info2
.priority
;
255 s
->info2
->defaultpriority
= i
->info2
.defaultpriority
;
256 s
->info2
->starttime
= i
->info2
.starttime
;
257 s
->info2
->untiltime
= i
->info2
.untiltime
;
258 s
->info2
->status
= i
->info2
.status
;
259 s
->info2
->cjobs
= i
->info2
.cjobs
;
260 s
->info2
->averageppm
= i
->info2
.averageppm
;
276 static bool test_OpenPrinter_server(struct torture_context
*tctx
,
277 struct dcerpc_pipe
*p
,
278 struct policy_handle
*server_handle
)
281 struct spoolss_OpenPrinter op
;
282 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
284 op
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
285 op
.in
.datatype
= NULL
;
286 op
.in
.devmode_ctr
.devmode
= NULL
;
287 op
.in
.access_mask
= 0;
288 op
.out
.handle
= server_handle
;
290 torture_comment(tctx
, "Testing OpenPrinter(%s)\n", op
.in
.printername
);
292 status
= dcerpc_spoolss_OpenPrinter_r(b
, tctx
, &op
);
293 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_OpenPrinter failed");
294 torture_assert_werr_ok(tctx
, op
.out
.result
, "dcerpc_spoolss_OpenPrinter failed");
299 static bool test_EnumPorts(struct torture_context
*tctx
,
302 struct test_spoolss_context
*ctx
=
303 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
304 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
305 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
307 struct spoolss_EnumPorts r
;
308 uint16_t levels
[] = { 1, 2 };
311 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
312 int level
= levels
[i
];
316 union spoolss_PortInfo
*info
;
318 r
.in
.servername
= "";
322 r
.out
.needed
= &needed
;
323 r
.out
.count
= &count
;
326 torture_comment(tctx
, "Testing EnumPorts level %u\n", r
.in
.level
);
328 status
= dcerpc_spoolss_EnumPorts_r(b
, ctx
, &r
);
329 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPorts failed");
330 if (W_ERROR_IS_OK(r
.out
.result
)) {
331 /* TODO: do some more checks here */
334 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
335 "EnumPorts unexpected return code");
337 blob
= data_blob_talloc_zero(ctx
, needed
);
339 r
.in
.offered
= needed
;
341 status
= dcerpc_spoolss_EnumPorts_r(b
, ctx
, &r
);
342 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPorts failed");
344 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
346 torture_assert(tctx
, info
, "EnumPorts returned no info");
348 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts
, info
, r
.in
.level
, count
, needed
, 4);
350 ctx
->port_count
[level
] = count
;
351 ctx
->ports
[level
] = info
;
354 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
355 int level
= levels
[i
];
356 int old_level
= levels
[i
-1];
357 torture_assert_int_equal(tctx
, ctx
->port_count
[level
], ctx
->port_count
[old_level
],
358 "EnumPorts invalid value");
360 /* if the array sizes are not the same we would maybe segfault in the following code */
362 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
363 int level
= levels
[i
];
364 for (j
=0;j
<ctx
->port_count
[level
];j
++) {
365 union spoolss_PortInfo
*cur
= &ctx
->ports
[level
][j
];
366 union spoolss_PortInfo
*ref
= &ctx
->ports
[2][j
];
369 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, port_name
);
372 /* level 2 is our reference, and it makes no sense to compare it to itself */
381 static bool test_GetPrintProcessorDirectory(struct torture_context
*tctx
,
384 struct test_spoolss_context
*ctx
=
385 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
388 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
389 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
390 struct spoolss_GetPrintProcessorDirectory r
;
405 .server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
))
408 .server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
))
414 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
415 int level
= levels
[i
].level
;
418 r
.in
.server
= levels
[i
].server
;
419 r
.in
.environment
= ctx
->environment
;
423 r
.out
.needed
= &needed
;
425 torture_comment(tctx
, "Testing GetPrintProcessorDirectory level %u\n", r
.in
.level
);
427 status
= dcerpc_spoolss_GetPrintProcessorDirectory_r(b
, tctx
, &r
);
428 torture_assert_ntstatus_ok(tctx
, status
,
429 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
430 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
431 "GetPrintProcessorDirectory unexpected return code");
433 blob
= data_blob_talloc_zero(tctx
, needed
);
435 r
.in
.offered
= needed
;
437 status
= dcerpc_spoolss_GetPrintProcessorDirectory_r(b
, tctx
, &r
);
438 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
440 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrintProcessorDirectory failed");
442 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo
, r
.out
.info
, r
.in
.level
, needed
, 2);
449 static bool test_GetPrinterDriverDirectory(struct torture_context
*tctx
,
452 struct test_spoolss_context
*ctx
=
453 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
456 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
457 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
458 struct spoolss_GetPrinterDriverDirectory r
;
473 .server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
))
476 .server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
))
482 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
483 int level
= levels
[i
].level
;
486 r
.in
.server
= levels
[i
].server
;
487 r
.in
.environment
= ctx
->environment
;
491 r
.out
.needed
= &needed
;
493 torture_comment(tctx
, "Testing GetPrinterDriverDirectory level %u\n", r
.in
.level
);
495 status
= dcerpc_spoolss_GetPrinterDriverDirectory_r(b
, tctx
, &r
);
496 torture_assert_ntstatus_ok(tctx
, status
,
497 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
498 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
499 "GetPrinterDriverDirectory unexpected return code");
501 blob
= data_blob_talloc_zero(tctx
, needed
);
503 r
.in
.offered
= needed
;
505 status
= dcerpc_spoolss_GetPrinterDriverDirectory_r(b
, tctx
, &r
);
506 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
508 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrinterDriverDirectory failed");
510 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo
, r
.out
.info
, r
.in
.level
, needed
, 2);
516 static bool test_EnumPrinterDrivers_buffers(struct torture_context
*tctx
,
517 struct dcerpc_binding_handle
*b
,
518 const char *server_name
,
519 const char *environment
,
523 union spoolss_DriverInfo
**info_p
)
525 struct spoolss_EnumPrinterDrivers r
;
528 union spoolss_DriverInfo
*info
;
532 buffer
= data_blob_talloc_zero(tctx
, offered
);
535 r
.in
.server
= server_name
;
536 r
.in
.environment
= environment
;
538 r
.in
.buffer
= offered
? &buffer
: NULL
;
539 r
.in
.offered
= offered
;
540 r
.out
.needed
= &needed
;
541 r
.out
.count
= &count
;
544 torture_comment(tctx
, "Testing EnumPrinterDrivers(%s) level %u, offered: %u\n",
545 r
.in
.environment
, r
.in
.level
, r
.in
.offered
);
547 torture_assert_ntstatus_ok(tctx
,
548 dcerpc_spoolss_EnumPrinterDrivers_r(b
, tctx
, &r
),
549 "EnumPrinterDrivers failed");
550 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
551 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
553 r
.in
.offered
= needed
;
555 torture_assert_ntstatus_ok(tctx
,
556 dcerpc_spoolss_EnumPrinterDrivers_r(b
, tctx
, &r
),
557 "EnumPrinterDrivers failed");
560 torture_assert_werr_ok(tctx
, r
.out
.result
,
561 "EnumPrinterDrivers failed");
570 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers
, info
, r
.in
.level
, count
, needed
, 4);
577 static bool test_EnumPrinterDrivers_args(struct torture_context
*tctx
,
578 struct dcerpc_binding_handle
*b
,
579 const char *server_name
,
580 const char *environment
,
583 union spoolss_DriverInfo
**info_p
)
585 return test_EnumPrinterDrivers_buffers(tctx
, b
, server_name
,
586 environment
, level
, 0,
590 static bool test_EnumPrinterDrivers_findone(struct torture_context
*tctx
,
591 struct dcerpc_binding_handle
*b
,
592 const char *server_name
,
593 const char *environment
,
595 const char *driver_name
,
596 union spoolss_DriverInfo
*info_p
)
599 union spoolss_DriverInfo
*info
;
601 const char *environment_ret
= NULL
;
604 test_EnumPrinterDrivers_args(tctx
, b
, server_name
, environment
, level
, &count
, &info
),
605 "failed to enumerate printer drivers");
607 for (i
=0; i
< count
; i
++) {
608 const char *driver_name_ret
= "";
611 driver_name_ret
= info
[i
].info1
.driver_name
;
614 driver_name_ret
= info
[i
].info2
.driver_name
;
615 environment_ret
= info
[i
].info2
.architecture
;
618 driver_name_ret
= info
[i
].info3
.driver_name
;
619 environment_ret
= info
[i
].info3
.architecture
;
622 driver_name_ret
= info
[i
].info4
.driver_name
;
623 environment_ret
= info
[i
].info4
.architecture
;
626 driver_name_ret
= info
[i
].info5
.driver_name
;
627 environment_ret
= info
[i
].info5
.architecture
;
630 driver_name_ret
= info
[i
].info6
.driver_name
;
631 environment_ret
= info
[i
].info6
.architecture
;
634 driver_name_ret
= info
[i
].info7
.driver_name
;
637 driver_name_ret
= info
[i
].info8
.driver_name
;
638 environment_ret
= info
[i
].info8
.architecture
;
643 if (environment_ret
) {
644 torture_assert_str_equal(tctx
, environment
, environment_ret
, "architecture mismatch");
646 if (strequal(driver_name
, driver_name_ret
)) {
657 static bool test_EnumPrinterDrivers(struct torture_context
*tctx
,
660 struct test_spoolss_context
*ctx
=
661 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
662 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
663 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
664 uint16_t levels
[] = { 1, 2, 3, 4, 5, 6, 8 };
665 uint16_t buffer_sizes
[] = { 0, 1024, 6040, 0xffff };
668 /* FIXME: gd, come back and fix "" as server, and handle
669 * priority of returned error codes in torture test and samba 3
671 const char *server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
672 const char *environments
[2];
674 environments
[0] = SPOOLSS_ARCHITECTURE_ALL
;
675 environments
[1] = ctx
->environment
;
677 for (a
=0;a
<ARRAY_SIZE(environments
);a
++) {
679 for (i
=0;i
<ARRAY_SIZE(buffer_sizes
);i
++) {
681 test_EnumPrinterDrivers_buffers(tctx
, b
, server_name
,
685 "failed to enumerate drivers");
688 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
689 int level
= levels
[i
];
691 union spoolss_DriverInfo
*info
;
694 test_EnumPrinterDrivers_args(tctx
, b
, server_name
, environments
[a
], level
, &count
, &info
),
695 "failed to enumerate drivers");
697 ctx
->driver_count
[level
] = count
;
698 ctx
->drivers
[level
] = info
;
701 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
702 int level
= levels
[i
];
703 int old_level
= levels
[i
-1];
705 torture_assert_int_equal(tctx
, ctx
->driver_count
[level
], ctx
->driver_count
[old_level
],
706 "EnumPrinterDrivers invalid value");
709 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
710 int level
= levels
[i
];
712 for (j
=0;j
<ctx
->driver_count
[level
- 1];j
++) {
713 union spoolss_DriverInfo
*cur
= &ctx
->drivers
[level
- 1][j
];
714 union spoolss_DriverInfo
*ref
= &ctx
->drivers
[7][j
];
718 COMPARE_STRING(tctx
, cur
->info1
, ref
->info8
, driver_name
);
721 COMPARE_UINT32(tctx
, cur
->info2
, ref
->info8
, version
);
722 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, driver_name
);
723 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, architecture
);
724 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, driver_path
);
725 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, data_file
);
726 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, config_file
);
729 COMPARE_UINT32(tctx
, cur
->info3
, ref
->info8
, version
);
730 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, driver_name
);
731 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, architecture
);
732 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, driver_path
);
733 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, data_file
);
734 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, config_file
);
735 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, help_file
);
736 COMPARE_STRING_ARRAY(tctx
, cur
->info3
, ref
->info8
, dependent_files
);
737 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, monitor_name
);
738 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, default_datatype
);
741 COMPARE_UINT32(tctx
, cur
->info4
, ref
->info8
, version
);
742 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, driver_name
);
743 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, architecture
);
744 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, driver_path
);
745 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, data_file
);
746 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, config_file
);
747 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, help_file
);
748 COMPARE_STRING_ARRAY(tctx
, cur
->info4
, ref
->info8
, dependent_files
);
749 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, monitor_name
);
750 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, default_datatype
);
751 COMPARE_STRING_ARRAY(tctx
, cur
->info4
, ref
->info8
, previous_names
);
754 COMPARE_UINT32(tctx
, cur
->info5
, ref
->info8
, version
);
755 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, driver_name
);
756 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, architecture
);
757 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, driver_path
);
758 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, data_file
);
759 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, config_file
);
760 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
761 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
762 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
765 COMPARE_UINT32(tctx
, cur
->info6
, ref
->info8
, version
);
766 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, driver_name
);
767 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, architecture
);
768 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, driver_path
);
769 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, data_file
);
770 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, config_file
);
771 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, help_file
);
772 COMPARE_STRING_ARRAY(tctx
, cur
->info6
, ref
->info8
, dependent_files
);
773 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, monitor_name
);
774 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, default_datatype
);
775 COMPARE_STRING_ARRAY(tctx
, cur
->info6
, ref
->info8
, previous_names
);
776 COMPARE_NTTIME(tctx
, cur
->info6
, ref
->info8
, driver_date
);
777 COMPARE_UINT64(tctx
, cur
->info6
, ref
->info8
, driver_version
);
778 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, manufacturer_name
);
779 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, manufacturer_url
);
780 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, hardware_id
);
781 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, provider
);
784 /* level 8 is our reference, and it makes no sense to compare it to itself */
794 static bool test_EnumMonitors(struct torture_context
*tctx
,
797 struct test_spoolss_context
*ctx
=
798 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
799 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
800 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
802 struct spoolss_EnumMonitors r
;
803 uint16_t levels
[] = { 1, 2 };
806 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
807 int level
= levels
[i
];
811 union spoolss_MonitorInfo
*info
;
813 r
.in
.servername
= "";
817 r
.out
.needed
= &needed
;
818 r
.out
.count
= &count
;
821 torture_comment(tctx
, "Testing EnumMonitors level %u\n", r
.in
.level
);
823 status
= dcerpc_spoolss_EnumMonitors_r(b
, ctx
, &r
);
824 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumMonitors failed");
825 if (W_ERROR_IS_OK(r
.out
.result
)) {
826 /* TODO: do some more checks here */
829 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
830 "EnumMonitors failed");
832 blob
= data_blob_talloc_zero(ctx
, needed
);
834 r
.in
.offered
= needed
;
836 status
= dcerpc_spoolss_EnumMonitors_r(b
, ctx
, &r
);
837 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumMonitors failed");
839 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumMonitors failed");
841 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors
, info
, r
.in
.level
, count
, needed
, 4);
843 ctx
->monitor_count
[level
] = count
;
844 ctx
->monitors
[level
] = info
;
847 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
848 int level
= levels
[i
];
849 int old_level
= levels
[i
-1];
850 torture_assert_int_equal(tctx
, ctx
->monitor_count
[level
], ctx
->monitor_count
[old_level
],
851 "EnumMonitors invalid value");
854 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
855 int level
= levels
[i
];
856 for (j
=0;j
<ctx
->monitor_count
[level
];j
++) {
857 union spoolss_MonitorInfo
*cur
= &ctx
->monitors
[level
][j
];
858 union spoolss_MonitorInfo
*ref
= &ctx
->monitors
[2][j
];
861 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, monitor_name
);
864 /* level 2 is our reference, and it makes no sense to compare it to itself */
873 static bool test_EnumPrintProcessors_level(struct torture_context
*tctx
,
874 struct dcerpc_binding_handle
*b
,
875 const char *environment
,
878 union spoolss_PrintProcessorInfo
**info_p
,
879 WERROR expected_result
)
881 struct spoolss_EnumPrintProcessors r
;
885 union spoolss_PrintProcessorInfo
*info
;
887 r
.in
.servername
= "";
888 r
.in
.environment
= environment
;
892 r
.out
.needed
= &needed
;
893 r
.out
.count
= &count
;
896 torture_comment(tctx
, "Testing EnumPrintProcessors(%s) level %u\n",
897 r
.in
.environment
, r
.in
.level
);
899 torture_assert_ntstatus_ok(tctx
,
900 dcerpc_spoolss_EnumPrintProcessors_r(b
, tctx
, &r
),
901 "EnumPrintProcessors failed");
902 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
903 blob
= data_blob_talloc_zero(tctx
, needed
);
905 r
.in
.offered
= needed
;
906 torture_assert_ntstatus_ok(tctx
,
907 dcerpc_spoolss_EnumPrintProcessors_r(b
, tctx
, &r
),
908 "EnumPrintProcessors failed");
910 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
911 "EnumPrintProcessors failed");
913 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors
, info
, level
, count
, needed
, 4);
925 static bool test_EnumPrintProcessors(struct torture_context
*tctx
,
928 struct test_spoolss_context
*ctx
=
929 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
931 uint16_t levels
[] = {0, 1, 2, 3, 32, 256 };
932 uint16_t ok
[] = {0, 1, 0, 0, 0, 0 };
934 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
935 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
938 test_EnumPrintProcessors_level(tctx
, b
, "phantasy", 1, NULL
, NULL
, WERR_INVALID_ENVIRONMENT
),
939 "test_EnumPrintProcessors_level failed");
941 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
942 union spoolss_PrintProcessorInfo
*info
;
944 WERROR expected_result
= ok
[i
] ? WERR_OK
: WERR_INVALID_LEVEL
;
947 test_EnumPrintProcessors_level(tctx
, b
, ctx
->environment
, levels
[i
], &count
, &info
, expected_result
),
948 "test_EnumPrintProcessors_level failed");
954 static bool test_EnumPrintProcDataTypes_level(struct torture_context
*tctx
,
955 struct dcerpc_binding_handle
*b
,
956 const char *print_processor_name
,
959 union spoolss_PrintProcDataTypesInfo
**info_p
,
960 WERROR expected_result
)
962 struct spoolss_EnumPrintProcDataTypes r
;
966 union spoolss_PrintProcDataTypesInfo
*info
;
968 r
.in
.servername
= "";
969 r
.in
.print_processor_name
= print_processor_name
;
973 r
.out
.needed
= &needed
;
974 r
.out
.count
= &count
;
977 torture_comment(tctx
, "Testing EnumPrintProcDataTypes(%s) level %u\n",
978 r
.in
.print_processor_name
, r
.in
.level
);
980 torture_assert_ntstatus_ok(tctx
,
981 dcerpc_spoolss_EnumPrintProcDataTypes_r(b
, tctx
, &r
),
982 "EnumPrintProcDataTypes failed");
983 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
984 blob
= data_blob_talloc_zero(tctx
, needed
);
986 r
.in
.offered
= needed
;
987 torture_assert_ntstatus_ok(tctx
,
988 dcerpc_spoolss_EnumPrintProcDataTypes_r(b
, tctx
, &r
),
989 "EnumPrintProcDataTypes failed");
991 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
992 "EnumPrintProcDataTypes failed");
994 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes
, info
, level
, count
, needed
, 4);
1006 static bool test_EnumPrintProcDataTypes(struct torture_context
*tctx
,
1009 struct test_spoolss_context
*ctx
=
1010 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
1012 uint16_t levels
[] = {0, 1, 2, 3, 32, 256 };
1013 uint16_t ok
[] = {0, 1, 0, 0, 0, 0 };
1015 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
1016 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
1018 torture_assert(tctx
,
1019 test_EnumPrintProcDataTypes_level(tctx
, b
, NULL
, 1, NULL
, NULL
, WERR_UNKNOWN_PRINTPROCESSOR
),
1020 "test_EnumPrintProcDataTypes_level failed");
1022 torture_assert(tctx
,
1023 test_EnumPrintProcDataTypes_level(tctx
, b
, "nonexisting", 1, NULL
, NULL
, WERR_UNKNOWN_PRINTPROCESSOR
),
1024 "test_EnumPrintProcDataTypes_level failed");
1026 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
1027 int level
= levels
[i
];
1029 union spoolss_PrintProcDataTypesInfo
*info
;
1030 WERROR expected_result
= ok
[i
] ? WERR_OK
: WERR_INVALID_LEVEL
;
1032 torture_assert(tctx
,
1033 test_EnumPrintProcDataTypes_level(tctx
, b
, "winprint", level
, &count
, &info
, expected_result
),
1034 "test_EnumPrintProcDataTypes_level failed");
1038 union spoolss_PrintProcessorInfo
*info
;
1041 torture_assert(tctx
,
1042 test_EnumPrintProcessors_level(tctx
, b
, ctx
->environment
, 1, &count
, &info
, WERR_OK
),
1043 "test_EnumPrintProcessors_level failed");
1045 for (i
=0; i
< count
; i
++) {
1046 torture_assert(tctx
,
1047 test_EnumPrintProcDataTypes_level(tctx
, b
, info
[i
].info1
.print_processor_name
, 1, NULL
, NULL
, WERR_OK
),
1048 "test_EnumPrintProcDataTypes_level failed");
1056 static bool test_EnumPrinters(struct torture_context
*tctx
,
1059 struct test_spoolss_context
*ctx
=
1060 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
1061 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
1062 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
1063 struct spoolss_EnumPrinters r
;
1065 uint16_t levels
[] = { 0, 1, 2, 4, 5 };
1068 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
1069 int level
= levels
[i
];
1073 union spoolss_PrinterInfo
*info
;
1075 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
1080 r
.out
.needed
= &needed
;
1081 r
.out
.count
= &count
;
1084 torture_comment(tctx
, "Testing EnumPrinters level %u\n", r
.in
.level
);
1086 status
= dcerpc_spoolss_EnumPrinters_r(b
, ctx
, &r
);
1087 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinters failed");
1088 if (W_ERROR_IS_OK(r
.out
.result
)) {
1089 /* TODO: do some more checks here */
1092 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
1093 "EnumPrinters unexpected return code");
1095 blob
= data_blob_talloc_zero(ctx
, needed
);
1096 r
.in
.buffer
= &blob
;
1097 r
.in
.offered
= needed
;
1099 status
= dcerpc_spoolss_EnumPrinters_r(b
, ctx
, &r
);
1100 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinters failed");
1102 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
1104 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters
, info
, r
.in
.level
, count
, needed
, 4);
1106 ctx
->printer_count
[level
] = count
;
1107 ctx
->printers
[level
] = info
;
1110 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
1111 int level
= levels
[i
];
1112 int old_level
= levels
[i
-1];
1113 torture_assert_int_equal(tctx
, ctx
->printer_count
[level
], ctx
->printer_count
[old_level
],
1114 "EnumPrinters invalid value");
1117 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
1118 int level
= levels
[i
];
1119 for (j
=0;j
<ctx
->printer_count
[level
];j
++) {
1120 union spoolss_PrinterInfo
*cur
= &ctx
->printers
[level
][j
];
1121 union spoolss_PrinterInfo
*ref
= &ctx
->printers
[2][j
];
1124 COMPARE_STRING(tctx
, cur
->info0
, ref
->info2
, printername
);
1125 COMPARE_STRING(tctx
, cur
->info0
, ref
->info2
, servername
);
1126 COMPARE_UINT32(tctx
, cur
->info0
, ref
->info2
, cjobs
);
1127 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
1128 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
1129 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
1130 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
1131 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
1132 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
1133 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
1134 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
1135 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
1136 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
1137 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
1138 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
1139 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
1140 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
1141 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
1142 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
1143 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
1144 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
1145 COMPARE_UINT32(tctx
, cur
->info0
, ref
->info2
, status
);
1146 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
1147 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
1148 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
1149 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
1150 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
1151 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
1152 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
1155 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
1156 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
1157 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
1158 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, comment
);
1161 /* level 2 is our reference, and it makes no sense to compare it to itself */
1164 COMPARE_STRING(tctx
, cur
->info4
, ref
->info2
, printername
);
1165 COMPARE_STRING(tctx
, cur
->info4
, ref
->info2
, servername
);
1166 COMPARE_UINT32(tctx
, cur
->info4
, ref
->info2
, attributes
);
1169 COMPARE_STRING(tctx
, cur
->info5
, ref
->info2
, printername
);
1170 COMPARE_STRING(tctx
, cur
->info5
, ref
->info2
, portname
);
1171 COMPARE_UINT32(tctx
, cur
->info5
, ref
->info2
, attributes
);
1172 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
1173 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
1180 * - verify that the port of a printer was in the list returned by EnumPorts
1186 static bool test_GetPrinterDriver2(struct torture_context
*tctx
,
1187 struct dcerpc_binding_handle
*b
,
1188 struct policy_handle
*handle
,
1189 const char *driver_name
,
1190 const char *environment
);
1192 bool test_GetPrinter_level(struct torture_context
*tctx
,
1193 struct dcerpc_binding_handle
*b
,
1194 struct policy_handle
*handle
,
1196 union spoolss_PrinterInfo
*info
)
1198 struct spoolss_GetPrinter r
;
1201 r
.in
.handle
= handle
;
1205 r
.out
.needed
= &needed
;
1207 torture_comment(tctx
, "Testing GetPrinter level %u\n", r
.in
.level
);
1209 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinter_r(b
, tctx
, &r
),
1210 "GetPrinter failed");
1212 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1213 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
1214 r
.in
.buffer
= &blob
;
1215 r
.in
.offered
= needed
;
1217 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinter_r(b
, tctx
, &r
),
1218 "GetPrinter failed");
1221 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrinter failed");
1223 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo
, r
.out
.info
, r
.in
.level
, needed
, 4);
1225 if (info
&& r
.out
.info
) {
1226 *info
= *r
.out
.info
;
1233 static bool test_GetPrinter(struct torture_context
*tctx
,
1234 struct dcerpc_binding_handle
*b
,
1235 struct policy_handle
*handle
,
1236 const char *environment
)
1238 uint32_t levels
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1241 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
1243 union spoolss_PrinterInfo info
;
1247 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, levels
[i
], &info
),
1248 "failed to call GetPrinter");
1250 if ((levels
[i
] == 2) && info
.info2
.drivername
&& strlen(info
.info2
.drivername
)) {
1251 torture_assert(tctx
,
1252 test_GetPrinterDriver2(tctx
, b
, handle
, info
.info2
.drivername
, environment
),
1253 "failed to call test_GetPrinterDriver2");
1260 static bool test_SetPrinter(struct torture_context
*tctx
,
1261 struct dcerpc_binding_handle
*b
,
1262 struct policy_handle
*handle
,
1263 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
1264 struct spoolss_DevmodeContainer
*devmode_ctr
,
1265 struct sec_desc_buf
*secdesc_ctr
,
1266 enum spoolss_PrinterControl command
)
1268 struct spoolss_SetPrinter r
;
1270 r
.in
.handle
= handle
;
1271 r
.in
.info_ctr
= info_ctr
;
1272 r
.in
.devmode_ctr
= devmode_ctr
;
1273 r
.in
.secdesc_ctr
= secdesc_ctr
;
1274 r
.in
.command
= command
;
1276 torture_comment(tctx
, "Testing SetPrinter level %d\n", r
.in
.info_ctr
->level
);
1278 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
),
1279 "failed to call SetPrinter");
1280 torture_assert(tctx
, (W_ERROR_EQUAL(r
.out
.result
, WERR_OK
)
1281 || W_ERROR_EQUAL(r
.out
.result
, WERR_IO_PENDING
)),
1282 "SetPrinter failed");
1287 static bool test_SetPrinter_errors(struct torture_context
*tctx
,
1288 struct dcerpc_binding_handle
*b
,
1289 struct policy_handle
*handle
)
1291 struct spoolss_SetPrinter r
;
1292 uint16_t levels
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1295 struct spoolss_SetPrinterInfoCtr info_ctr
;
1296 struct spoolss_DevmodeContainer devmode_ctr
;
1297 struct sec_desc_buf secdesc_ctr
;
1300 info_ctr
.info
.info0
= NULL
;
1302 ZERO_STRUCT(devmode_ctr
);
1303 ZERO_STRUCT(secdesc_ctr
);
1305 r
.in
.handle
= handle
;
1306 r
.in
.info_ctr
= &info_ctr
;
1307 r
.in
.devmode_ctr
= &devmode_ctr
;
1308 r
.in
.secdesc_ctr
= &secdesc_ctr
;
1311 torture_comment(tctx
, "Testing SetPrinter all zero\n");
1313 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
),
1314 "failed to call SetPrinter");
1315 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
1316 "failed to call SetPrinter");
1319 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
1321 struct spoolss_SetPrinterInfo0 info0
;
1322 struct spoolss_SetPrinterInfo1 info1
;
1323 struct spoolss_SetPrinterInfo2 info2
;
1324 struct spoolss_SetPrinterInfo3 info3
;
1325 struct spoolss_SetPrinterInfo4 info4
;
1326 struct spoolss_SetPrinterInfo5 info5
;
1327 struct spoolss_SetPrinterInfo6 info6
;
1328 struct spoolss_SetPrinterInfo7 info7
;
1329 struct spoolss_SetPrinterInfo8 info8
;
1330 struct spoolss_SetPrinterInfo9 info9
;
1333 info_ctr
.level
= levels
[i
];
1334 switch (levels
[i
]) {
1337 info_ctr
.info
.info0
= &info0
;
1341 info_ctr
.info
.info1
= &info1
;
1345 info_ctr
.info
.info2
= &info2
;
1349 info_ctr
.info
.info3
= &info3
;
1353 info_ctr
.info
.info4
= &info4
;
1357 info_ctr
.info
.info5
= &info5
;
1361 info_ctr
.info
.info6
= &info6
;
1365 info_ctr
.info
.info7
= &info7
;
1369 info_ctr
.info
.info8
= &info8
;
1373 info_ctr
.info
.info9
= &info9
;
1377 torture_comment(tctx
, "Testing SetPrinter level %d, command %d\n",
1378 info_ctr
.level
, r
.in
.command
);
1380 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
),
1381 "failed to call SetPrinter");
1383 switch (r
.in
.command
) {
1384 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
: /* 0 */
1385 /* is ignored for all levels other then 0 */
1386 if (info_ctr
.level
> 0) {
1390 case SPOOLSS_PRINTER_CONTROL_PAUSE
: /* 1 */
1391 case SPOOLSS_PRINTER_CONTROL_RESUME
: /* 2 */
1392 case SPOOLSS_PRINTER_CONTROL_PURGE
: /* 3 */
1393 if (info_ctr
.level
> 0) {
1394 /* is invalid for all levels other then 0 */
1395 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PRINTER_COMMAND
,
1396 "unexpected error code returned");
1399 torture_assert_werr_ok(tctx
, r
.out
.result
,
1400 "failed to call SetPrinter with non 0 command");
1405 case SPOOLSS_PRINTER_CONTROL_SET_STATUS
: /* 4 */
1406 /* FIXME: gd needs further investigation */
1408 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PRINTER_COMMAND
,
1409 "unexpected error code returned");
1413 switch (info_ctr
.level
) {
1415 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
,
1416 "unexpected error code returned");
1419 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_PRINTER_DRIVER
,
1420 "unexpected error code returned");
1426 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
1427 "unexpected error code returned");
1430 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_NOT_SUPPORTED
,
1431 "unexpected error code returned");
1434 torture_assert_werr_ok(tctx
, r
.out
.result
,
1435 "failed to call SetPrinter");
1440 if (r
.in
.command
< 5) {
1448 static void clear_info2(struct spoolss_SetPrinterInfoCtr
*r
)
1450 if ((r
->level
== 2) && (r
->info
.info2
)) {
1451 r
->info
.info2
->secdesc_ptr
= NULL
;
1452 r
->info
.info2
->devmode_ptr
= NULL
;
1456 static bool test_PrinterInfo(struct torture_context
*tctx
,
1457 struct dcerpc_binding_handle
*b
,
1458 struct policy_handle
*handle
)
1461 struct spoolss_SetPrinter s
;
1462 struct spoolss_GetPrinter q
;
1463 struct spoolss_GetPrinter q0
;
1464 struct spoolss_SetPrinterInfoCtr info_ctr
;
1465 union spoolss_PrinterInfo info
;
1466 struct spoolss_DevmodeContainer devmode_ctr
;
1467 struct sec_desc_buf secdesc_ctr
;
1472 uint32_t status_list
[] = {
1473 /* these do not stick
1474 PRINTER_STATUS_PAUSED,
1475 PRINTER_STATUS_ERROR,
1476 PRINTER_STATUS_PENDING_DELETION, */
1477 PRINTER_STATUS_PAPER_JAM
,
1478 PRINTER_STATUS_PAPER_OUT
,
1479 PRINTER_STATUS_MANUAL_FEED
,
1480 PRINTER_STATUS_PAPER_PROBLEM
,
1481 PRINTER_STATUS_OFFLINE
,
1482 PRINTER_STATUS_IO_ACTIVE
,
1483 PRINTER_STATUS_BUSY
,
1484 PRINTER_STATUS_PRINTING
,
1485 PRINTER_STATUS_OUTPUT_BIN_FULL
,
1486 PRINTER_STATUS_NOT_AVAILABLE
,
1487 PRINTER_STATUS_WAITING
,
1488 PRINTER_STATUS_PROCESSING
,
1489 PRINTER_STATUS_INITIALIZING
,
1490 PRINTER_STATUS_WARMING_UP
,
1491 PRINTER_STATUS_TONER_LOW
,
1492 PRINTER_STATUS_NO_TONER
,
1493 PRINTER_STATUS_PAGE_PUNT
,
1494 PRINTER_STATUS_USER_INTERVENTION
,
1495 PRINTER_STATUS_OUT_OF_MEMORY
,
1496 PRINTER_STATUS_DOOR_OPEN
,
1497 PRINTER_STATUS_SERVER_UNKNOWN
,
1498 PRINTER_STATUS_POWER_SAVE
,
1499 /* these do not stick
1508 uint32_t default_attribute
= PRINTER_ATTRIBUTE_LOCAL
;
1509 uint32_t attribute_list
[] = {
1510 PRINTER_ATTRIBUTE_QUEUED
,
1511 /* fails with WERR_INVALID_DATATYPE:
1512 PRINTER_ATTRIBUTE_DIRECT, */
1514 PRINTER_ATTRIBUTE_DEFAULT, */
1515 PRINTER_ATTRIBUTE_SHARED
,
1517 PRINTER_ATTRIBUTE_NETWORK, */
1518 PRINTER_ATTRIBUTE_HIDDEN
,
1519 PRINTER_ATTRIBUTE_LOCAL
,
1520 PRINTER_ATTRIBUTE_ENABLE_DEVQ
,
1521 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
,
1522 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST
,
1523 PRINTER_ATTRIBUTE_WORK_OFFLINE
,
1525 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1526 /* fails with WERR_INVALID_DATATYPE:
1527 PRINTER_ATTRIBUTE_RAW_ONLY, */
1528 /* these do not stick
1529 PRINTER_ATTRIBUTE_PUBLISHED,
1530 PRINTER_ATTRIBUTE_FAX,
1531 PRINTER_ATTRIBUTE_TS,
1550 torture_skip(tctx
, "Printer Info test is currently broken, skipping");
1553 ZERO_STRUCT(devmode_ctr
);
1554 ZERO_STRUCT(secdesc_ctr
);
1556 s
.in
.handle
= handle
;
1558 s
.in
.info_ctr
= &info_ctr
;
1559 s
.in
.devmode_ctr
= &devmode_ctr
;
1560 s
.in
.secdesc_ctr
= &secdesc_ctr
;
1562 q
.in
.handle
= handle
;
1566 #define TESTGETCALL(call, r) \
1567 r.in.buffer = NULL; \
1569 r.out.needed = &needed; \
1570 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1571 if (!NT_STATUS_IS_OK(status)) { \
1572 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1573 r.in.level, nt_errstr(status), __location__); \
1577 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1578 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1579 r.in.buffer = &blob; \
1580 r.in.offered = needed; \
1582 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1583 if (!NT_STATUS_IS_OK(status)) { \
1584 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1585 r.in.level, nt_errstr(status), __location__); \
1589 if (!W_ERROR_IS_OK(r.out.result)) { \
1590 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1591 r.in.level, win_errstr(r.out.result), __location__); \
1597 #define TESTSETCALL_EXP(call, r, err) \
1598 clear_info2(&info_ctr);\
1599 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1600 if (!NT_STATUS_IS_OK(status)) { \
1601 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1602 r.in.info_ctr->level, nt_errstr(status), __location__); \
1606 if (!W_ERROR_IS_OK(err)) { \
1607 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1608 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1609 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1614 if (!W_ERROR_IS_OK(r.out.result)) { \
1615 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1616 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1621 #define TESTSETCALL(call, r) \
1622 TESTSETCALL_EXP(call, r, WERR_OK)
1624 #define STRING_EQUAL(s1, s2, field) \
1625 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1626 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1627 #field, s2, __location__); \
1632 #define MEM_EQUAL(s1, s2, length, field) \
1633 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1634 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1635 #field, (const char *)s2, __location__); \
1640 #define INT_EQUAL(i1, i2, field) \
1642 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1643 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1648 #define SD_EQUAL(sd1, sd2, field) \
1649 if (!security_descriptor_equal(sd1, sd2)) { \
1650 torture_comment(tctx, "Failed to set %s (%s)\n", \
1651 #field, __location__); \
1656 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1658 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1659 q.in.level = lvl1; \
1660 TESTGETCALL(GetPrinter, q) \
1661 info_ctr.level = lvl1; \
1662 p = (void *)&q.out.info->info ## lvl1; \
1663 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
1664 info_ctr.info.info ## lvl1->field1 = value;\
1665 TESTSETCALL_EXP(SetPrinter, s, err) \
1666 info_ctr.info.info ## lvl1->field1 = ""; \
1667 TESTGETCALL(GetPrinter, q) \
1668 info_ctr.info.info ## lvl1->field1 = value; \
1669 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1670 q.in.level = lvl2; \
1671 TESTGETCALL(GetPrinter, q) \
1672 p = (void *)&q.out.info->info ## lvl2; \
1673 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)p; \
1674 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1677 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1678 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1681 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1683 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1684 q.in.level = lvl1; \
1685 TESTGETCALL(GetPrinter, q) \
1686 info_ctr.level = lvl1; \
1687 p = (void *)&q.out.info->info ## lvl1; \
1688 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
1689 info_ctr.info.info ## lvl1->field1 = value; \
1690 TESTSETCALL(SetPrinter, s) \
1691 info_ctr.info.info ## lvl1->field1 = 0; \
1692 TESTGETCALL(GetPrinter, q) \
1693 p = (void *)&q.out.info->info ## lvl1; \
1694 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
1695 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1696 q.in.level = lvl2; \
1697 TESTGETCALL(GetPrinter, q) \
1698 p = (void *)&q.out.info->info ## lvl2; \
1699 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)p; \
1700 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1703 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1704 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1708 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1710 TEST_PRINTERINFO_STRING(2, comment
, 1, comment
, "xx2-1 comment");
1711 TEST_PRINTERINFO_STRING(2, comment
, 2, comment
, "xx2-2 comment");
1713 /* level 0 printername does not stick */
1714 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1715 TEST_PRINTERINFO_STRING(2, printername
, 1, name
, "xx2-1 printer");
1716 TEST_PRINTERINFO_STRING(2, printername
, 2, printername
, "xx2-2 printer");
1717 TEST_PRINTERINFO_STRING(2, printername
, 4, printername
, "xx2-4 printer");
1718 TEST_PRINTERINFO_STRING(2, printername
, 5, printername
, "xx2-5 printer");
1719 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1720 TEST_PRINTERINFO_STRING(4, printername
, 1, name
, "xx4-1 printer");
1721 TEST_PRINTERINFO_STRING(4, printername
, 2, printername
, "xx4-2 printer");
1722 TEST_PRINTERINFO_STRING(4, printername
, 4, printername
, "xx4-4 printer");
1723 TEST_PRINTERINFO_STRING(4, printername
, 5, printername
, "xx4-5 printer");
1724 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1725 TEST_PRINTERINFO_STRING(5, printername
, 1, name
, "xx5-1 printer");
1726 TEST_PRINTERINFO_STRING(5, printername
, 2, printername
, "xx5-2 printer");
1727 TEST_PRINTERINFO_STRING(5, printername
, 4, printername
, "xx5-4 printer");
1728 TEST_PRINTERINFO_STRING(5, printername
, 5, printername
, "xx5-5 printer");
1730 /* servername can be set but does not stick
1731 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1732 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1733 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1736 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1737 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname
, 2, portname
, "xx2-2 portname", WERR_UNKNOWN_PORT
);
1738 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname
, 5, portname
, "xx2-5 portname", WERR_UNKNOWN_PORT
);
1739 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname
, 2, portname
, "xx5-2 portname", WERR_UNKNOWN_PORT
);
1740 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname
, 5, portname
, "xx5-5 portname", WERR_UNKNOWN_PORT
);
1742 TEST_PRINTERINFO_STRING(2, sharename
, 2, sharename
, "xx2-2 sharename");
1743 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1744 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername
, 2, drivername
, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER
);
1745 TEST_PRINTERINFO_STRING(2, location
, 2, location
, "xx2-2 location");
1746 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1747 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile
, 2, sepfile
, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE
);
1748 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1749 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor
, 2, printprocessor
, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR
);
1750 TEST_PRINTERINFO_STRING(2, datatype
, 2, datatype
, "xx2-2 datatype");
1751 TEST_PRINTERINFO_STRING(2, parameters
, 2, parameters
, "xx2-2 parameters");
1753 for (i
=0; i
< ARRAY_SIZE(attribute_list
); i
++) {
1754 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1756 (attribute_list[i] | default_attribute)
1758 TEST_PRINTERINFO_INT_EXP(2, attributes
, 2, attributes
,
1760 (attribute_list
[i
] | default_attribute
)
1762 TEST_PRINTERINFO_INT_EXP(2, attributes
, 4, attributes
,
1764 (attribute_list
[i
] | default_attribute
)
1766 TEST_PRINTERINFO_INT_EXP(2, attributes
, 5, attributes
,
1768 (attribute_list
[i
] | default_attribute
)
1770 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1772 (attribute_list[i] | default_attribute)
1774 TEST_PRINTERINFO_INT_EXP(4, attributes
, 2, attributes
,
1776 (attribute_list
[i
] | default_attribute
)
1778 TEST_PRINTERINFO_INT_EXP(4, attributes
, 4, attributes
,
1780 (attribute_list
[i
] | default_attribute
)
1782 TEST_PRINTERINFO_INT_EXP(4, attributes
, 5, attributes
,
1784 (attribute_list
[i
] | default_attribute
)
1786 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1788 (attribute_list[i] | default_attribute)
1790 TEST_PRINTERINFO_INT_EXP(5, attributes
, 2, attributes
,
1792 (attribute_list
[i
] | default_attribute
)
1794 TEST_PRINTERINFO_INT_EXP(5, attributes
, 4, attributes
,
1796 (attribute_list
[i
] | default_attribute
)
1798 TEST_PRINTERINFO_INT_EXP(5, attributes
, 5, attributes
,
1800 (attribute_list
[i
] | default_attribute
)
1804 for (i
=0; i
< ARRAY_SIZE(status_list
); i
++) {
1805 /* level 2 sets do not stick
1806 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1807 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1808 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1809 TEST_PRINTERINFO_INT(6, status
, 0, status
, status_list
[i
]);
1810 TEST_PRINTERINFO_INT(6, status
, 2, status
, status_list
[i
]);
1811 TEST_PRINTERINFO_INT(6, status
, 6, status
, status_list
[i
]);
1814 /* priorities need to be between 0 and 99
1815 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1816 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 0);
1817 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 1);
1818 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 99);
1819 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1820 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 0);
1821 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 1);
1822 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 99);
1823 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1825 TEST_PRINTERINFO_INT(2, starttime
, 2, starttime
, __LINE__
);
1826 TEST_PRINTERINFO_INT(2, untiltime
, 2, untiltime
, __LINE__
);
1829 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1830 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1833 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1834 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1836 /* FIXME: gd also test devmode and secdesc behavior */
1839 /* verify composition of level 1 description field */
1840 const char *description
;
1844 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1846 description
= talloc_strdup(tctx
, q0
.out
.info
->info1
.description
);
1849 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1851 tmp
= talloc_asprintf(tctx
, "%s,%s,%s",
1852 q0
.out
.info
->info2
.printername
,
1853 q0
.out
.info
->info2
.drivername
,
1854 q0
.out
.info
->info2
.location
);
1856 do { STRING_EQUAL(description
, tmp
, "description")} while (0);
1862 static bool test_security_descriptor_equal(struct torture_context
*tctx
,
1863 const struct security_descriptor
*sd1
,
1864 const struct security_descriptor
*sd2
)
1871 torture_comment(tctx
, "%s\n", __location__
);
1875 torture_assert_int_equal(tctx
, sd1
->revision
, sd2
->revision
, "revision mismatch");
1876 torture_assert_int_equal(tctx
, sd1
->type
, sd2
->type
, "type mismatch");
1878 torture_assert_sid_equal(tctx
, sd1
->owner_sid
, sd2
->owner_sid
, "owner mismatch");
1879 torture_assert_sid_equal(tctx
, sd1
->group_sid
, sd2
->group_sid
, "group mismatch");
1881 if (!security_acl_equal(sd1
->sacl
, sd2
->sacl
)) {
1882 torture_comment(tctx
, "%s: sacl mismatch\n", __location__
);
1883 NDR_PRINT_DEBUG(security_acl
, sd1
->sacl
);
1884 NDR_PRINT_DEBUG(security_acl
, sd2
->sacl
);
1887 if (!security_acl_equal(sd1
->dacl
, sd2
->dacl
)) {
1888 torture_comment(tctx
, "%s: dacl mismatch\n", __location__
);
1889 NDR_PRINT_DEBUG(security_acl
, sd1
->dacl
);
1890 NDR_PRINT_DEBUG(security_acl
, sd2
->dacl
);
1897 static bool test_sd_set_level(struct torture_context
*tctx
,
1898 struct dcerpc_binding_handle
*b
,
1899 struct policy_handle
*handle
,
1901 struct security_descriptor
*sd
)
1903 struct spoolss_SetPrinterInfoCtr info_ctr
;
1904 struct spoolss_DevmodeContainer devmode_ctr
;
1905 struct sec_desc_buf secdesc_ctr
;
1906 union spoolss_SetPrinterInfo sinfo
;
1907 union spoolss_PrinterInfo info
;
1908 struct spoolss_SetPrinterInfo3 info3
;
1910 ZERO_STRUCT(devmode_ctr
);
1911 ZERO_STRUCT(secdesc_ctr
);
1915 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
1916 torture_assert(tctx
, PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
1919 info_ctr
.info
= sinfo
;
1925 info3
.sec_desc_ptr
= NULL
;
1928 info_ctr
.info
.info3
= &info3
;
1936 secdesc_ctr
.sd
= sd
;
1938 torture_assert(tctx
,
1939 test_SetPrinter(tctx
, b
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0), "");
1944 static bool test_PrinterInfo_SDs(struct torture_context
*tctx
,
1945 struct dcerpc_binding_handle
*b
,
1946 struct policy_handle
*handle
)
1948 union spoolss_PrinterInfo info
;
1949 struct security_descriptor
*sd1
, *sd2
;
1952 /* just compare level 2 and level 3 */
1954 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
1956 sd1
= info
.info2
.secdesc
;
1958 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 3, &info
), "");
1960 sd2
= info
.info3
.secdesc
;
1962 torture_assert(tctx
, test_security_descriptor_equal(tctx
, sd1
, sd2
),
1963 "SD level 2 != SD level 3");
1966 /* query level 2, set level 2, query level 2 */
1968 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
1970 sd1
= info
.info2
.secdesc
;
1972 torture_assert(tctx
, test_sd_set_level(tctx
, b
, handle
, 2, sd1
), "");
1974 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
1976 sd2
= info
.info2
.secdesc
;
1977 if (sd1
->type
& SEC_DESC_DACL_DEFAULTED
) {
1978 torture_comment(tctx
, "removing SEC_DESC_DACL_DEFAULTED\n");
1979 sd1
->type
&= ~SEC_DESC_DACL_DEFAULTED
;
1982 torture_assert(tctx
, test_security_descriptor_equal(tctx
, sd1
, sd2
),
1983 "SD level 2 != SD level 2 after SD has been set via level 2");
1986 /* query level 2, set level 3, query level 2 */
1988 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
1990 sd1
= info
.info2
.secdesc
;
1992 torture_assert(tctx
, test_sd_set_level(tctx
, b
, handle
, 3, sd1
), "");
1994 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
1996 sd2
= info
.info2
.secdesc
;
1998 torture_assert(tctx
, test_security_descriptor_equal(tctx
, sd1
, sd2
),
1999 "SD level 2 != SD level 2 after SD has been set via level 3");
2001 /* set modified sd level 3, query level 2 */
2003 for (i
=0; i
< 93; i
++) {
2004 struct security_ace a
;
2005 const char *sid_string
= talloc_asprintf(tctx
, "S-1-5-32-9999%i", i
);
2006 a
.type
= SEC_ACE_TYPE_ACCESS_ALLOWED
;
2008 a
.size
= 0; /* autogenerated */
2010 a
.trustee
= *dom_sid_parse_talloc(tctx
, sid_string
);
2011 torture_assert_ntstatus_ok(tctx
, security_descriptor_dacl_add(sd1
, &a
), "");
2014 torture_assert(tctx
, test_sd_set_level(tctx
, b
, handle
, 3, sd1
), "");
2016 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
2017 sd2
= info
.info2
.secdesc
;
2019 if (sd1
->type
& SEC_DESC_DACL_DEFAULTED
) {
2020 torture_comment(tctx
, "removing SEC_DESC_DACL_DEFAULTED\n");
2021 sd1
->type
&= ~SEC_DESC_DACL_DEFAULTED
;
2024 torture_assert(tctx
, test_security_descriptor_equal(tctx
, sd1
, sd2
),
2025 "modified SD level 2 != SD level 2 after SD has been set via level 3");
2032 * wrapper call that saves original sd, runs tests, and restores sd
2035 static bool test_PrinterInfo_SD(struct torture_context
*tctx
,
2036 struct dcerpc_binding_handle
*b
,
2037 struct policy_handle
*handle
)
2039 union spoolss_PrinterInfo info
;
2040 struct security_descriptor
*sd
;
2043 torture_comment(tctx
, "Testing Printer Security Descriptors\n");
2045 /* save original sd */
2047 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
2048 "failed to get initial security descriptor");
2050 sd
= security_descriptor_copy(tctx
, info
.info2
.secdesc
);
2054 ret
= test_PrinterInfo_SDs(tctx
, b
, handle
);
2056 /* restore original sd */
2058 torture_assert(tctx
, test_sd_set_level(tctx
, b
, handle
, 3, sd
),
2059 "failed to restore initial security descriptor");
2061 torture_comment(tctx
, "Printer Security Descriptors test %s\n\n",
2062 ret
? "succeeded" : "failed");
2068 static bool test_devmode_set_level(struct torture_context
*tctx
,
2069 struct dcerpc_binding_handle
*b
,
2070 struct policy_handle
*handle
,
2072 struct spoolss_DeviceMode
*devmode
)
2074 struct spoolss_SetPrinterInfoCtr info_ctr
;
2075 struct spoolss_DevmodeContainer devmode_ctr
;
2076 struct sec_desc_buf secdesc_ctr
;
2077 union spoolss_SetPrinterInfo sinfo
;
2079 ZERO_STRUCT(devmode_ctr
);
2080 ZERO_STRUCT(secdesc_ctr
);
2084 union spoolss_PrinterInfo info
;
2085 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
2086 torture_assert(tctx
, PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
2089 info_ctr
.info
= sinfo
;
2094 struct spoolss_SetPrinterInfo8 info8
;
2096 info8
.devmode_ptr
= NULL
;
2099 info_ctr
.info
.info8
= &info8
;
2107 devmode_ctr
.devmode
= devmode
;
2109 torture_assert(tctx
,
2110 test_SetPrinter(tctx
, b
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0), "");
2116 static bool test_devicemode_equal(struct torture_context
*tctx
,
2117 const struct spoolss_DeviceMode
*d1
,
2118 const struct spoolss_DeviceMode
*d2
)
2125 torture_comment(tctx
, "%s\n", __location__
);
2128 torture_assert_str_equal(tctx
, d1
->devicename
, d2
->devicename
, "devicename mismatch");
2129 torture_assert_int_equal(tctx
, d1
->specversion
, d2
->specversion
, "specversion mismatch");
2130 torture_assert_int_equal(tctx
, d1
->driverversion
, d2
->driverversion
, "driverversion mismatch");
2131 torture_assert_int_equal(tctx
, d1
->size
, d2
->size
, "size mismatch");
2132 torture_assert_int_equal(tctx
, d1
->__driverextra_length
, d2
->__driverextra_length
, "__driverextra_length mismatch");
2133 torture_assert_int_equal(tctx
, d1
->fields
, d2
->fields
, "fields mismatch");
2134 torture_assert_int_equal(tctx
, d1
->orientation
, d2
->orientation
, "orientation mismatch");
2135 torture_assert_int_equal(tctx
, d1
->papersize
, d2
->papersize
, "papersize mismatch");
2136 torture_assert_int_equal(tctx
, d1
->paperlength
, d2
->paperlength
, "paperlength mismatch");
2137 torture_assert_int_equal(tctx
, d1
->paperwidth
, d2
->paperwidth
, "paperwidth mismatch");
2138 torture_assert_int_equal(tctx
, d1
->scale
, d2
->scale
, "scale mismatch");
2139 torture_assert_int_equal(tctx
, d1
->copies
, d2
->copies
, "copies mismatch");
2140 torture_assert_int_equal(tctx
, d1
->defaultsource
, d2
->defaultsource
, "defaultsource mismatch");
2141 torture_assert_int_equal(tctx
, d1
->printquality
, d2
->printquality
, "printquality mismatch");
2142 torture_assert_int_equal(tctx
, d1
->color
, d2
->color
, "color mismatch");
2143 torture_assert_int_equal(tctx
, d1
->duplex
, d2
->duplex
, "duplex mismatch");
2144 torture_assert_int_equal(tctx
, d1
->yresolution
, d2
->yresolution
, "yresolution mismatch");
2145 torture_assert_int_equal(tctx
, d1
->ttoption
, d2
->ttoption
, "ttoption mismatch");
2146 torture_assert_int_equal(tctx
, d1
->collate
, d2
->collate
, "collate mismatch");
2147 torture_assert_str_equal(tctx
, d1
->formname
, d2
->formname
, "formname mismatch");
2148 torture_assert_int_equal(tctx
, d1
->logpixels
, d2
->logpixels
, "logpixels mismatch");
2149 torture_assert_int_equal(tctx
, d1
->bitsperpel
, d2
->bitsperpel
, "bitsperpel mismatch");
2150 torture_assert_int_equal(tctx
, d1
->pelswidth
, d2
->pelswidth
, "pelswidth mismatch");
2151 torture_assert_int_equal(tctx
, d1
->pelsheight
, d2
->pelsheight
, "pelsheight mismatch");
2152 torture_assert_int_equal(tctx
, d1
->displayflags
, d2
->displayflags
, "displayflags mismatch");
2153 torture_assert_int_equal(tctx
, d1
->displayfrequency
, d2
->displayfrequency
, "displayfrequency mismatch");
2154 torture_assert_int_equal(tctx
, d1
->icmmethod
, d2
->icmmethod
, "icmmethod mismatch");
2155 torture_assert_int_equal(tctx
, d1
->icmintent
, d2
->icmintent
, "icmintent mismatch");
2156 torture_assert_int_equal(tctx
, d1
->mediatype
, d2
->mediatype
, "mediatype mismatch");
2157 torture_assert_int_equal(tctx
, d1
->dithertype
, d2
->dithertype
, "dithertype mismatch");
2158 torture_assert_int_equal(tctx
, d1
->reserved1
, d2
->reserved1
, "reserved1 mismatch");
2159 torture_assert_int_equal(tctx
, d1
->reserved2
, d2
->reserved2
, "reserved2 mismatch");
2160 torture_assert_int_equal(tctx
, d1
->panningwidth
, d2
->panningwidth
, "panningwidth mismatch");
2161 torture_assert_int_equal(tctx
, d1
->panningheight
, d2
->panningheight
, "panningheight mismatch");
2162 torture_assert_data_blob_equal(tctx
, d1
->driverextra_data
, d2
->driverextra_data
, "driverextra_data mismatch");
2167 static bool test_devicemode_full(struct torture_context
*tctx
,
2168 struct dcerpc_binding_handle
*b
,
2169 struct policy_handle
*handle
)
2171 struct spoolss_SetPrinter s
;
2172 struct spoolss_GetPrinter q
;
2173 struct spoolss_SetPrinterInfoCtr info_ctr
;
2174 struct spoolss_SetPrinterInfo8 info8
;
2175 union spoolss_PrinterInfo info
;
2176 struct spoolss_DevmodeContainer devmode_ctr
;
2177 struct sec_desc_buf secdesc_ctr
;
2182 #define TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, exp_value, expected_result) do { \
2183 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2184 q.in.level = lvl1; \
2185 TESTGETCALL(GetPrinter, q) \
2186 info_ctr.level = lvl1; \
2188 void *p = (void *)&q.out.info->info ## lvl1; \
2189 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
2190 } else if (lvl1 == 8) {\
2191 info_ctr.info.info ## lvl1 = &info8; \
2193 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2194 devmode_ctr.devmode->field1 = value; \
2195 TESTSETCALL_EXP(SetPrinter, s, expected_result) \
2196 if (W_ERROR_IS_OK(expected_result)) { \
2197 TESTGETCALL(GetPrinter, q) \
2198 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2199 q.in.level = lvl2; \
2200 TESTGETCALL(GetPrinter, q) \
2201 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2205 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, expected_result) do { \
2206 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, expected_result); \
2209 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2210 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, WERR_OK); \
2213 ZERO_STRUCT(devmode_ctr
);
2214 ZERO_STRUCT(secdesc_ctr
);
2217 s
.in
.handle
= handle
;
2219 s
.in
.info_ctr
= &info_ctr
;
2220 s
.in
.devmode_ctr
= &devmode_ctr
;
2221 s
.in
.secdesc_ctr
= &secdesc_ctr
;
2223 q
.in
.handle
= handle
;
2227 const char *devicename
;/* [charset(UTF16)] */
2228 enum spoolss_DeviceModeSpecVersion specversion
;
2229 uint16_t driverversion
;
2230 uint16_t __driverextra_length
;/* [value(r->driverextra_data.length)] */
2233 TEST_DEVMODE_INT_EXP(8, size
, 8, size
, __LINE__
, WERR_INVALID_PARAM
);
2234 TEST_DEVMODE_INT_EXP(8, size
, 8, size
, 0, WERR_INVALID_PARAM
);
2235 TEST_DEVMODE_INT_EXP(8, size
, 8, size
, 0xffff, WERR_INVALID_PARAM
);
2236 TEST_DEVMODE_INT_EXP(8, size
, 8, size
, ndr_size_spoolss_DeviceMode(devmode_ctr
.devmode
, 0), (devmode_ctr
.devmode
->__driverextra_length
> 0 ) ? WERR_INVALID_PARAM
: WERR_OK
);
2237 TEST_DEVMODE_INT(8, size
, 8, size
, ndr_size_spoolss_DeviceMode(devmode_ctr
.devmode
, 0) - devmode_ctr
.devmode
->__driverextra_length
);
2239 devmode_ctr
.devmode
->driverextra_data
= data_blob_string_const("foobar");
2240 torture_assert(tctx
,
2241 test_devmode_set_level(tctx
, b
, handle
, 8, devmode_ctr
.devmode
),
2242 "failed to set devmode");
2244 TEST_DEVMODE_INT_EXP(8, size
, 8, size
, ndr_size_spoolss_DeviceMode(devmode_ctr
.devmode
, 0), (devmode_ctr
.devmode
->__driverextra_length
> 0 ) ? WERR_INVALID_PARAM
: WERR_OK
);
2245 TEST_DEVMODE_INT(8, size
, 8, size
, ndr_size_spoolss_DeviceMode(devmode_ctr
.devmode
, 0) - devmode_ctr
.devmode
->__driverextra_length
);
2247 TEST_DEVMODE_INT(8, orientation
, 8, orientation
, __LINE__
);
2248 TEST_DEVMODE_INT(8, papersize
, 8, papersize
, __LINE__
);
2249 TEST_DEVMODE_INT(8, paperlength
, 8, paperlength
, __LINE__
);
2250 TEST_DEVMODE_INT(8, paperwidth
, 8, paperwidth
, __LINE__
);
2251 TEST_DEVMODE_INT(8, scale
, 8, scale
, __LINE__
);
2252 TEST_DEVMODE_INT(8, copies
, 8, copies
, __LINE__
);
2253 TEST_DEVMODE_INT(8, defaultsource
, 8, defaultsource
, __LINE__
);
2254 TEST_DEVMODE_INT(8, printquality
, 8, printquality
, __LINE__
);
2255 TEST_DEVMODE_INT(8, color
, 8, color
, __LINE__
);
2256 TEST_DEVMODE_INT(8, duplex
, 8, duplex
, __LINE__
);
2257 TEST_DEVMODE_INT(8, yresolution
, 8, yresolution
, __LINE__
);
2258 TEST_DEVMODE_INT(8, ttoption
, 8, ttoption
, __LINE__
);
2259 TEST_DEVMODE_INT(8, collate
, 8, collate
, __LINE__
);
2261 const char *formname
;/* [charset(UTF16)] */
2263 TEST_DEVMODE_INT(8, logpixels
, 8, logpixels
, __LINE__
);
2264 TEST_DEVMODE_INT(8, bitsperpel
, 8, bitsperpel
, __LINE__
);
2265 TEST_DEVMODE_INT(8, pelswidth
, 8, pelswidth
, __LINE__
);
2266 TEST_DEVMODE_INT(8, pelsheight
, 8, pelsheight
, __LINE__
);
2267 TEST_DEVMODE_INT(8, displayflags
, 8, displayflags
, __LINE__
);
2268 TEST_DEVMODE_INT(8, displayfrequency
, 8, displayfrequency
, __LINE__
);
2269 TEST_DEVMODE_INT(8, icmmethod
, 8, icmmethod
, __LINE__
);
2270 TEST_DEVMODE_INT(8, icmintent
, 8, icmintent
, __LINE__
);
2271 TEST_DEVMODE_INT(8, mediatype
, 8, mediatype
, __LINE__
);
2272 TEST_DEVMODE_INT(8, dithertype
, 8, dithertype
, __LINE__
);
2273 TEST_DEVMODE_INT(8, reserved1
, 8, reserved1
, __LINE__
);
2274 TEST_DEVMODE_INT(8, reserved2
, 8, reserved2
, __LINE__
);
2275 TEST_DEVMODE_INT(8, panningwidth
, 8, panningwidth
, __LINE__
);
2276 TEST_DEVMODE_INT(8, panningheight
, 8, panningheight
, __LINE__
);
2281 static bool call_OpenPrinterEx(struct torture_context
*tctx
,
2282 struct dcerpc_pipe
*p
,
2284 struct spoolss_DeviceMode
*devmode
,
2285 struct policy_handle
*handle
);
2287 static bool test_PrinterInfo_DevModes(struct torture_context
*tctx
,
2288 struct dcerpc_pipe
*p
,
2289 struct policy_handle
*handle
,
2292 union spoolss_PrinterInfo info
;
2293 struct spoolss_DeviceMode
*devmode
;
2294 struct spoolss_DeviceMode
*devmode2
;
2295 struct policy_handle handle_devmode
;
2296 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
2298 /* simply compare level8 and level2 devmode */
2300 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 8, &info
), "");
2302 devmode
= info
.info8
.devmode
;
2304 if (devmode
&& devmode
->size
== 0) {
2306 "devmode of zero size!");
2309 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
2311 devmode2
= info
.info2
.devmode
;
2313 if (devmode2
&& devmode2
->size
== 0) {
2315 "devmode of zero size!");
2318 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2319 "DM level 8 != DM level 2");
2322 /* set devicemode level 8 and see if it persists */
2324 devmode
->copies
= 93;
2325 devmode
->formname
= talloc_strdup(tctx
, "Legal");
2327 torture_assert(tctx
, test_devmode_set_level(tctx
, b
, handle
, 8, devmode
), "");
2329 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 8, &info
), "");
2331 devmode2
= info
.info8
.devmode
;
2333 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2334 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2336 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
2338 devmode2
= info
.info2
.devmode
;
2340 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2341 "modified DM level 8 != DM level 2");
2344 /* set devicemode level 2 and see if it persists */
2346 devmode
->copies
= 39;
2347 devmode
->formname
= talloc_strdup(tctx
, "Executive");
2349 torture_assert(tctx
, test_devmode_set_level(tctx
, b
, handle
, 2, devmode
), "");
2351 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 8, &info
), "");
2353 devmode2
= info
.info8
.devmode
;
2355 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2356 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2358 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
2360 devmode2
= info
.info2
.devmode
;
2362 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2363 "modified DM level 8 != DM level 2");
2366 /* check every single bit in public part of devicemode */
2368 torture_assert(tctx
, test_devicemode_full(tctx
, b
, handle
),
2369 "failed to set every single devicemode component");
2372 /* change formname upon open and see if it persists in getprinter calls */
2374 devmode
->formname
= talloc_strdup(tctx
, "A4");
2375 devmode
->copies
= 42;
2377 torture_assert(tctx
, call_OpenPrinterEx(tctx
, p
, name
, devmode
, &handle_devmode
),
2378 "failed to open printer handle");
2380 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, &handle_devmode
, 8, &info
), "");
2382 devmode2
= info
.info8
.devmode
;
2384 if (strequal(devmode
->devicename
, devmode2
->devicename
)) {
2385 torture_warning(tctx
, "devicenames are the same\n");
2387 torture_comment(tctx
, "devicename passed in for open: %s\n", devmode
->devicename
);
2388 torture_comment(tctx
, "devicename after level 8 get: %s\n", devmode2
->devicename
);
2391 if (strequal(devmode
->formname
, devmode2
->formname
)) {
2392 torture_warning(tctx
, "formname are the same\n");
2394 torture_comment(tctx
, "formname passed in for open: %s\n", devmode
->formname
);
2395 torture_comment(tctx
, "formname after level 8 get: %s\n", devmode2
->formname
);
2398 if (devmode
->copies
== devmode2
->copies
) {
2399 torture_warning(tctx
, "copies are the same\n");
2401 torture_comment(tctx
, "copies passed in for open: %d\n", devmode
->copies
);
2402 torture_comment(tctx
, "copies after level 8 get: %d\n", devmode2
->copies
);
2405 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, &handle_devmode
, 2, &info
), "");
2407 devmode2
= info
.info2
.devmode
;
2409 if (strequal(devmode
->devicename
, devmode2
->devicename
)) {
2410 torture_warning(tctx
, "devicenames are the same\n");
2412 torture_comment(tctx
, "devicename passed in for open: %s\n", devmode
->devicename
);
2413 torture_comment(tctx
, "devicename after level 2 get: %s\n", devmode2
->devicename
);
2416 if (strequal(devmode
->formname
, devmode2
->formname
)) {
2417 torture_warning(tctx
, "formname is the same\n");
2419 torture_comment(tctx
, "formname passed in for open: %s\n", devmode
->formname
);
2420 torture_comment(tctx
, "formname after level 2 get: %s\n", devmode2
->formname
);
2423 if (devmode
->copies
== devmode2
->copies
) {
2424 torture_warning(tctx
, "copies are the same\n");
2426 torture_comment(tctx
, "copies passed in for open: %d\n", devmode
->copies
);
2427 torture_comment(tctx
, "copies after level 2 get: %d\n", devmode2
->copies
);
2430 test_ClosePrinter(tctx
, b
, &handle_devmode
);
2436 * wrapper call that saves original devmode, runs tests, and restores devmode
2439 static bool test_PrinterInfo_DevMode(struct torture_context
*tctx
,
2440 struct dcerpc_pipe
*p
,
2441 struct policy_handle
*handle
,
2443 struct spoolss_DeviceMode
*addprinter_devmode
)
2445 union spoolss_PrinterInfo info
;
2446 struct spoolss_DeviceMode
*devmode
;
2448 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
2450 torture_comment(tctx
, "Testing Printer Devicemodes\n");
2452 /* save original devmode */
2454 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 8, &info
),
2455 "failed to get initial global devicemode");
2457 devmode
= info
.info8
.devmode
;
2459 if (devmode
&& devmode
->size
== 0) {
2461 "devmode of zero size!");
2464 if (addprinter_devmode
) {
2465 if (!test_devicemode_equal(tctx
, devmode
, addprinter_devmode
)) {
2466 torture_warning(tctx
, "current global DM is != DM provided in addprinter");
2472 ret
= test_PrinterInfo_DevModes(tctx
, p
, handle
, name
);
2474 /* restore original devmode */
2476 torture_assert(tctx
, test_devmode_set_level(tctx
, b
, handle
, 8, devmode
),
2477 "failed to restore initial global device mode");
2479 torture_comment(tctx
, "Printer Devicemodes test %s\n\n",
2480 ret
? "succeeded" : "failed");
2486 bool test_ClosePrinter(struct torture_context
*tctx
,
2487 struct dcerpc_binding_handle
*b
,
2488 struct policy_handle
*handle
)
2491 struct spoolss_ClosePrinter r
;
2493 r
.in
.handle
= handle
;
2494 r
.out
.handle
= handle
;
2496 torture_comment(tctx
, "Testing ClosePrinter\n");
2498 status
= dcerpc_spoolss_ClosePrinter_r(b
, tctx
, &r
);
2499 torture_assert_ntstatus_ok(tctx
, status
, "ClosePrinter failed");
2500 torture_assert_werr_ok(tctx
, r
.out
.result
, "ClosePrinter failed");
2505 static bool test_GetForm_args(struct torture_context
*tctx
,
2506 struct dcerpc_binding_handle
*b
,
2507 struct policy_handle
*handle
,
2508 const char *form_name
,
2510 union spoolss_FormInfo
*info_p
)
2513 struct spoolss_GetForm r
;
2516 r
.in
.handle
= handle
;
2517 r
.in
.form_name
= form_name
;
2521 r
.out
.needed
= &needed
;
2523 torture_comment(tctx
, "Testing GetForm(%s) level %d\n", form_name
, r
.in
.level
);
2525 status
= dcerpc_spoolss_GetForm_r(b
, tctx
, &r
);
2526 torture_assert_ntstatus_ok(tctx
, status
, "GetForm failed");
2528 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2529 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
2530 r
.in
.buffer
= &blob
;
2531 r
.in
.offered
= needed
;
2532 status
= dcerpc_spoolss_GetForm_r(b
, tctx
, &r
);
2533 torture_assert_ntstatus_ok(tctx
, status
, "GetForm failed");
2535 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetForm failed");
2537 torture_assert(tctx
, r
.out
.info
, "No form info returned");
2540 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetForm failed");
2542 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo
, r
.out
.info
, r
.in
.level
, needed
, 4);
2545 *info_p
= *r
.out
.info
;
2551 static bool test_GetForm(struct torture_context
*tctx
,
2552 struct dcerpc_binding_handle
*b
,
2553 struct policy_handle
*handle
,
2554 const char *form_name
,
2557 return test_GetForm_args(tctx
, b
, handle
, form_name
, level
, NULL
);
2560 static bool test_EnumForms(struct torture_context
*tctx
,
2561 struct dcerpc_binding_handle
*b
,
2562 struct policy_handle
*handle
,
2566 union spoolss_FormInfo
**info_p
)
2568 struct spoolss_EnumForms r
;
2571 union spoolss_FormInfo
*info
;
2573 r
.in
.handle
= handle
;
2577 r
.out
.needed
= &needed
;
2578 r
.out
.count
= &count
;
2581 torture_comment(tctx
, "Testing EnumForms level %d\n", r
.in
.level
);
2583 torture_assert_ntstatus_ok(tctx
,
2584 dcerpc_spoolss_EnumForms_r(b
, tctx
, &r
),
2585 "EnumForms failed");
2587 if ((r
.in
.level
== 2) && (W_ERROR_EQUAL(r
.out
.result
, WERR_UNKNOWN_LEVEL
))) {
2588 torture_skip(tctx
, "EnumForms level 2 not supported");
2591 if (print_server
&& W_ERROR_EQUAL(r
.out
.result
, WERR_BADFID
)) {
2592 torture_fail(tctx
, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2595 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2596 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
2597 r
.in
.buffer
= &blob
;
2598 r
.in
.offered
= needed
;
2600 torture_assert_ntstatus_ok(tctx
,
2601 dcerpc_spoolss_EnumForms_r(b
, tctx
, &r
),
2602 "EnumForms failed");
2604 torture_assert(tctx
, info
, "No forms returned");
2607 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumForms failed");
2609 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms
, info
, r
.in
.level
, count
, needed
, 4);
2621 static bool test_EnumForms_all(struct torture_context
*tctx
,
2622 struct dcerpc_binding_handle
*b
,
2623 struct policy_handle
*handle
,
2626 uint32_t levels
[] = { 1, 2 };
2629 for (i
=0; i
<ARRAY_SIZE(levels
); i
++) {
2632 union spoolss_FormInfo
*info
= NULL
;
2634 torture_assert(tctx
,
2635 test_EnumForms(tctx
, b
, handle
, print_server
, levels
[i
], &count
, &info
),
2636 "failed to enum forms");
2638 for (j
= 0; j
< count
; j
++) {
2639 if (!print_server
) {
2640 torture_assert(tctx
,
2641 test_GetForm(tctx
, b
, handle
, info
[j
].info1
.form_name
, levels
[i
]),
2642 "failed to get form");
2650 static bool test_EnumForms_find_one(struct torture_context
*tctx
,
2651 struct dcerpc_binding_handle
*b
,
2652 struct policy_handle
*handle
,
2654 const char *form_name
)
2656 union spoolss_FormInfo
*info
;
2661 torture_assert(tctx
,
2662 test_EnumForms(tctx
, b
, handle
, print_server
, 1, &count
, &info
),
2663 "failed to enumerate forms");
2665 for (i
=0; i
<count
; i
++) {
2666 if (strequal(form_name
, info
[i
].info1
.form_name
)) {
2675 static bool test_DeleteForm(struct torture_context
*tctx
,
2676 struct dcerpc_binding_handle
*b
,
2677 struct policy_handle
*handle
,
2678 const char *form_name
,
2679 WERROR expected_result
)
2681 struct spoolss_DeleteForm r
;
2683 r
.in
.handle
= handle
;
2684 r
.in
.form_name
= form_name
;
2686 torture_comment(tctx
, "Testing DeleteForm(%s)\n", form_name
);
2688 torture_assert_ntstatus_ok(tctx
,
2689 dcerpc_spoolss_DeleteForm_r(b
, tctx
, &r
),
2690 "DeleteForm failed");
2691 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
2692 "DeleteForm gave unexpected result");
2693 if (W_ERROR_IS_OK(r
.out
.result
)) {
2694 torture_assert_ntstatus_ok(tctx
,
2695 dcerpc_spoolss_DeleteForm_r(b
, tctx
, &r
),
2696 "2nd DeleteForm failed");
2697 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_FORM_NAME
,
2698 "2nd DeleteForm failed");
2704 static bool test_AddForm(struct torture_context
*tctx
,
2705 struct dcerpc_binding_handle
*b
,
2706 struct policy_handle
*handle
,
2708 union spoolss_AddFormInfo
*info
,
2709 WERROR expected_result
)
2711 struct spoolss_AddForm r
;
2712 struct spoolss_AddFormInfoCtr info_ctr
;
2714 info_ctr
.level
= level
;
2715 info_ctr
.info
= *info
;
2718 torture_skip(tctx
, "only level 1 supported");
2721 r
.in
.handle
= handle
;
2722 r
.in
.info_ctr
= &info_ctr
;
2724 torture_comment(tctx
, "Testing AddForm(%s) level %d, type %d\n",
2725 r
.in
.info_ctr
->info
.info1
->form_name
, level
,
2726 r
.in
.info_ctr
->info
.info1
->flags
);
2728 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_AddForm_r(b
, tctx
, &r
),
2730 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
2731 "AddForm gave unexpected result");
2733 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_AddForm_r(b
, tctx
, &r
),
2734 "2nd AddForm failed");
2735 if (W_ERROR_EQUAL(expected_result
, WERR_INVALID_PARAM
)) {
2736 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
2737 "2nd AddForm gave unexpected result");
2739 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_FILE_EXISTS
,
2740 "2nd AddForm gave unexpected result");
2746 static bool test_SetForm(struct torture_context
*tctx
,
2747 struct dcerpc_binding_handle
*b
,
2748 struct policy_handle
*handle
,
2749 const char *form_name
,
2751 union spoolss_AddFormInfo
*info
)
2753 struct spoolss_SetForm r
;
2754 struct spoolss_AddFormInfoCtr info_ctr
;
2756 info_ctr
.level
= level
;
2757 info_ctr
.info
= *info
;
2759 r
.in
.handle
= handle
;
2760 r
.in
.form_name
= form_name
;
2761 r
.in
.info_ctr
= &info_ctr
;
2763 torture_comment(tctx
, "Testing SetForm(%s) level %d\n",
2766 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetForm_r(b
, tctx
, &r
),
2769 torture_assert_werr_ok(tctx
, r
.out
.result
,
2775 static bool test_GetForm_winreg(struct torture_context
*tctx
,
2776 struct dcerpc_binding_handle
*b
,
2777 struct policy_handle
*handle
,
2778 const char *key_name
,
2779 const char *form_name
,
2780 enum winreg_Type
*w_type
,
2785 static bool test_Forms_args(struct torture_context
*tctx
,
2786 struct dcerpc_binding_handle
*b
,
2787 struct policy_handle
*handle
,
2789 const char *printer_name
,
2790 struct dcerpc_binding_handle
*winreg_handle
,
2791 struct policy_handle
*hive_handle
,
2792 const char *form_name
,
2793 struct spoolss_AddFormInfo1
*info1
,
2794 WERROR expected_add_result
,
2795 WERROR expected_delete_result
)
2797 union spoolss_FormInfo info
;
2798 union spoolss_AddFormInfo add_info
;
2800 enum winreg_Type w_type
;
2805 add_info
.info1
= info1
;
2807 torture_assert(tctx
,
2808 test_AddForm(tctx
, b
, handle
, 1, &add_info
, expected_add_result
),
2809 "failed to add form");
2811 if (winreg_handle
&& hive_handle
&& W_ERROR_IS_OK(expected_add_result
)) {
2813 struct spoolss_FormInfo1 i1
;
2815 torture_assert(tctx
,
2816 test_GetForm_winreg(tctx
, winreg_handle
, hive_handle
, TOP_LEVEL_CONTROL_FORMS_KEY
, form_name
, &w_type
, &w_size
, &w_length
, &w_data
),
2817 "failed to get form via winreg");
2819 i1
.size
.width
= IVAL(w_data
, 0);
2820 i1
.size
.height
= IVAL(w_data
, 4);
2821 i1
.area
.left
= IVAL(w_data
, 8);
2822 i1
.area
.top
= IVAL(w_data
, 12);
2823 i1
.area
.right
= IVAL(w_data
, 16);
2824 i1
.area
.bottom
= IVAL(w_data
, 20);
2825 /* skip index here */
2826 i1
.flags
= IVAL(w_data
, 28);
2828 torture_assert_int_equal(tctx
, w_type
, REG_BINARY
, "unexpected type");
2829 torture_assert_int_equal(tctx
, w_size
, 0x20, "unexpected size");
2830 torture_assert_int_equal(tctx
, w_length
, 0x20, "unexpected length");
2831 torture_assert_int_equal(tctx
, i1
.size
.width
, add_info
.info1
->size
.width
, "width mismatch");
2832 torture_assert_int_equal(tctx
, i1
.size
.height
, add_info
.info1
->size
.height
, "height mismatch");
2833 torture_assert_int_equal(tctx
, i1
.area
.left
, add_info
.info1
->area
.left
, "left mismatch");
2834 torture_assert_int_equal(tctx
, i1
.area
.top
, add_info
.info1
->area
.top
, "top mismatch");
2835 torture_assert_int_equal(tctx
, i1
.area
.right
, add_info
.info1
->area
.right
, "right mismatch");
2836 torture_assert_int_equal(tctx
, i1
.area
.bottom
, add_info
.info1
->area
.bottom
, "bottom mismatch");
2837 torture_assert_int_equal(tctx
, i1
.flags
, add_info
.info1
->flags
, "flags mismatch");
2840 if (!print_server
&& W_ERROR_IS_OK(expected_add_result
)) {
2841 torture_assert(tctx
,
2842 test_GetForm_args(tctx
, b
, handle
, form_name
, 1, &info
),
2843 "failed to get added form");
2845 torture_assert_int_equal(tctx
, info
.info1
.size
.width
, add_info
.info1
->size
.width
, "width mismatch");
2846 torture_assert_int_equal(tctx
, info
.info1
.size
.height
, add_info
.info1
->size
.height
, "height mismatch");
2847 torture_assert_int_equal(tctx
, info
.info1
.area
.left
, add_info
.info1
->area
.left
, "left mismatch");
2848 torture_assert_int_equal(tctx
, info
.info1
.area
.top
, add_info
.info1
->area
.top
, "top mismatch");
2849 torture_assert_int_equal(tctx
, info
.info1
.area
.right
, add_info
.info1
->area
.right
, "right mismatch");
2850 torture_assert_int_equal(tctx
, info
.info1
.area
.bottom
, add_info
.info1
->area
.bottom
, "bottom mismatch");
2851 torture_assert_int_equal(tctx
, info
.info1
.flags
, add_info
.info1
->flags
, "flags mismatch");
2853 if (winreg_handle
&& hive_handle
) {
2855 struct spoolss_FormInfo1 i1
;
2857 i1
.size
.width
= IVAL(w_data
, 0);
2858 i1
.size
.height
= IVAL(w_data
, 4);
2859 i1
.area
.left
= IVAL(w_data
, 8);
2860 i1
.area
.top
= IVAL(w_data
, 12);
2861 i1
.area
.right
= IVAL(w_data
, 16);
2862 i1
.area
.bottom
= IVAL(w_data
, 20);
2863 /* skip index here */
2864 i1
.flags
= IVAL(w_data
, 28);
2866 torture_assert_int_equal(tctx
, i1
.size
.width
, info
.info1
.size
.width
, "width mismatch");
2867 torture_assert_int_equal(tctx
, i1
.size
.height
, info
.info1
.size
.height
, "height mismatch");
2868 torture_assert_int_equal(tctx
, i1
.area
.left
, info
.info1
.area
.left
, "left mismatch");
2869 torture_assert_int_equal(tctx
, i1
.area
.top
, info
.info1
.area
.top
, "top mismatch");
2870 torture_assert_int_equal(tctx
, i1
.area
.right
, info
.info1
.area
.right
, "right mismatch");
2871 torture_assert_int_equal(tctx
, i1
.area
.bottom
, info
.info1
.area
.bottom
, "bottom mismatch");
2872 torture_assert_int_equal(tctx
, i1
.flags
, info
.info1
.flags
, "flags mismatch");
2875 add_info
.info1
->size
.width
= 1234;
2877 torture_assert(tctx
,
2878 test_SetForm(tctx
, b
, handle
, form_name
, 1, &add_info
),
2879 "failed to set form");
2880 torture_assert(tctx
,
2881 test_GetForm_args(tctx
, b
, handle
, form_name
, 1, &info
),
2882 "failed to get setted form");
2884 torture_assert_int_equal(tctx
, info
.info1
.size
.width
, add_info
.info1
->size
.width
, "width mismatch");
2887 if (!W_ERROR_EQUAL(expected_add_result
, WERR_INVALID_PARAM
)) {
2888 torture_assert(tctx
,
2889 test_EnumForms_find_one(tctx
, b
, handle
, print_server
, form_name
),
2890 "Newly added form not found in enum call");
2893 torture_assert(tctx
,
2894 test_DeleteForm(tctx
, b
, handle
, form_name
, expected_delete_result
),
2895 "failed to delete form");
2900 static bool test_Forms(struct torture_context
*tctx
,
2901 struct dcerpc_binding_handle
*b
,
2902 struct policy_handle
*handle
,
2904 const char *printer_name
,
2905 struct dcerpc_binding_handle
*winreg_handle
,
2906 struct policy_handle
*hive_handle
)
2908 const struct spoolss_FormSize size
= {
2912 const struct spoolss_FormArea area
= {
2921 struct spoolss_AddFormInfo1 info1
;
2922 WERROR expected_add_result
;
2923 WERROR expected_delete_result
;
2927 .flags
= SPOOLSS_FORM_USER
,
2928 .form_name
= "testform_user",
2932 .expected_add_result
= WERR_OK
,
2933 .expected_delete_result
= WERR_OK
2936 weird, we can add a builtin form but we can never remove it
2941 .flags = SPOOLSS_FORM_BUILTIN,
2942 .form_name = "testform_builtin",
2946 .expected_add_result = WERR_OK,
2947 .expected_delete_result = WERR_INVALID_PARAM,
2952 .flags
= SPOOLSS_FORM_PRINTER
,
2953 .form_name
= "testform_printer",
2957 .expected_add_result
= WERR_OK
,
2958 .expected_delete_result
= WERR_OK
2962 .flags
= SPOOLSS_FORM_USER
,
2963 .form_name
= "Letter",
2967 .expected_add_result
= WERR_FILE_EXISTS
,
2968 .expected_delete_result
= WERR_INVALID_PARAM
2972 .flags
= SPOOLSS_FORM_BUILTIN
,
2973 .form_name
= "Letter",
2977 .expected_add_result
= WERR_FILE_EXISTS
,
2978 .expected_delete_result
= WERR_INVALID_PARAM
2982 .flags
= SPOOLSS_FORM_PRINTER
,
2983 .form_name
= "Letter",
2987 .expected_add_result
= WERR_FILE_EXISTS
,
2988 .expected_delete_result
= WERR_INVALID_PARAM
2993 .form_name
= "invalid_flags",
2997 .expected_add_result
= WERR_INVALID_PARAM
,
2998 .expected_delete_result
= WERR_INVALID_FORM_NAME
3003 for (i
=0; i
< ARRAY_SIZE(forms
); i
++) {
3004 torture_assert(tctx
,
3005 test_Forms_args(tctx
, b
, handle
, print_server
, printer_name
,
3006 winreg_handle
, hive_handle
,
3007 forms
[i
].info1
.form_name
,
3009 forms
[i
].expected_add_result
,
3010 forms
[i
].expected_delete_result
),
3011 talloc_asprintf(tctx
, "failed to test form '%s'", forms
[i
].info1
.form_name
));
3017 static bool test_EnumPorts_old(struct torture_context
*tctx
,
3020 struct test_spoolss_context
*ctx
=
3021 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
3024 struct spoolss_EnumPorts r
;
3027 union spoolss_PortInfo
*info
;
3028 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
3029 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
3031 r
.in
.servername
= talloc_asprintf(tctx
, "\\\\%s",
3032 dcerpc_server_name(p
));
3036 r
.out
.needed
= &needed
;
3037 r
.out
.count
= &count
;
3040 torture_comment(tctx
, "Testing EnumPorts\n");
3042 status
= dcerpc_spoolss_EnumPorts_r(b
, tctx
, &r
);
3044 torture_assert_ntstatus_ok(tctx
, status
, "EnumPorts failed");
3046 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
3047 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
3048 r
.in
.buffer
= &blob
;
3049 r
.in
.offered
= needed
;
3051 status
= dcerpc_spoolss_EnumPorts_r(b
, tctx
, &r
);
3052 torture_assert_ntstatus_ok(tctx
, status
, "EnumPorts failed");
3053 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
3055 torture_assert(tctx
, info
, "No ports returned");
3058 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
3060 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts
, info
, 2, count
, needed
, 4);
3065 static bool test_AddPort(struct torture_context
*tctx
,
3068 struct test_spoolss_context
*ctx
=
3069 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
3072 struct spoolss_AddPort r
;
3073 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
3074 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
3076 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s",
3077 dcerpc_server_name(p
));
3079 r
.in
.monitor_name
= "foo";
3081 torture_comment(tctx
, "Testing AddPort\n");
3083 status
= dcerpc_spoolss_AddPort_r(b
, tctx
, &r
);
3085 torture_assert_ntstatus_ok(tctx
, status
, "AddPort failed");
3087 /* win2k3 returns WERR_NOT_SUPPORTED */
3091 if (!W_ERROR_IS_OK(r
.out
.result
)) {
3092 printf("AddPort failed - %s\n", win_errstr(r
.out
.result
));
3101 static bool test_GetJob_args(struct torture_context
*tctx
,
3102 struct dcerpc_binding_handle
*b
,
3103 struct policy_handle
*handle
,
3106 union spoolss_JobInfo
*info_p
)
3109 struct spoolss_GetJob r
;
3110 union spoolss_JobInfo info
;
3113 r
.in
.handle
= handle
;
3114 r
.in
.job_id
= job_id
;
3118 r
.out
.needed
= &needed
;
3121 torture_comment(tctx
, "Testing GetJob(%d), level %d\n", job_id
, r
.in
.level
);
3123 status
= dcerpc_spoolss_GetJob_r(b
, tctx
, &r
);
3124 torture_assert_ntstatus_ok(tctx
, status
, "GetJob failed");
3126 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
, "Unexpected return code");
3129 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
3130 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
3131 r
.in
.buffer
= &blob
;
3132 r
.in
.offered
= needed
;
3134 status
= dcerpc_spoolss_GetJob_r(b
, tctx
, &r
);
3135 torture_assert_ntstatus_ok(tctx
, status
, "GetJob failed");
3138 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetJob failed");
3139 torture_assert(tctx
, r
.out
.info
, "No job info returned");
3141 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo
, r
.out
.info
, r
.in
.level
, needed
, 4);
3144 *info_p
= *r
.out
.info
;
3151 static bool test_GetJob(struct torture_context
*tctx
,
3152 struct dcerpc_binding_handle
*b
,
3153 struct policy_handle
*handle
,
3156 uint32_t levels
[] = {0, 1, 2 /* 3, 4 */};
3159 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
3160 torture_assert(tctx
,
3161 test_GetJob_args(tctx
, b
, handle
, job_id
, levels
[i
], NULL
),
3169 static bool test_SetJob(struct torture_context
*tctx
,
3170 struct dcerpc_binding_handle
*b
,
3171 struct policy_handle
*handle
,
3173 struct spoolss_JobInfoContainer
*ctr
,
3174 enum spoolss_JobControl command
)
3177 struct spoolss_SetJob r
;
3179 r
.in
.handle
= handle
;
3180 r
.in
.job_id
= job_id
;
3182 r
.in
.command
= command
;
3185 case SPOOLSS_JOB_CONTROL_PAUSE
:
3186 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id
);
3188 case SPOOLSS_JOB_CONTROL_RESUME
:
3189 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id
);
3191 case SPOOLSS_JOB_CONTROL_CANCEL
:
3192 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id
);
3194 case SPOOLSS_JOB_CONTROL_RESTART
:
3195 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id
);
3197 case SPOOLSS_JOB_CONTROL_DELETE
:
3198 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id
);
3200 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER
:
3201 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id
);
3203 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED
:
3204 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id
);
3206 case SPOOLSS_JOB_CONTROL_RETAIN
:
3207 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id
);
3209 case SPOOLSS_JOB_CONTROL_RELEASE
:
3210 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id
);
3213 torture_comment(tctx
, "Testing SetJob(%d)\n", job_id
);
3217 status
= dcerpc_spoolss_SetJob_r(b
, tctx
, &r
);
3218 torture_assert_ntstatus_ok(tctx
, status
, "SetJob failed");
3219 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetJob failed");
3224 static bool test_AddJob(struct torture_context
*tctx
,
3225 struct dcerpc_binding_handle
*b
,
3226 struct policy_handle
*handle
)
3229 struct spoolss_AddJob r
;
3233 r
.in
.handle
= handle
;
3235 r
.out
.needed
= &needed
;
3236 r
.in
.buffer
= r
.out
.buffer
= NULL
;
3238 torture_comment(tctx
, "Testing AddJob\n");
3240 status
= dcerpc_spoolss_AddJob_r(b
, tctx
, &r
);
3241 torture_assert_ntstatus_ok(tctx
, status
, "AddJob failed");
3242 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
, "AddJob failed");
3246 status
= dcerpc_spoolss_AddJob_r(b
, tctx
, &r
);
3247 torture_assert_ntstatus_ok(tctx
, status
, "AddJob failed");
3248 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
, "AddJob failed");
3254 static bool test_EnumJobs_args(struct torture_context
*tctx
,
3255 struct dcerpc_binding_handle
*b
,
3256 struct policy_handle
*handle
,
3258 WERROR werr_expected
,
3260 union spoolss_JobInfo
**info_p
)
3263 struct spoolss_EnumJobs r
;
3266 union spoolss_JobInfo
*info
;
3268 r
.in
.handle
= handle
;
3270 r
.in
.numjobs
= 0xffffffff;
3274 r
.out
.needed
= &needed
;
3275 r
.out
.count
= &count
;
3278 torture_comment(tctx
, "Testing EnumJobs level %d\n", level
);
3280 status
= dcerpc_spoolss_EnumJobs_r(b
, tctx
, &r
);
3282 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
3284 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
3285 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
3286 r
.in
.buffer
= &blob
;
3287 r
.in
.offered
= needed
;
3289 status
= dcerpc_spoolss_EnumJobs_r(b
, tctx
, &r
);
3291 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
3292 torture_assert_werr_equal(tctx
, r
.out
.result
, werr_expected
,
3294 torture_assert(tctx
, info
, "No jobs returned");
3296 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs
, *r
.out
.info
, r
.in
.level
, count
, needed
, 4);
3299 torture_assert_werr_equal(tctx
, r
.out
.result
, werr_expected
,
3313 static bool test_JobPropertiesEnum(struct torture_context
*tctx
,
3314 struct dcerpc_binding_handle
*b
,
3315 struct policy_handle
*handle
,
3318 struct spoolss_RpcEnumJobNamedProperties r
;
3319 uint32_t pcProperties
= 0;
3320 struct RPC_PrintNamedProperty
*ppProperties
= NULL
;
3322 r
.in
.hPrinter
= handle
;
3323 r
.in
.JobId
= job_id
;
3324 r
.out
.pcProperties
= &pcProperties
;
3325 r
.out
.ppProperties
= &ppProperties
;
3327 torture_comment(tctx
, "Testing RpcEnumJobNamedProperties(%d)\n", job_id
);
3329 torture_assert_ntstatus_ok(tctx
,
3330 dcerpc_spoolss_RpcEnumJobNamedProperties_r(b
, tctx
, &r
),
3331 "spoolss_RpcEnumJobNamedProperties failed");
3332 torture_assert_werr_ok(tctx
, r
.out
.result
,
3333 "spoolss_RpcEnumJobNamedProperties failed");
3338 static bool test_JobPropertySet(struct torture_context
*tctx
,
3339 struct dcerpc_binding_handle
*b
,
3340 struct policy_handle
*handle
,
3342 struct RPC_PrintNamedProperty
*property
)
3344 struct spoolss_RpcSetJobNamedProperty r
;
3346 r
.in
.hPrinter
= handle
;
3347 r
.in
.JobId
= job_id
;
3348 r
.in
.pProperty
= property
;
3350 torture_comment(tctx
, "Testing RpcSetJobNamedProperty(%d) %s - %d\n",
3351 job_id
, property
->propertyName
,
3352 property
->propertyValue
.ePropertyType
);
3354 torture_assert_ntstatus_ok(tctx
,
3355 dcerpc_spoolss_RpcSetJobNamedProperty_r(b
, tctx
, &r
),
3356 "spoolss_RpcSetJobNamedProperty failed");
3357 torture_assert_werr_ok(tctx
, r
.out
.result
,
3358 "spoolss_RpcSetJobNamedProperty failed");
3363 static bool test_JobPropertyGetValue(struct torture_context
*tctx
,
3364 struct dcerpc_binding_handle
*b
,
3365 struct policy_handle
*handle
,
3367 const char *property_name
,
3368 struct RPC_PrintPropertyValue
*value
)
3370 struct spoolss_RpcGetJobNamedPropertyValue r
;
3372 r
.in
.hPrinter
= handle
;
3373 r
.in
.JobId
= job_id
;
3374 r
.in
.pszName
= property_name
;
3375 r
.out
.pValue
= value
;
3377 torture_comment(tctx
, "Testing RpcGetJobNamedPropertyValue(%d) %s\n",
3378 job_id
, property_name
);
3380 torture_assert_ntstatus_ok(tctx
,
3381 dcerpc_spoolss_RpcGetJobNamedPropertyValue_r(b
, tctx
, &r
),
3382 "spoolss_RpcGetJobNamedPropertyValue failed");
3383 torture_assert_werr_ok(tctx
, r
.out
.result
,
3384 "spoolss_RpcGetJobNamedPropertyValue failed");
3389 static bool test_JobPropertyDelete(struct torture_context
*tctx
,
3390 struct dcerpc_binding_handle
*b
,
3391 struct policy_handle
*handle
,
3393 const char *property_name
)
3395 struct spoolss_RpcDeleteJobNamedProperty r
;
3397 r
.in
.hPrinter
= handle
;
3398 r
.in
.JobId
= job_id
;
3399 r
.in
.pszName
= property_name
;
3401 torture_comment(tctx
, "Testing RpcDeleteJobNamedProperty(%d) %s\n",
3402 job_id
, property_name
);
3404 torture_assert_ntstatus_ok(tctx
,
3405 dcerpc_spoolss_RpcDeleteJobNamedProperty_r(b
, tctx
, &r
),
3406 "spoolss_RpcDeleteJobNamedProperty failed");
3407 torture_assert_werr_ok(tctx
, r
.out
.result
,
3408 "spoolss_RpcDeleteJobNamedProperty failed");
3413 static bool test_DoPrintTest_add_one_job_common(struct torture_context
*tctx
,
3414 struct dcerpc_binding_handle
*b
,
3415 struct policy_handle
*handle
,
3416 const char *document_name
,
3417 const char *datatype
,
3421 struct spoolss_StartDocPrinter s
;
3422 struct spoolss_DocumentInfoCtr info_ctr
;
3423 struct spoolss_DocumentInfo1 info1
;
3424 struct spoolss_StartPagePrinter sp
;
3425 struct spoolss_WritePrinter w
;
3426 struct spoolss_EndPagePrinter ep
;
3427 struct spoolss_EndDocPrinter e
;
3429 uint32_t num_written
;
3431 torture_comment(tctx
, "Testing StartDocPrinter\n");
3433 s
.in
.handle
= handle
;
3434 s
.in
.info_ctr
= &info_ctr
;
3435 s
.out
.job_id
= job_id
;
3437 info1
.document_name
= document_name
;
3438 info1
.output_file
= NULL
;
3439 info1
.datatype
= datatype
;
3442 info_ctr
.info
.info1
= &info1
;
3444 status
= dcerpc_spoolss_StartDocPrinter_r(b
, tctx
, &s
);
3445 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_StartDocPrinter failed");
3446 torture_assert_werr_ok(tctx
, s
.out
.result
, "StartDocPrinter failed");
3448 for (i
=1; i
< 4; i
++) {
3449 torture_comment(tctx
, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i
, *job_id
);
3451 sp
.in
.handle
= handle
;
3453 status
= dcerpc_spoolss_StartPagePrinter_r(b
, tctx
, &sp
);
3454 torture_assert_ntstatus_ok(tctx
, status
,
3455 "dcerpc_spoolss_StartPagePrinter failed");
3456 torture_assert_werr_ok(tctx
, sp
.out
.result
, "StartPagePrinter failed");
3458 torture_comment(tctx
, "Testing WritePrinter: Page[%d], JobId[%d]\n", i
, *job_id
);
3460 w
.in
.handle
= handle
;
3461 w
.in
.data
= data_blob_string_const(talloc_asprintf(tctx
,"TortureTestPage: %d\nData\n",i
));
3462 w
.out
.num_written
= &num_written
;
3464 status
= dcerpc_spoolss_WritePrinter_r(b
, tctx
, &w
);
3465 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_WritePrinter failed");
3466 torture_assert_werr_ok(tctx
, w
.out
.result
, "WritePrinter failed");
3468 torture_comment(tctx
, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i
, *job_id
);
3470 ep
.in
.handle
= handle
;
3472 status
= dcerpc_spoolss_EndPagePrinter_r(b
, tctx
, &ep
);
3473 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndPagePrinter failed");
3474 torture_assert_werr_ok(tctx
, ep
.out
.result
, "EndPagePrinter failed");
3477 torture_comment(tctx
, "Testing EndDocPrinter: JobId[%d]\n", *job_id
);
3479 e
.in
.handle
= handle
;
3481 status
= dcerpc_spoolss_EndDocPrinter_r(b
, tctx
, &e
);
3482 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndDocPrinter failed");
3483 torture_assert_werr_ok(tctx
, e
.out
.result
, "EndDocPrinter failed");
3488 static bool test_DoPrintTest_add_one_job(struct torture_context
*tctx
,
3489 struct dcerpc_binding_handle
*b
,
3490 struct policy_handle
*handle
,
3491 const char *document_name
,
3494 test_DoPrintTest_add_one_job_common(tctx
, b
, handle
, document_name
, "RAW", job_id
);
3499 static bool test_DoPrintTest_add_one_job_v4(struct torture_context
*tctx
,
3500 struct dcerpc_binding_handle
*b
,
3501 struct policy_handle
*handle
,
3502 const char *document_name
,
3505 test_DoPrintTest_add_one_job_common(tctx
, b
, handle
, document_name
, "XPS_PASS", job_id
);
3511 static bool test_DoPrintTest_check_jobs(struct torture_context
*tctx
,
3512 struct dcerpc_binding_handle
*b
,
3513 struct policy_handle
*handle
,
3518 union spoolss_JobInfo
*info
= NULL
;
3521 torture_assert(tctx
,
3522 test_AddJob(tctx
, b
, handle
),
3525 torture_assert(tctx
,
3526 test_EnumJobs_args(tctx
, b
, handle
, 1, WERR_OK
, &count
, &info
),
3527 "EnumJobs level 1 failed");
3529 torture_assert_int_equal(tctx
, count
, num_jobs
, "unexpected number of jobs in queue");
3531 for (i
=0; i
< num_jobs
; i
++) {
3532 union spoolss_JobInfo ginfo
;
3533 const char *document_name
;
3534 const char *new_document_name
= "any_other_docname";
3535 struct spoolss_JobInfoContainer ctr
;
3536 struct spoolss_SetJobInfo1 info1
;
3538 torture_assert_int_equal(tctx
, info
[i
].info1
.job_id
, job_ids
[i
], "job id mismatch");
3540 torture_assert(tctx
,
3541 test_GetJob_args(tctx
, b
, handle
, info
[i
].info1
.job_id
, 1, &ginfo
),
3542 "failed to call test_GetJob");
3544 torture_assert_int_equal(tctx
, ginfo
.info1
.job_id
, info
[i
].info1
.job_id
, "job id mismatch");
3546 document_name
= ginfo
.info1
.document_name
;
3548 info1
.job_id
= ginfo
.info1
.job_id
;
3549 info1
.printer_name
= ginfo
.info1
.printer_name
;
3550 info1
.server_name
= ginfo
.info1
.server_name
;
3551 info1
.user_name
= ginfo
.info1
.user_name
;
3552 info1
.document_name
= new_document_name
;
3553 info1
.data_type
= ginfo
.info1
.data_type
;
3554 info1
.text_status
= ginfo
.info1
.text_status
;
3555 info1
.status
= ginfo
.info1
.status
;
3556 info1
.priority
= ginfo
.info1
.priority
;
3557 info1
.position
= ginfo
.info1
.position
;
3558 info1
.total_pages
= ginfo
.info1
.total_pages
;
3559 info1
.pages_printed
= ginfo
.info1
.pages_printed
;
3560 info1
.submitted
= ginfo
.info1
.submitted
;
3563 ctr
.info
.info1
= &info1
;
3565 torture_assert(tctx
,
3566 test_SetJob(tctx
, b
, handle
, info
[i
].info1
.job_id
, &ctr
, 0),
3567 "failed to call test_SetJob level 1");
3569 torture_assert(tctx
,
3570 test_GetJob_args(tctx
, b
, handle
, info
[i
].info1
.job_id
, 1, &ginfo
),
3571 "failed to call test_GetJob");
3573 if (strequal(ginfo
.info1
.document_name
, document_name
)) {
3574 torture_warning(tctx
,
3575 "document_name did *NOT* change from '%s' to '%s'\n",
3576 document_name
, new_document_name
);
3580 for (i
=0; i
< num_jobs
; i
++) {
3581 if (!test_SetJob(tctx
, b
, handle
, info
[i
].info1
.job_id
, NULL
, SPOOLSS_JOB_CONTROL_PAUSE
)) {
3582 torture_warning(tctx
, "failed to pause printjob\n");
3584 if (!test_SetJob(tctx
, b
, handle
, info
[i
].info1
.job_id
, NULL
, SPOOLSS_JOB_CONTROL_RESUME
)) {
3585 torture_warning(tctx
, "failed to resume printjob\n");
3592 static bool test_DoPrintTest(struct torture_context
*tctx
,
3593 struct dcerpc_binding_handle
*b
,
3594 struct policy_handle
*handle
)
3597 uint32_t num_jobs
= 8;
3601 torture_comment(tctx
, "Testing real print operations\n");
3603 job_ids
= talloc_zero_array(tctx
, uint32_t, num_jobs
);
3605 for (i
=0; i
< num_jobs
; i
++) {
3606 ret
&= test_DoPrintTest_add_one_job(tctx
, b
, handle
, "TorturePrintJob", &job_ids
[i
]);
3609 for (i
=0; i
< num_jobs
; i
++) {
3610 ret
&= test_SetJob(tctx
, b
, handle
, job_ids
[i
], NULL
, SPOOLSS_JOB_CONTROL_DELETE
);
3613 for (i
=0; i
< num_jobs
; i
++) {
3614 ret
&= test_DoPrintTest_add_one_job_v4(tctx
, b
, handle
, "TorturePrintJob v4", &job_ids
[i
]);
3617 for (i
=0; i
< num_jobs
; i
++) {
3618 ret
&= test_SetJob(tctx
, b
, handle
, job_ids
[i
], NULL
, SPOOLSS_JOB_CONTROL_DELETE
);
3622 torture_comment(tctx
, "real print operations test succeeded\n\n");
3628 static bool test_DoPrintTest_extended(struct torture_context
*tctx
,
3629 struct dcerpc_binding_handle
*b
,
3630 struct policy_handle
*handle
)
3633 uint32_t num_jobs
= 8;
3636 torture_comment(tctx
, "Testing real print operations (extended)\n");
3638 job_ids
= talloc_zero_array(tctx
, uint32_t, num_jobs
);
3640 for (i
=0; i
< num_jobs
; i
++) {
3641 ret
&= test_DoPrintTest_add_one_job(tctx
, b
, handle
, "TorturePrintJob", &job_ids
[i
]);
3644 ret
&= test_DoPrintTest_check_jobs(tctx
, b
, handle
, num_jobs
, job_ids
);
3646 for (i
=0; i
< num_jobs
; i
++) {
3647 ret
&= test_SetJob(tctx
, b
, handle
, job_ids
[i
], NULL
, SPOOLSS_JOB_CONTROL_DELETE
);
3651 torture_comment(tctx
, "real print operations (extended) test succeeded\n\n");
3657 static bool test_JobPrintProperties_equal(struct torture_context
*tctx
,
3658 struct RPC_PrintPropertyValue
*got
,
3659 struct RPC_PrintNamedProperty
*exp
)
3661 torture_assert_int_equal(tctx
,
3663 exp
->propertyValue
.ePropertyType
,
3666 switch (exp
->propertyValue
.ePropertyType
) {
3667 case kRpcPropertyTypeString
:
3668 torture_assert_str_equal(tctx
,
3669 got
->value
.propertyString
,
3670 exp
->propertyValue
.value
.propertyString
,
3673 case kRpcPropertyTypeInt32
:
3674 torture_assert_int_equal(tctx
,
3675 got
->value
.propertyInt32
,
3676 exp
->propertyValue
.value
.propertyInt32
,
3679 case kRpcPropertyTypeInt64
:
3680 torture_assert_u64_equal(tctx
,
3681 got
->value
.propertyInt64
,
3682 exp
->propertyValue
.value
.propertyInt64
,
3685 case kRpcPropertyTypeByte
:
3686 torture_assert_int_equal(tctx
,
3687 got
->value
.propertyByte
,
3688 exp
->propertyValue
.value
.propertyByte
,
3691 case kRpcPropertyTypeBuffer
:
3692 torture_assert_int_equal(tctx
,
3693 got
->value
.propertyBlob
.cbBuf
,
3694 exp
->propertyValue
.value
.propertyBlob
.cbBuf
,
3695 "propertyBlob.cbBuf");
3696 torture_assert_mem_equal(tctx
,
3697 got
->value
.propertyBlob
.pBuf
,
3698 exp
->propertyValue
.value
.propertyBlob
.pBuf
,
3699 exp
->propertyValue
.value
.propertyBlob
.cbBuf
,
3700 "propertyBlob.pBuf");
3709 static bool test_JobPrintProperties(struct torture_context
*tctx
,
3710 struct dcerpc_binding_handle
*b
,
3711 struct policy_handle
*handle
,
3714 struct RPC_PrintNamedProperty in
;
3715 struct RPC_PrintPropertyValue out
;
3717 DATA_BLOB blob
= data_blob_string_const("blob");
3719 const char *property_name
;
3720 enum RPC_EPrintPropertyType type
;
3721 union RPC_PrintPropertyValueUnion value
;
3722 WERROR expected_result
;
3725 .property_name
= "torture_property_string",
3726 .type
= kRpcPropertyTypeString
,
3727 .value
.propertyString
= "torture_property_value_string",
3729 .property_name
= "torture_property_int32",
3730 .type
= kRpcPropertyTypeInt32
,
3731 .value
.propertyInt32
= 42,
3733 .property_name
= "torture_property_int64",
3734 .type
= kRpcPropertyTypeInt64
,
3735 .value
.propertyInt64
= 0xaffe,
3737 .property_name
= "torture_property_byte",
3738 .type
= kRpcPropertyTypeByte
,
3739 .value
.propertyByte
= 0xab,
3741 .property_name
= "torture_property_buffer",
3742 .type
= kRpcPropertyTypeBuffer
,
3743 .value
.propertyBlob
.cbBuf
= blob
.length
,
3744 .value
.propertyBlob
.pBuf
= blob
.data
,
3748 torture_assert(tctx
,
3749 test_JobPropertiesEnum(tctx
, b
, handle
, job_id
),
3750 "failed to enum properties");
3752 for (i
=0; i
<ARRAY_SIZE(tests
); i
++) {
3754 in
.propertyName
= tests
[i
].property_name
;
3755 in
.propertyValue
.ePropertyType
= tests
[i
].type
;
3756 in
.propertyValue
.value
= tests
[i
].value
;
3758 torture_assert(tctx
,
3759 test_JobPropertySet(tctx
, b
, handle
, job_id
, &in
),
3760 "failed to set property");
3762 torture_assert(tctx
,
3763 test_JobPropertyGetValue(tctx
, b
, handle
, job_id
, in
.propertyName
, &out
),
3764 "failed to get property");
3766 torture_assert(tctx
,
3767 test_JobPrintProperties_equal(tctx
, &out
, &in
),
3768 "property unequal");
3770 torture_assert(tctx
,
3771 test_JobPropertiesEnum(tctx
, b
, handle
, job_id
),
3772 "failed to enum properties");
3774 torture_assert(tctx
,
3775 test_JobPropertyDelete(tctx
, b
, handle
, job_id
, in
.propertyName
),
3776 "failed to delete job property");
3779 torture_assert(tctx
,
3780 test_JobPropertiesEnum(tctx
, b
, handle
, job_id
),
3781 "failed to enum properties");
3786 static bool test_DoPrintTest_properties(struct torture_context
*tctx
,
3787 struct dcerpc_binding_handle
*b
,
3788 struct policy_handle
*handle
)
3790 uint32_t num_jobs
= 8;
3793 torture_comment(tctx
, "Testing real print operations (properties)\n");
3795 job_ids
= talloc_zero_array(tctx
, uint32_t, num_jobs
);
3797 for (i
=0; i
< num_jobs
; i
++) {
3798 torture_assert(tctx
,
3799 test_DoPrintTest_add_one_job(tctx
, b
, handle
, "TorturePrintJob", &job_ids
[i
]),
3800 "failed to create print job");
3803 for (i
=0; i
< num_jobs
; i
++) {
3804 torture_assert(tctx
,
3805 test_JobPrintProperties(tctx
, b
, handle
, job_ids
[i
]),
3806 "failed to test job properties");
3810 for (i
=0; i
< num_jobs
; i
++) {
3811 torture_assert(tctx
,
3812 test_SetJob(tctx
, b
, handle
, job_ids
[i
], NULL
, SPOOLSS_JOB_CONTROL_DELETE
),
3813 "failed to delete printjob");
3816 torture_comment(tctx
, "real print operations (properties) test succeeded\n\n");
3821 static bool test_PausePrinter(struct torture_context
*tctx
,
3822 struct dcerpc_binding_handle
*b
,
3823 struct policy_handle
*handle
)
3826 struct spoolss_SetPrinter r
;
3827 struct spoolss_SetPrinterInfoCtr info_ctr
;
3828 struct spoolss_DevmodeContainer devmode_ctr
;
3829 struct sec_desc_buf secdesc_ctr
;
3832 info_ctr
.info
.info0
= NULL
;
3834 ZERO_STRUCT(devmode_ctr
);
3835 ZERO_STRUCT(secdesc_ctr
);
3837 r
.in
.handle
= handle
;
3838 r
.in
.info_ctr
= &info_ctr
;
3839 r
.in
.devmode_ctr
= &devmode_ctr
;
3840 r
.in
.secdesc_ctr
= &secdesc_ctr
;
3841 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
3843 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3845 status
= dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
);
3847 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
3849 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
3854 static bool test_ResumePrinter(struct torture_context
*tctx
,
3855 struct dcerpc_binding_handle
*b
,
3856 struct policy_handle
*handle
)
3859 struct spoolss_SetPrinter r
;
3860 struct spoolss_SetPrinterInfoCtr info_ctr
;
3861 struct spoolss_DevmodeContainer devmode_ctr
;
3862 struct sec_desc_buf secdesc_ctr
;
3865 info_ctr
.info
.info0
= NULL
;
3867 ZERO_STRUCT(devmode_ctr
);
3868 ZERO_STRUCT(secdesc_ctr
);
3870 r
.in
.handle
= handle
;
3871 r
.in
.info_ctr
= &info_ctr
;
3872 r
.in
.devmode_ctr
= &devmode_ctr
;
3873 r
.in
.secdesc_ctr
= &secdesc_ctr
;
3874 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
3876 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3878 status
= dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
);
3880 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
3882 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
3887 static bool test_printer_purge(struct torture_context
*tctx
,
3888 struct dcerpc_binding_handle
*b
,
3889 struct policy_handle
*handle
)
3892 struct spoolss_SetPrinter r
;
3893 struct spoolss_SetPrinterInfoCtr info_ctr
;
3894 struct spoolss_DevmodeContainer devmode_ctr
;
3895 struct sec_desc_buf secdesc_ctr
;
3898 info_ctr
.info
.info0
= NULL
;
3900 ZERO_STRUCT(devmode_ctr
);
3901 ZERO_STRUCT(secdesc_ctr
);
3903 r
.in
.handle
= handle
;
3904 r
.in
.info_ctr
= &info_ctr
;
3905 r
.in
.devmode_ctr
= &devmode_ctr
;
3906 r
.in
.secdesc_ctr
= &secdesc_ctr
;
3907 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_PURGE
;
3909 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PURGE\n");
3911 status
= dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
);
3912 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
3913 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
3918 static bool test_GetPrinterData_checktype(struct torture_context
*tctx
,
3919 struct dcerpc_binding_handle
*b
,
3920 struct policy_handle
*handle
,
3921 const char *value_name
,
3922 enum winreg_Type
*expected_type
,
3923 enum winreg_Type
*type_p
,
3928 struct spoolss_GetPrinterData r
;
3930 enum winreg_Type type
;
3931 union spoolss_PrinterData data
;
3933 r
.in
.handle
= handle
;
3934 r
.in
.value_name
= value_name
;
3936 r
.out
.needed
= &needed
;
3938 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
3940 torture_comment(tctx
, "Testing GetPrinterData(%s)\n", r
.in
.value_name
);
3942 status
= dcerpc_spoolss_GetPrinterData_r(b
, tctx
, &r
);
3943 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
3945 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
3946 if (expected_type
) {
3947 torture_assert_int_equal(tctx
, type
, *expected_type
, "unexpected type");
3949 r
.in
.offered
= needed
;
3950 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
3951 status
= dcerpc_spoolss_GetPrinterData_r(b
, tctx
, &r
);
3952 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
3955 torture_assert_werr_ok(tctx
, r
.out
.result
,
3956 talloc_asprintf(tctx
, "GetPrinterData(%s) failed", r
.in
.value_name
));
3958 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData
, &data
, type
, needed
, 1);
3965 *data_p
= r
.out
.data
;
3975 static bool test_GetPrinterData(struct torture_context
*tctx
,
3976 struct dcerpc_binding_handle
*b
,
3977 struct policy_handle
*handle
,
3978 const char *value_name
,
3979 enum winreg_Type
*type_p
,
3983 return test_GetPrinterData_checktype(tctx
, b
, handle
, value_name
,
3984 NULL
, type_p
, data_p
, needed_p
);
3987 static bool test_GetPrinterDataEx_checktype(struct torture_context
*tctx
,
3988 struct dcerpc_pipe
*p
,
3989 struct policy_handle
*handle
,
3990 const char *key_name
,
3991 const char *value_name
,
3992 enum winreg_Type
*expected_type
,
3993 enum winreg_Type
*type_p
,
3998 struct spoolss_GetPrinterDataEx r
;
3999 enum winreg_Type type
;
4001 union spoolss_PrinterData data
;
4002 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4004 r
.in
.handle
= handle
;
4005 r
.in
.key_name
= key_name
;
4006 r
.in
.value_name
= value_name
;
4009 r
.out
.needed
= &needed
;
4010 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
4012 torture_comment(tctx
, "Testing GetPrinterDataEx(%s - %s)\n",
4013 r
.in
.key_name
, r
.in
.value_name
);
4015 status
= dcerpc_spoolss_GetPrinterDataEx_r(b
, tctx
, &r
);
4016 if (!NT_STATUS_IS_OK(status
)) {
4017 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
4018 torture_skip(tctx
, "GetPrinterDataEx not supported by server\n");
4020 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
4023 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
4024 if (expected_type
) {
4025 torture_assert_int_equal(tctx
, type
, *expected_type
, "unexpected type");
4027 r
.in
.offered
= needed
;
4028 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
4029 status
= dcerpc_spoolss_GetPrinterDataEx_r(b
, tctx
, &r
);
4030 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
4033 torture_assert_werr_ok(tctx
, r
.out
.result
,
4034 talloc_asprintf(tctx
, "GetPrinterDataEx(%s - %s) failed", r
.in
.key_name
, r
.in
.value_name
));
4036 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData
, &data
, type
, needed
, 1);
4043 *data_p
= r
.out
.data
;
4053 static bool test_GetPrinterDataEx(struct torture_context
*tctx
,
4054 struct dcerpc_pipe
*p
,
4055 struct policy_handle
*handle
,
4056 const char *key_name
,
4057 const char *value_name
,
4058 enum winreg_Type
*type_p
,
4062 return test_GetPrinterDataEx_checktype(tctx
, p
, handle
, key_name
, value_name
,
4063 NULL
, type_p
, data_p
, needed_p
);
4066 static bool test_get_environment(struct torture_context
*tctx
,
4067 struct dcerpc_binding_handle
*b
,
4068 struct policy_handle
*handle
,
4069 const char **architecture
)
4072 enum winreg_Type type
;
4076 torture_assert(tctx
,
4077 test_GetPrinterData(tctx
, b
, handle
, "Architecture", &type
, &data
, &needed
),
4078 "failed to get Architecture");
4080 torture_assert_int_equal(tctx
, type
, REG_SZ
, "unexpected type");
4082 blob
= data_blob_const(data
, needed
);
4083 *architecture
= reg_val_data_string(tctx
, REG_SZ
, blob
);
4088 static bool test_GetPrinterData_list(struct torture_context
*tctx
,
4091 struct test_spoolss_context
*ctx
=
4092 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
4093 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
4094 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4095 const char *list
[] = {
4099 /* "NetPopup", not on w2k8 */
4100 /* "NetPopupToComputer", not on w2k8 */
4103 "DefaultSpoolDirectory",
4107 /* "OSVersionEx", not on s3 */
4112 for (i
=0; i
< ARRAY_SIZE(list
); i
++) {
4113 enum winreg_Type type
, type_ex
;
4114 uint8_t *data
, *data_ex
;
4115 uint32_t needed
, needed_ex
;
4117 torture_assert(tctx
, test_GetPrinterData(tctx
, b
, &ctx
->server_handle
, list
[i
], &type
, &data
, &needed
),
4118 talloc_asprintf(tctx
, "GetPrinterData failed on %s\n", list
[i
]));
4119 torture_assert(tctx
, test_GetPrinterDataEx(tctx
, p
, &ctx
->server_handle
, "random_string", list
[i
], &type_ex
, &data_ex
, &needed_ex
),
4120 talloc_asprintf(tctx
, "GetPrinterDataEx failed on %s\n", list
[i
]));
4121 torture_assert_int_equal(tctx
, type
, type_ex
, "type mismatch");
4122 torture_assert_int_equal(tctx
, needed
, needed_ex
, "needed mismatch");
4123 torture_assert_mem_equal(tctx
, data
, data_ex
, needed
, "data mismatch");
4129 static bool test_EnumPrinterData(struct torture_context
*tctx
,
4130 struct dcerpc_pipe
*p
,
4131 struct policy_handle
*handle
,
4132 uint32_t enum_index
,
4133 uint32_t value_offered
,
4134 uint32_t data_offered
,
4135 enum winreg_Type
*type_p
,
4136 uint32_t *value_needed_p
,
4137 uint32_t *data_needed_p
,
4138 const char **value_name_p
,
4142 struct spoolss_EnumPrinterData r
;
4143 uint32_t data_needed
;
4144 uint32_t value_needed
;
4145 enum winreg_Type type
;
4146 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4148 r
.in
.handle
= handle
;
4149 r
.in
.enum_index
= enum_index
;
4150 r
.in
.value_offered
= value_offered
;
4151 r
.in
.data_offered
= data_offered
;
4152 r
.out
.data_needed
= &data_needed
;
4153 r
.out
.value_needed
= &value_needed
;
4155 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.data_offered
);
4156 r
.out
.value_name
= talloc_zero_array(tctx
, const char, r
.in
.value_offered
);
4158 torture_comment(tctx
, "Testing EnumPrinterData(%d)\n", enum_index
);
4160 torture_assert_ntstatus_ok(tctx
,
4161 dcerpc_spoolss_EnumPrinterData_r(b
, tctx
, &r
),
4162 "EnumPrinterData failed");
4167 if (value_needed_p
) {
4168 *value_needed_p
= value_needed
;
4170 if (data_needed_p
) {
4171 *data_needed_p
= data_needed
;
4174 *value_name_p
= r
.out
.value_name
;
4177 *data_p
= r
.out
.data
;
4180 *result_p
= r
.out
.result
;
4187 static bool test_EnumPrinterData_all(struct torture_context
*tctx
,
4188 struct dcerpc_pipe
*p
,
4189 struct policy_handle
*handle
)
4191 uint32_t enum_index
= 0;
4192 enum winreg_Type type
;
4193 uint32_t value_needed
;
4194 uint32_t data_needed
;
4196 const char *value_name
;
4199 torture_comment(tctx
, "Testing EnumPrinterData\n");
4202 torture_assert(tctx
,
4203 test_EnumPrinterData(tctx
, p
, handle
, enum_index
, 0, 0,
4204 &type
, &value_needed
, &data_needed
,
4205 &value_name
, &data
, &result
),
4206 "EnumPrinterData failed");
4208 if (W_ERROR_EQUAL(result
, WERR_NO_MORE_ITEMS
)) {
4212 torture_assert(tctx
,
4213 test_EnumPrinterData(tctx
, p
, handle
, enum_index
, value_needed
, data_needed
,
4214 &type
, &value_needed
, &data_needed
,
4215 &value_name
, &data
, &result
),
4216 "EnumPrinterData failed");
4218 if (W_ERROR_EQUAL(result
, WERR_NO_MORE_ITEMS
)) {
4224 } while (W_ERROR_IS_OK(result
));
4226 torture_comment(tctx
, "EnumPrinterData test succeeded\n");
4231 static bool test_EnumPrinterDataEx(struct torture_context
*tctx
,
4232 struct dcerpc_binding_handle
*b
,
4233 struct policy_handle
*handle
,
4234 const char *key_name
,
4236 struct spoolss_PrinterEnumValues
**info_p
)
4238 struct spoolss_EnumPrinterDataEx r
;
4239 struct spoolss_PrinterEnumValues
*info
;
4243 r
.in
.handle
= handle
;
4244 r
.in
.key_name
= key_name
;
4246 r
.out
.needed
= &needed
;
4247 r
.out
.count
= &count
;
4250 torture_comment(tctx
, "Testing EnumPrinterDataEx(%s)\n", key_name
);
4252 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterDataEx_r(b
, tctx
, &r
),
4253 "EnumPrinterDataEx failed");
4254 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
4255 r
.in
.offered
= needed
;
4256 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterDataEx_r(b
, tctx
, &r
),
4257 "EnumPrinterDataEx failed");
4260 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDataEx failed");
4262 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx
, info
, count
, needed
, 1);
4274 static bool test_SetPrinterData(struct torture_context
*tctx
,
4275 struct dcerpc_binding_handle
*b
,
4276 struct policy_handle
*handle
,
4277 const char *value_name
,
4278 enum winreg_Type type
,
4281 static bool test_DeletePrinterData(struct torture_context
*tctx
,
4282 struct dcerpc_binding_handle
*b
,
4283 struct policy_handle
*handle
,
4284 const char *value_name
);
4286 static bool test_EnumPrinterData_consistency(struct torture_context
*tctx
,
4287 struct dcerpc_pipe
*p
,
4288 struct policy_handle
*handle
)
4291 struct spoolss_PrinterEnumValues
*info
;
4293 uint32_t value_needed
, data_needed
;
4294 uint32_t value_offered
, data_offered
;
4296 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4298 enum winreg_Type type
;
4301 torture_comment(tctx
, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
4303 torture_assert(tctx
, push_reg_sz(tctx
, &blob
, "torture_data1"), "");
4306 torture_assert(tctx
,
4307 test_SetPrinterData(tctx
, b
, handle
, "torture_value1", type
, blob
.data
, blob
.length
),
4308 "SetPrinterData failed");
4310 blob
= data_blob_string_const("torture_data2");
4312 torture_assert(tctx
,
4313 test_SetPrinterData(tctx
, b
, handle
, "torture_value2", REG_BINARY
, blob
.data
, blob
.length
),
4314 "SetPrinterData failed");
4316 blob
= data_blob_talloc(tctx
, NULL
, 4);
4317 SIVAL(blob
.data
, 0, 0x11223344);
4319 torture_assert(tctx
,
4320 test_SetPrinterData(tctx
, b
, handle
, "torture_value3", type
, blob
.data
, blob
.length
),
4321 "SetPrinterData failed");
4323 torture_assert(tctx
,
4324 test_EnumPrinterDataEx(tctx
, b
, handle
, "PrinterDriverData", &count
, &info
),
4325 "failed to call EnumPrinterDataEx");
4327 /* get the max sizes for value and data */
4329 torture_assert(tctx
,
4330 test_EnumPrinterData(tctx
, p
, handle
, 0, 0, 0,
4331 NULL
, &value_needed
, &data_needed
,
4332 NULL
, NULL
, &result
),
4333 "EnumPrinterData failed");
4334 torture_assert_werr_ok(tctx
, result
, "unexpected result");
4336 /* check if the reply from the EnumPrinterData really matches max values */
4338 for (i
=0; i
< count
; i
++) {
4339 if (info
[i
].value_name_len
> value_needed
) {
4341 talloc_asprintf(tctx
,
4342 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
4343 info
[i
].value_name_len
, value_needed
));
4345 if (info
[i
].data_length
> data_needed
) {
4347 talloc_asprintf(tctx
,
4348 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
4349 info
[i
].data_length
, data_needed
));
4353 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
4354 * sort or not sort the replies by value name, we should be able to do
4355 * the following entry comparison */
4357 data_offered
= data_needed
;
4358 value_offered
= value_needed
;
4360 for (i
=0; i
< count
; i
++) {
4362 const char *value_name
;
4365 torture_assert(tctx
,
4366 test_EnumPrinterData(tctx
, p
, handle
, i
, value_offered
, data_offered
,
4367 &type
, &value_needed
, &data_needed
,
4368 &value_name
, &data
, &result
),
4369 "EnumPrinterData failed");
4371 if (i
-1 == count
) {
4372 torture_assert_werr_equal(tctx
, result
, WERR_NO_MORE_ITEMS
,
4373 "unexpected result");
4376 torture_assert_werr_ok(tctx
, result
, "unexpected result");
4379 torture_assert_int_equal(tctx
, type
, info
[i
].type
, "type mismatch");
4380 torture_assert_int_equal(tctx
, value_needed
, info
[i
].value_name_len
, "value name length mismatch");
4381 torture_assert_str_equal(tctx
, value_name
, info
[i
].value_name
, "value name mismatch");
4382 torture_assert_int_equal(tctx
, data_needed
, info
[i
].data_length
, "data length mismatch");
4383 torture_assert_mem_equal(tctx
, data
, info
[i
].data
->data
, info
[i
].data_length
, "data mismatch");
4386 torture_assert(tctx
,
4387 test_DeletePrinterData(tctx
, b
, handle
, "torture_value1"),
4388 "DeletePrinterData failed");
4389 torture_assert(tctx
,
4390 test_DeletePrinterData(tctx
, b
, handle
, "torture_value2"),
4391 "DeletePrinterData failed");
4392 torture_assert(tctx
,
4393 test_DeletePrinterData(tctx
, b
, handle
, "torture_value3"),
4394 "DeletePrinterData failed");
4396 torture_comment(tctx
, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4401 static bool test_DeletePrinterData(struct torture_context
*tctx
,
4402 struct dcerpc_binding_handle
*b
,
4403 struct policy_handle
*handle
,
4404 const char *value_name
)
4407 struct spoolss_DeletePrinterData r
;
4409 r
.in
.handle
= handle
;
4410 r
.in
.value_name
= value_name
;
4412 torture_comment(tctx
, "Testing DeletePrinterData(%s)\n",
4415 status
= dcerpc_spoolss_DeletePrinterData_r(b
, tctx
, &r
);
4417 torture_assert_ntstatus_ok(tctx
, status
, "DeletePrinterData failed");
4418 torture_assert_werr_ok(tctx
, r
.out
.result
, "DeletePrinterData failed");
4423 static bool test_DeletePrinterDataEx(struct torture_context
*tctx
,
4424 struct dcerpc_binding_handle
*b
,
4425 struct policy_handle
*handle
,
4426 const char *key_name
,
4427 const char *value_name
)
4429 struct spoolss_DeletePrinterDataEx r
;
4431 r
.in
.handle
= handle
;
4432 r
.in
.key_name
= key_name
;
4433 r
.in
.value_name
= value_name
;
4435 torture_comment(tctx
, "Testing DeletePrinterDataEx(%s - %s)\n",
4436 r
.in
.key_name
, r
.in
.value_name
);
4438 torture_assert_ntstatus_ok(tctx
,
4439 dcerpc_spoolss_DeletePrinterDataEx_r(b
, tctx
, &r
),
4440 "DeletePrinterDataEx failed");
4441 torture_assert_werr_ok(tctx
, r
.out
.result
,
4442 "DeletePrinterDataEx failed");
4447 static bool test_DeletePrinterKey(struct torture_context
*tctx
,
4448 struct dcerpc_binding_handle
*b
,
4449 struct policy_handle
*handle
,
4450 const char *key_name
)
4452 struct spoolss_DeletePrinterKey r
;
4454 r
.in
.handle
= handle
;
4455 r
.in
.key_name
= key_name
;
4457 torture_comment(tctx
, "Testing DeletePrinterKey(%s)\n", r
.in
.key_name
);
4459 if (strequal(key_name
, "") && !torture_setting_bool(tctx
, "dangerous", false)) {
4460 torture_skip(tctx
, "not wiping out printer registry - enable dangerous tests to use\n");
4464 torture_assert_ntstatus_ok(tctx
,
4465 dcerpc_spoolss_DeletePrinterKey_r(b
, tctx
, &r
),
4466 "DeletePrinterKey failed");
4467 torture_assert_werr_ok(tctx
, r
.out
.result
,
4468 "DeletePrinterKey failed");
4473 static bool test_winreg_OpenHKLM(struct torture_context
*tctx
,
4474 struct dcerpc_binding_handle
*b
,
4475 struct policy_handle
*handle
)
4477 struct winreg_OpenHKLM r
;
4479 r
.in
.system_name
= NULL
;
4480 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4481 r
.out
.handle
= handle
;
4483 torture_comment(tctx
, "Testing winreg_OpenHKLM\n");
4485 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_OpenHKLM_r(b
, tctx
, &r
), "OpenHKLM failed");
4486 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenHKLM failed");
4491 static void init_winreg_String(struct winreg_String
*name
, const char *s
)
4495 name
->name_len
= 2 * (strlen_m(s
) + 1);
4496 name
->name_size
= name
->name_len
;
4499 name
->name_size
= 0;
4503 static bool test_winreg_OpenKey_opts(struct torture_context
*tctx
,
4504 struct dcerpc_binding_handle
*b
,
4505 struct policy_handle
*hive_handle
,
4506 const char *keyname
,
4508 struct policy_handle
*key_handle
)
4510 struct winreg_OpenKey r
;
4512 r
.in
.parent_handle
= hive_handle
;
4513 init_winreg_String(&r
.in
.keyname
, keyname
);
4514 r
.in
.options
= options
;
4515 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4516 r
.out
.handle
= key_handle
;
4518 torture_comment(tctx
, "Testing winreg_OpenKey(%s)\n", keyname
);
4520 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_OpenKey_r(b
, tctx
, &r
), "OpenKey failed");
4521 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenKey failed");
4526 static bool test_winreg_OpenKey(struct torture_context
*tctx
,
4527 struct dcerpc_binding_handle
*b
,
4528 struct policy_handle
*hive_handle
,
4529 const char *keyname
,
4530 struct policy_handle
*key_handle
)
4532 return test_winreg_OpenKey_opts(tctx
, b
, hive_handle
, keyname
,
4533 REG_OPTION_NON_VOLATILE
, key_handle
);
4536 static bool test_winreg_CloseKey(struct torture_context
*tctx
,
4537 struct dcerpc_binding_handle
*b
,
4538 struct policy_handle
*handle
)
4540 struct winreg_CloseKey r
;
4542 r
.in
.handle
= handle
;
4543 r
.out
.handle
= handle
;
4545 torture_comment(tctx
, "Testing winreg_CloseKey\n");
4547 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_CloseKey_r(b
, tctx
, &r
), "CloseKey failed");
4548 torture_assert_werr_ok(tctx
, r
.out
.result
, "CloseKey failed");
4553 bool test_winreg_QueryValue(struct torture_context
*tctx
,
4554 struct dcerpc_binding_handle
*b
,
4555 struct policy_handle
*handle
,
4556 const char *value_name
,
4557 enum winreg_Type
*type_p
,
4558 uint32_t *data_size_p
,
4559 uint32_t *data_length_p
,
4562 struct winreg_QueryValue r
;
4563 enum winreg_Type type
= REG_NONE
;
4564 uint32_t data_size
= 0;
4565 uint32_t data_length
= 0;
4566 struct winreg_String valuename
;
4567 uint8_t *data
= NULL
;
4569 init_winreg_String(&valuename
, value_name
);
4571 data
= talloc_zero_array(tctx
, uint8_t, 0);
4573 r
.in
.handle
= handle
;
4574 r
.in
.value_name
= &valuename
;
4576 r
.in
.data_size
= &data_size
;
4577 r
.in
.data_length
= &data_length
;
4581 r
.out
.data_size
= &data_size
;
4582 r
.out
.data_length
= &data_length
;
4584 torture_comment(tctx
, "Testing winreg_QueryValue(%s)\n", value_name
);
4586 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_QueryValue_r(b
, tctx
, &r
), "QueryValue failed");
4587 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
4588 *r
.in
.data_size
= *r
.out
.data_size
;
4589 data
= talloc_zero_array(tctx
, uint8_t, *r
.in
.data_size
);
4592 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_QueryValue_r(b
, tctx
, &r
), "QueryValue failed");
4594 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryValue failed");
4597 *type_p
= *r
.out
.type
;
4600 *data_size_p
= *r
.out
.data_size
;
4602 if (data_length_p
) {
4603 *data_length_p
= *r
.out
.data_length
;
4606 *data_p
= r
.out
.data
;
4612 static bool test_winreg_query_printerdata(struct torture_context
*tctx
,
4613 struct dcerpc_binding_handle
*b
,
4614 struct policy_handle
*handle
,
4615 const char *printer_name
,
4616 const char *key_name
,
4617 const char *value_name
,
4618 enum winreg_Type
*w_type
,
4623 const char *printer_key
;
4624 struct policy_handle key_handle
;
4626 printer_key
= talloc_asprintf(tctx
, "%s\\%s\\%s",
4627 TOP_LEVEL_PRINT_PRINTERS_KEY
, printer_name
, key_name
);
4629 torture_assert(tctx
,
4630 test_winreg_OpenKey(tctx
, b
, handle
, printer_key
, &key_handle
), "");
4632 torture_assert(tctx
,
4633 test_winreg_QueryValue(tctx
, b
, &key_handle
, value_name
, w_type
, w_size
, w_length
, w_data
), "");
4635 torture_assert(tctx
,
4636 test_winreg_CloseKey(tctx
, b
, &key_handle
), "");
4641 static bool test_GetForm_winreg(struct torture_context
*tctx
,
4642 struct dcerpc_binding_handle
*b
,
4643 struct policy_handle
*handle
,
4644 const char *key_name
,
4645 const char *form_name
,
4646 enum winreg_Type
*w_type
,
4651 struct policy_handle key_handle
;
4653 torture_assert(tctx
,
4654 test_winreg_OpenKey(tctx
, b
, handle
, key_name
, &key_handle
), "");
4656 torture_assert(tctx
,
4657 test_winreg_QueryValue(tctx
, b
, &key_handle
, form_name
, w_type
, w_size
, w_length
, w_data
), "");
4659 torture_assert(tctx
,
4660 test_winreg_CloseKey(tctx
, b
, &key_handle
), "");
4665 static bool test_winreg_symbolic_link(struct torture_context
*tctx
,
4666 struct dcerpc_binding_handle
*b
,
4667 struct policy_handle
*handle
,
4668 const char *symlink_keyname
,
4669 const char *symlink_destination
)
4671 /* check if the first key is a symlink to the second key */
4673 enum winreg_Type w_type
;
4677 struct policy_handle key_handle
;
4681 if (torture_setting_bool(tctx
, "samba3", false)) {
4682 torture_skip(tctx
, "skip winreg symlink test against samba");
4685 torture_assert(tctx
,
4686 test_winreg_OpenKey_opts(tctx
, b
, handle
, symlink_keyname
, REG_OPTION_OPEN_LINK
, &key_handle
),
4687 "failed to open key link");
4689 torture_assert(tctx
,
4690 test_winreg_QueryValue(tctx
, b
, &key_handle
,
4691 "SymbolicLinkValue",
4692 &w_type
, &w_size
, &w_length
, &w_data
),
4693 "failed to query for 'SymbolicLinkValue' attribute");
4695 torture_assert_int_equal(tctx
, w_type
, REG_LINK
, "unexpected type");
4697 blob
= data_blob(w_data
, w_size
);
4698 str
= reg_val_data_string(tctx
, REG_SZ
, blob
);
4700 torture_assert_str_equal(tctx
, str
, symlink_destination
, "unexpected symlink target string");
4702 torture_assert(tctx
,
4703 test_winreg_CloseKey(tctx
, b
, &key_handle
),
4704 "failed to close key link");
4709 static const char *strip_unc(const char *unc
)
4717 if (unc
[0] == '\\' && unc
[1] == '\\') {
4721 name
= strchr(unc
, '\\');
4729 static bool test_GetPrinterInfo_winreg(struct torture_context
*tctx
,
4730 struct dcerpc_binding_handle
*b
,
4731 struct policy_handle
*handle
,
4732 const char *printer_name
,
4733 struct dcerpc_binding_handle
*winreg_handle
,
4734 struct policy_handle
*hive_handle
)
4736 union spoolss_PrinterInfo info
;
4737 const char *keys
[] = {
4738 TOP_LEVEL_CONTROL_PRINTERS_KEY
,
4739 TOP_LEVEL_PRINT_PRINTERS_KEY
4742 const char *printername
, *sharename
;
4744 torture_comment(tctx
, "Testing Printer Info and winreg consistency\n");
4746 torture_assert(tctx
,
4747 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
4748 "failed to get printer info level 2");
4750 printername
= strip_unc(info
.info2
.printername
);
4751 sharename
= strip_unc(info
.info2
.sharename
);
4753 #define test_sz(wname, iname) \
4757 enum winreg_Type w_type;\
4761 torture_assert(tctx,\
4762 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4763 &w_type, &w_size, &w_length, &w_data),\
4764 "failed to query winreg");\
4765 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4766 blob = data_blob(w_data, w_size);\
4767 str = reg_val_data_string(tctx, REG_SZ, blob);\
4768 if (w_size == 2 && iname == NULL) {\
4769 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4771 torture_assert_str_equal(tctx, str, iname,\
4772 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4776 #define test_dword(wname, iname) \
4779 enum winreg_Type w_type;\
4783 torture_assert(tctx,\
4784 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4785 &w_type, &w_size, &w_length, &w_data),\
4786 "failed to query winreg");\
4787 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4788 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4789 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4790 value = IVAL(w_data, 0);\
4791 torture_assert_int_equal(tctx, value, iname,\
4792 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4795 #define test_binary(wname, iname) \
4797 enum winreg_Type w_type;\
4801 torture_assert(tctx,\
4802 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4803 &w_type, &w_size, &w_length, &w_data),\
4804 "failed to query winreg");\
4805 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4806 torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4807 torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4812 #define test_dm(wname, iname) \
4815 struct spoolss_DeviceMode dm;\
4816 enum ndr_err_code ndr_err;\
4817 enum winreg_Type w_type;\
4821 torture_assert(tctx,\
4822 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4823 &w_type, &w_size, &w_length, &w_data),\
4824 "failed to query winreg");\
4825 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4826 blob = data_blob(w_data, w_size);\
4827 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4828 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4829 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4830 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4834 #define test_sd(wname, iname) \
4837 struct security_descriptor sd;\
4838 enum ndr_err_code ndr_err;\
4839 enum winreg_Type w_type;\
4843 torture_assert(tctx,\
4844 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4845 &w_type, &w_size, &w_length, &w_data),\
4846 "failed to query winreg");\
4847 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4848 blob = data_blob(w_data, w_size);\
4849 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4850 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4851 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4852 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4856 #define test_multi_sz(wname, iname) \
4859 const char **array;\
4860 enum winreg_Type w_type;\
4865 torture_assert(tctx,\
4866 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4867 &w_type, &w_size, &w_length, &w_data),\
4868 "failed to query winreg");\
4869 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4870 blob = data_blob(w_data, w_size);\
4871 torture_assert(tctx, \
4872 pull_reg_multi_sz(tctx, &blob, &array),\
4873 "failed to pull multi sz");\
4874 for (i=0; array[i] != NULL; i++) {\
4875 torture_assert_str_equal(tctx, array[i], iname[i],\
4876 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4880 if (!test_winreg_symbolic_link(tctx
, winreg_handle
, hive_handle
,
4881 TOP_LEVEL_CONTROL_PRINTERS_KEY
,
4882 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4884 torture_warning(tctx
, "failed to check for winreg symlink");
4887 for (i
=0; i
< ARRAY_SIZE(keys
); i
++) {
4889 const char *printer_key
;
4890 struct policy_handle key_handle
;
4892 printer_key
= talloc_asprintf(tctx
, "%s\\%s",
4893 keys
[i
], printer_name
);
4895 torture_assert(tctx
,
4896 test_winreg_OpenKey(tctx
, winreg_handle
, hive_handle
, printer_key
, &key_handle
), "");
4898 test_sz("Name", printername
);
4899 test_sz("Share Name", sharename
);
4900 test_sz("Port", info
.info2
.portname
);
4901 test_sz("Printer Driver", info
.info2
.drivername
);
4902 test_sz("Description", info
.info2
.comment
);
4903 test_sz("Location", info
.info2
.location
);
4904 test_sz("Separator File", info
.info2
.sepfile
);
4905 test_sz("Print Processor", info
.info2
.printprocessor
);
4906 test_sz("Datatype", info
.info2
.datatype
);
4907 test_sz("Parameters", info
.info2
.parameters
);
4908 /* winreg: 0, spoolss not */
4909 /* test_dword("Attributes", info.info2.attributes); */
4910 test_dword("Priority", info
.info2
.priority
);
4911 test_dword("Default Priority", info
.info2
.defaultpriority
);
4912 /* winreg: 60, spoolss: 0 */
4913 /* test_dword("StartTime", info.info2.starttime); */
4914 /* test_dword("UntilTime", info.info2.untiltime); */
4915 /* winreg != spoolss */
4916 /* test_dword("Status", info.info2.status); */
4917 test_dm("Default DevMode", info
.info2
.devmode
);
4918 test_sd("Security", info
.info2
.secdesc
);
4920 torture_assert(tctx
,
4921 test_winreg_CloseKey(tctx
, winreg_handle
, &key_handle
), "");
4927 torture_comment(tctx
, "Printer Info and winreg consistency test succeeded\n\n");
4932 static bool test_PrintProcessors(struct torture_context
*tctx
,
4933 struct dcerpc_binding_handle
*b
,
4934 const char *environment
,
4935 struct dcerpc_binding_handle
*winreg_handle
,
4936 struct policy_handle
*hive_handle
)
4938 union spoolss_PrintProcessorInfo
*info
;
4942 torture_comment(tctx
, "Testing Print Processor Info and winreg consistency\n");
4944 torture_assert(tctx
,
4945 test_EnumPrintProcessors_level(tctx
, b
, environment
, 1, &count
, &info
, WERR_OK
),
4946 "failed to enum print processors level 1");
4948 for (i
=0; i
< count
; i
++) {
4950 const char *processor_key
;
4951 struct policy_handle key_handle
;
4953 processor_key
= talloc_asprintf(tctx
, "%s\\%s\\Print Processors\\%s",
4954 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY
,
4956 info
[i
].info1
.print_processor_name
);
4958 torture_assert(tctx
,
4959 test_winreg_OpenKey(tctx
, winreg_handle
, hive_handle
, processor_key
, &key_handle
), "");
4961 /* nothing to check in there so far */
4963 torture_assert(tctx
,
4964 test_winreg_CloseKey(tctx
, winreg_handle
, &key_handle
), "");
4967 torture_comment(tctx
, "Print Processor Info and winreg consistency test succeeded\n\n");
4972 static bool test_GetPrinterDriver2_level(struct torture_context
*tctx
,
4973 struct dcerpc_binding_handle
*b
,
4974 struct policy_handle
*handle
,
4975 const char *driver_name
,
4976 const char *architecture
,
4978 uint32_t client_major_version
,
4979 uint32_t client_minor_version
,
4980 union spoolss_DriverInfo
*info_p
,
4983 static const char *strip_path(const char *path
)
4991 p
= strrchr(path
, '\\');
4999 static const char **strip_paths(const char **path_array
)
5003 if (path_array
== NULL
) {
5007 for (i
=0; path_array
[i
] != NULL
; i
++) {
5008 path_array
[i
] = strip_path(path_array
[i
]);
5014 static const char *driver_winreg_date(TALLOC_CTX
*mem_ctx
, NTTIME nt
)
5020 return talloc_strdup(mem_ctx
, "01/01/1601");
5023 t
= nt_time_to_unix(nt
);
5026 return talloc_asprintf(mem_ctx
, "%02d/%02d/%04d",
5027 tm
->tm_mon
+ 1, tm
->tm_mday
, tm
->tm_year
+ 1900);
5030 static const char *driver_winreg_version(TALLOC_CTX
*mem_ctx
, uint64_t v
)
5032 return talloc_asprintf(mem_ctx
, "%u.%u.%u.%u",
5033 (unsigned)((v
>> 48) & 0xFFFF),
5034 (unsigned)((v
>> 32) & 0xFFFF),
5035 (unsigned)((v
>> 16) & 0xFFFF),
5036 (unsigned)(v
& 0xFFFF));
5039 static bool test_GetDriverInfo_winreg(struct torture_context
*tctx
,
5040 struct dcerpc_binding_handle
*b
,
5041 struct policy_handle
*handle
,
5042 const char *printer_name
,
5043 const char *driver_name
,
5044 const char *environment
,
5045 enum spoolss_DriverOSVersion version
,
5046 struct dcerpc_binding_handle
*winreg_handle
,
5047 struct policy_handle
*hive_handle
,
5048 const char *server_name_slash
)
5050 WERROR result
= WERR_OK
;
5051 union spoolss_DriverInfo info
;
5052 const char *driver_key
;
5053 struct policy_handle key_handle
;
5055 const char *driver_path
;
5056 const char *data_file
;
5057 const char *config_file
;
5058 const char *help_file
;
5059 const char **dependent_files
;
5061 const char *driver_date
;
5062 const char *inbox_driver_date
;
5064 const char *driver_version
;
5065 const char *inbox_driver_version
;
5067 ZERO_STRUCT(key_handle
);
5069 torture_comment(tctx
, "Testing Driver Info and winreg consistency\n");
5071 driver_key
= talloc_asprintf(tctx
, "%s\\%s\\Drivers\\Version-%d\\%s",
5072 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY
,
5077 torture_assert(tctx
,
5078 test_winreg_OpenKey(tctx
, winreg_handle
, hive_handle
, driver_key
, &key_handle
),
5079 "failed to open driver key");
5081 if (torture_setting_bool(tctx
, "samba3", false) ||
5082 torture_setting_bool(tctx
, "w2k3", false)) {
5087 torture_assert(tctx
,
5088 test_GetPrinterDriver2_level(tctx
, b
, handle
, driver_name
, environment
, 8, version
, 0, &info
, &result
),
5089 "failed to get driver info level 8");
5091 torture_assert(tctx
,
5092 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, environment
, 8, driver_name
, &info
),
5093 "failed to get driver info level 8");
5096 if (W_ERROR_EQUAL(result
, WERR_INVALID_LEVEL
)) {
5100 driver_path
= strip_path(info
.info8
.driver_path
);
5101 data_file
= strip_path(info
.info8
.data_file
);
5102 config_file
= strip_path(info
.info8
.config_file
);
5103 help_file
= strip_path(info
.info8
.help_file
);
5104 dependent_files
= strip_paths(info
.info8
.dependent_files
);
5106 driver_date
= driver_winreg_date(tctx
, info
.info8
.driver_date
);
5107 inbox_driver_date
= driver_winreg_date(tctx
, info
.info8
.min_inbox_driver_ver_date
);
5109 driver_version
= driver_winreg_version(tctx
, info
.info8
.driver_version
);
5110 inbox_driver_version
= driver_winreg_version(tctx
, info
.info8
.min_inbox_driver_ver_version
);
5112 test_sz("Configuration File", config_file
);
5113 test_sz("Data File", data_file
);
5114 test_sz("Datatype", info
.info8
.default_datatype
);
5115 test_sz("Driver", driver_path
);
5116 test_sz("DriverDate", driver_date
);
5117 test_sz("DriverVersion", driver_version
);
5118 test_sz("HardwareID", info
.info8
.hardware_id
);
5119 test_sz("Help File", help_file
);
5120 test_sz("InfPath", info
.info8
.inf_path
);
5121 test_sz("Manufacturer", info
.info8
.manufacturer_name
);
5122 test_sz("MinInboxDriverVerDate", inbox_driver_date
);
5123 test_sz("MinInboxDriverVerVersion", inbox_driver_version
);
5124 test_sz("Monitor", info
.info8
.monitor_name
);
5125 test_sz("OEM URL", info
.info8
.manufacturer_url
);
5126 test_sz("Print Processor", info
.info8
.print_processor
);
5127 test_sz("Provider", info
.info8
.provider
);
5128 test_sz("VendorSetup", info
.info8
.vendor_setup
);
5129 test_multi_sz("ColorProfiles", info
.info8
.color_profiles
);
5130 test_multi_sz("Dependent Files", dependent_files
);
5131 test_multi_sz("CoreDependencies", info
.info8
.core_driver_dependencies
);
5132 test_multi_sz("Previous Names", info
.info8
.previous_names
);
5133 /* test_dword("Attributes", ?); */
5134 test_dword("PrinterDriverAttributes", info
.info8
.printer_driver_attributes
);
5135 test_dword("Version", info
.info8
.version
);
5136 /* test_dword("TempDir", ?); */
5141 torture_assert(tctx
,
5142 test_GetPrinterDriver2_level(tctx
, b
, handle
, driver_name
, environment
, 6, version
, 0, &info
, &result
),
5143 "failed to get driver info level 6");
5145 torture_assert(tctx
,
5146 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, environment
, 6, driver_name
, &info
),
5147 "failed to get driver info level 6");
5150 driver_path
= strip_path(info
.info6
.driver_path
);
5151 data_file
= strip_path(info
.info6
.data_file
);
5152 config_file
= strip_path(info
.info6
.config_file
);
5153 help_file
= strip_path(info
.info6
.help_file
);
5154 dependent_files
= strip_paths(info
.info6
.dependent_files
);
5156 driver_date
= driver_winreg_date(tctx
, info
.info6
.driver_date
);
5158 driver_version
= driver_winreg_version(tctx
, info
.info6
.driver_version
);
5160 test_sz("Configuration File", config_file
);
5161 test_sz("Data File", data_file
);
5162 test_sz("Datatype", info
.info6
.default_datatype
);
5163 test_sz("Driver", driver_path
);
5164 if (torture_setting_bool(tctx
, "w2k3", false)) {
5165 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, 8);
5166 push_nttime(blob
.data
, 0, info
.info6
.driver_date
);
5167 test_binary("DriverDate", blob
);
5168 SBVAL(blob
.data
, 0, info
.info6
.driver_version
);
5169 test_binary("DriverVersion", blob
);
5171 test_sz("DriverDate", driver_date
);
5172 test_sz("DriverVersion", driver_version
);
5174 test_sz("HardwareID", info
.info6
.hardware_id
);
5175 test_sz("Help File", help_file
);
5176 test_sz("Manufacturer", info
.info6
.manufacturer_name
);
5177 test_sz("Monitor", info
.info6
.monitor_name
);
5178 test_sz("OEM URL", info
.info6
.manufacturer_url
);
5179 test_sz("Provider", info
.info6
.provider
);
5180 test_multi_sz("Dependent Files", dependent_files
);
5181 test_multi_sz("Previous Names", info
.info6
.previous_names
);
5182 /* test_dword("Attributes", ?); */
5183 test_dword("Version", info
.info6
.version
);
5184 /* test_dword("TempDir", ?); */
5187 torture_assert(tctx
,
5188 test_GetPrinterDriver2_level(tctx
, b
, handle
, driver_name
, environment
, 3, version
, 0, &info
, &result
),
5189 "failed to get driver info level 3");
5191 torture_assert(tctx
,
5192 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, environment
, 3, driver_name
, &info
),
5193 "failed to get driver info level 3");
5196 driver_path
= strip_path(info
.info3
.driver_path
);
5197 data_file
= strip_path(info
.info3
.data_file
);
5198 config_file
= strip_path(info
.info3
.config_file
);
5199 help_file
= strip_path(info
.info3
.help_file
);
5200 dependent_files
= strip_paths(info
.info3
.dependent_files
);
5202 test_sz("Configuration File", config_file
);
5203 test_sz("Data File", data_file
);
5204 test_sz("Datatype", info
.info3
.default_datatype
);
5205 test_sz("Driver", driver_path
);
5206 test_sz("Help File", help_file
);
5207 test_sz("Monitor", info
.info3
.monitor_name
);
5208 test_multi_sz("Dependent Files", dependent_files
);
5209 /* test_dword("Attributes", ?); */
5210 test_dword("Version", info
.info3
.version
);
5211 /* test_dword("TempDir", ?); */
5214 torture_assert(tctx
,
5215 test_winreg_CloseKey(tctx
, winreg_handle
, &key_handle
), "");
5217 torture_comment(tctx
, "Driver Info and winreg consistency test succeeded\n\n");
5225 static bool test_SetPrinterData(struct torture_context
*tctx
,
5226 struct dcerpc_binding_handle
*b
,
5227 struct policy_handle
*handle
,
5228 const char *value_name
,
5229 enum winreg_Type type
,
5233 struct spoolss_SetPrinterData r
;
5235 r
.in
.handle
= handle
;
5236 r
.in
.value_name
= value_name
;
5239 r
.in
.offered
= offered
;
5241 torture_comment(tctx
, "Testing SetPrinterData(%s)\n",
5244 torture_assert_ntstatus_ok(tctx
,
5245 dcerpc_spoolss_SetPrinterData_r(b
, tctx
, &r
),
5246 "SetPrinterData failed");
5247 torture_assert_werr_ok(tctx
, r
.out
.result
,
5248 "SetPrinterData failed");
5253 static bool test_SetPrinterData_matrix(struct torture_context
*tctx
,
5254 struct dcerpc_binding_handle
*b
,
5255 struct policy_handle
*handle
,
5256 const char *printer_name
,
5257 struct dcerpc_binding_handle
*winreg_handle
,
5258 struct policy_handle
*hive_handle
)
5260 const char *values
[] = {
5264 /* FIXME: not working with s3 atm. */
5270 /* FIXME: not working with s3 atm. */
5277 for (i
=0; i
< ARRAY_SIZE(values
); i
++) {
5279 enum winreg_Type type
, expected_type
= REG_SZ
;
5284 torture_assert(tctx
, push_reg_sz(tctx
, &blob
, "dog"), "");
5287 torture_assert(tctx
,
5288 test_SetPrinterData(tctx
, b
, handle
, values
[i
], REG_SZ
, blob
.data
, blob
.length
),
5289 "SetPrinterData failed");
5291 torture_assert(tctx
,
5292 test_GetPrinterData_checktype(tctx
, b
, handle
, values
[i
], &expected_type
, &type
, &data
, &needed
),
5293 "GetPrinterData failed");
5295 torture_assert_int_equal(tctx
, type
, REG_SZ
, "type mismatch");
5296 torture_assert_int_equal(tctx
, needed
, blob
.length
, "size mismatch");
5297 torture_assert_mem_equal(tctx
, data
, blob
.data
, blob
.length
, "buffer mismatch");
5299 if (winreg_handle
&& hive_handle
) {
5301 enum winreg_Type w_type
;
5306 torture_assert(tctx
,
5307 test_winreg_query_printerdata(tctx
, winreg_handle
, hive_handle
,
5308 printer_name
, "PrinterDriverData", values
[i
],
5309 &w_type
, &w_size
, &w_length
, &w_data
), "");
5311 torture_assert_int_equal(tctx
, w_type
, REG_SZ
, "winreg type mismatch");
5312 torture_assert_int_equal(tctx
, w_size
, blob
.length
, "winreg size mismatch");
5313 torture_assert_int_equal(tctx
, w_length
, blob
.length
, "winreg length mismatch");
5314 torture_assert_mem_equal(tctx
, w_data
, blob
.data
, blob
.length
, "winreg buffer mismatch");
5317 torture_assert(tctx
,
5318 test_DeletePrinterData(tctx
, b
, handle
, values
[i
]),
5319 "DeletePrinterData failed");
5326 static bool test_EnumPrinterKey(struct torture_context
*tctx
,
5327 struct dcerpc_binding_handle
*b
,
5328 struct policy_handle
*handle
,
5329 const char *key_name
,
5330 const char ***array
);
5332 static bool test_SetPrinterDataEx(struct torture_context
*tctx
,
5333 struct dcerpc_binding_handle
*b
,
5334 struct policy_handle
*handle
,
5335 const char *key_name
,
5336 const char *value_name
,
5337 enum winreg_Type type
,
5342 struct spoolss_SetPrinterDataEx r
;
5344 r
.in
.handle
= handle
;
5345 r
.in
.key_name
= key_name
;
5346 r
.in
.value_name
= value_name
;
5349 r
.in
.offered
= offered
;
5351 torture_comment(tctx
, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
5352 r
.in
.key_name
, r
.in
.value_name
, str_regtype(r
.in
.type
), r
.in
.offered
);
5354 status
= dcerpc_spoolss_SetPrinterDataEx_r(b
, tctx
, &r
);
5356 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinterDataEx failed");
5357 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinterDataEx failed");
5362 static bool test_SetPrinterDataEx_keys(struct torture_context
*tctx
,
5363 struct dcerpc_pipe
*p
,
5364 struct policy_handle
*handle
)
5366 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5367 const char *value_name
= "dog";
5368 const char *keys
[] = {
5371 "torturedataex_with_subkey\\subkey",
5372 "torturedataex_with_subkey\\subkey:0",
5373 "torturedataex_with_subkey\\subkey:1",
5374 "torturedataex_with_subkey\\subkey\\subsubkey",
5375 "torturedataex_with_subkey\\subkey\\subsubkey:0",
5376 "torturedataex_with_subkey\\subkey\\subsubkey:1",
5383 "torture/data ex/sub",
5386 "torture//data ex/sub",
5387 "torture//data ex//sub",
5391 for (i
=0; i
< ARRAY_SIZE(keys
); i
++) {
5395 enum winreg_Type type
;
5396 DATA_BLOB blob_in
, blob_out
;
5397 const char **subkeys
;
5399 struct spoolss_PrinterEnumValues
*einfo
;
5402 blob_in
= data_blob_talloc(tctx
, NULL
, 42);
5404 generate_random_buffer(blob_in
.data
, blob_in
.length
);
5406 torture_assert(tctx
,
5407 test_SetPrinterDataEx(tctx
, b
, handle
, keys
[i
], value_name
, REG_BINARY
, blob_in
.data
, blob_in
.length
),
5408 "failed to call SetPrinterDataEx");
5410 torture_assert(tctx
,
5411 test_GetPrinterDataEx(tctx
, p
, handle
, keys
[i
], value_name
, &type
, &blob_out
.data
, &needed
),
5412 "failed to call GetPrinterDataEx");
5414 blob_out
.length
= needed
;
5415 torture_assert(tctx
,
5416 test_EnumPrinterDataEx(tctx
, b
, handle
, keys
[i
], &ecount
, &einfo
),
5417 "failed to call EnumPrinterDataEx");
5419 torture_assert_int_equal(tctx
, type
, REG_BINARY
, "type mismatch");
5420 torture_assert_int_equal(tctx
, blob_out
.length
, blob_in
.length
, "size mismatch");
5421 torture_assert_mem_equal(tctx
, blob_out
.data
, blob_in
.data
, blob_in
.length
, "buffer mismatch");
5423 torture_assert_int_equal(tctx
, ecount
, 1, "unexpected enum count");
5424 torture_assert_str_equal(tctx
, einfo
[0].value_name
, value_name
, "value_name mismatch");
5425 torture_assert_int_equal(tctx
, einfo
[0].value_name_len
, strlen_m_term(value_name
)*2, "unexpected value_name_len");
5426 torture_assert_int_equal(tctx
, einfo
[0].type
, REG_BINARY
, "type mismatch");
5427 torture_assert_int_equal(tctx
, einfo
[0].data_length
, blob_in
.length
, "size mismatch");
5428 if (einfo
[0].data_length
> 0) {
5429 torture_assert_mem_equal(tctx
, einfo
[0].data
->data
, blob_in
.data
, blob_in
.length
, "buffer mismatch");
5432 key
= talloc_strdup(tctx
, keys
[i
]);
5434 if (!test_DeletePrinterDataEx(tctx
, b
, handle
, keys
[i
], value_name
)) {
5438 c
= strchr(key
, '\\');
5442 /* we have subkeys */
5446 if (!test_EnumPrinterKey(tctx
, b
, handle
, key
, &subkeys
)) {
5450 for (k
=0; subkeys
&& subkeys
[k
]; k
++) {
5452 const char *current_key
= talloc_asprintf(tctx
, "%s\\%s", key
, subkeys
[k
]);
5454 if (!test_DeletePrinterKey(tctx
, b
, handle
, current_key
)) {
5459 if (!test_DeletePrinterKey(tctx
, b
, handle
, key
)) {
5464 if (!test_DeletePrinterKey(tctx
, b
, handle
, key
)) {
5473 static bool test_SetPrinterDataEx_values(struct torture_context
*tctx
,
5474 struct dcerpc_pipe
*p
,
5475 struct policy_handle
*handle
)
5477 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5478 const char *key
= "torturedataex";
5479 const char *values
[] = {
5489 for (i
=0; i
< ARRAY_SIZE(values
); i
++) {
5491 enum winreg_Type type
;
5492 DATA_BLOB blob_in
, blob_out
;
5494 struct spoolss_PrinterEnumValues
*einfo
;
5497 if (torture_setting_bool(tctx
, "samba3", false)) {
5499 q
= strrchr(values
[i
], ',');
5501 torture_comment(tctx
, "skipping valuename '%s' including ',' character against Samba3\n",
5507 blob_in
= data_blob_talloc(tctx
, NULL
, 42);
5509 generate_random_buffer(blob_in
.data
, blob_in
.length
);
5511 torture_assert(tctx
,
5512 test_SetPrinterDataEx(tctx
, b
, handle
, key
, values
[i
], REG_BINARY
, blob_in
.data
, blob_in
.length
),
5513 "failed to call SetPrinterDataEx");
5515 torture_assert(tctx
,
5516 test_GetPrinterDataEx(tctx
, p
, handle
, key
, values
[i
], &type
, &blob_out
.data
, &needed
),
5517 "failed to call GetPrinterDataEx");
5519 blob_out
.length
= needed
;
5520 torture_assert(tctx
,
5521 test_EnumPrinterDataEx(tctx
, b
, handle
, key
, &ecount
, &einfo
),
5522 "failed to call EnumPrinterDataEx");
5524 torture_assert_int_equal(tctx
, type
, REG_BINARY
, "type mismatch");
5525 torture_assert_int_equal(tctx
, blob_out
.length
, blob_in
.length
, "size mismatch");
5526 torture_assert_mem_equal(tctx
, blob_out
.data
, blob_in
.data
, blob_in
.length
, "buffer mismatch");
5528 torture_assert_int_equal(tctx
, ecount
, 1, "unexpected enum count");
5529 torture_assert_str_equal(tctx
, einfo
[0].value_name
, values
[i
], "value_name mismatch");
5530 torture_assert_int_equal(tctx
, einfo
[0].value_name_len
, strlen_m_term(values
[i
])*2, "unexpected value_name_len");
5531 torture_assert_int_equal(tctx
, einfo
[0].type
, REG_BINARY
, "type mismatch");
5532 torture_assert_int_equal(tctx
, einfo
[0].data_length
, blob_in
.length
, "size mismatch");
5533 if (einfo
[0].data_length
> 0) {
5534 torture_assert_mem_equal(tctx
, einfo
[0].data
->data
, blob_in
.data
, blob_in
.length
, "buffer mismatch");
5537 torture_assert(tctx
,
5538 test_DeletePrinterDataEx(tctx
, b
, handle
, key
, values
[i
]),
5539 "failed to call DeletePrinterDataEx");
5546 static bool test_SetPrinterDataEx_matrix(struct torture_context
*tctx
,
5547 struct dcerpc_pipe
*p
,
5548 struct policy_handle
*handle
,
5549 const char *printername
,
5550 struct dcerpc_binding_handle
*winreg_handle
,
5551 struct policy_handle
*hive_handle
)
5553 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5554 const char *value_name
= "dog";
5555 const char *key_name
= "torturedataex";
5556 enum winreg_Type types
[] = {
5562 const char *str
= "abcdefghi";
5565 for (t
=0; t
< ARRAY_SIZE(types
); t
++) {
5566 for (s
=0; s
< strlen(str
); s
++) {
5568 enum winreg_Type type
;
5569 const char *string
= talloc_strndup(tctx
, str
, s
);
5570 const char *array
[2];
5571 DATA_BLOB blob
= data_blob_string_const(string
);
5574 uint32_t needed
, offered
= 0;
5576 struct spoolss_PrinterEnumValues
*einfo
;
5578 array
[0] = talloc_strdup(tctx
, string
);
5581 if (types
[t
] == REG_DWORD
) {
5588 offered
= blob
.length
;
5591 data
= data_blob_talloc(tctx
, NULL
, 4);
5592 SIVAL(data
.data
, 0, 0x12345678);
5596 torture_assert(tctx
, push_reg_sz(tctx
, &data
, string
), "");
5598 offered
= data
.length
;
5599 /*strlen_m_term(data.string)*2;*/
5602 torture_assert(tctx
, push_reg_multi_sz(tctx
, &data
, array
), "");
5603 type
= REG_MULTI_SZ
;
5604 offered
= data
.length
;
5607 torture_fail(tctx
, talloc_asprintf(tctx
, "type %d untested\n", types
[t
]));
5610 torture_assert(tctx
,
5611 test_SetPrinterDataEx(tctx
, b
, handle
, key_name
, value_name
, types
[t
], data
.data
, offered
),
5612 "failed to call SetPrinterDataEx");
5614 torture_assert(tctx
,
5615 test_GetPrinterDataEx_checktype(tctx
, p
, handle
, key_name
, value_name
, &types
[t
], &type
, &data_out
, &needed
),
5616 "failed to call GetPrinterDataEx");
5618 torture_assert(tctx
,
5619 test_EnumPrinterDataEx(tctx
, b
, handle
, key_name
, &ecount
, &einfo
),
5620 "failed to call EnumPrinterDataEx");
5622 torture_assert_int_equal(tctx
, types
[t
], type
, "type mismatch");
5623 torture_assert_int_equal(tctx
, needed
, offered
, "size mismatch");
5624 torture_assert_mem_equal(tctx
, data_out
, data
.data
, offered
, "buffer mismatch");
5626 torture_assert_int_equal(tctx
, ecount
, 1, "unexpected enum count");
5627 torture_assert_str_equal(tctx
, einfo
[0].value_name
, value_name
, "value_name mismatch");
5628 torture_assert_int_equal(tctx
, einfo
[0].value_name_len
, strlen_m_term(value_name
)*2, "unexpected value_name_len");
5629 torture_assert_int_equal(tctx
, einfo
[0].type
, types
[t
], "type mismatch");
5630 torture_assert_int_equal(tctx
, einfo
[0].data_length
, offered
, "size mismatch");
5631 if (einfo
[0].data_length
> 0) {
5632 torture_assert_mem_equal(tctx
, einfo
[0].data
->data
, data
.data
, offered
, "buffer mismatch");
5635 if (winreg_handle
&& hive_handle
) {
5636 enum winreg_Type w_type
;
5641 torture_assert(tctx
,
5642 test_winreg_query_printerdata(tctx
, winreg_handle
, hive_handle
,
5643 printername
, key_name
, value_name
,
5644 &w_type
, &w_size
, &w_length
, &w_data
), "");
5646 torture_assert_int_equal(tctx
, w_type
, types
[t
], "winreg type mismatch");
5647 torture_assert_int_equal(tctx
, w_size
, offered
, "winreg size mismatch");
5648 torture_assert_int_equal(tctx
, w_length
, offered
, "winreg length mismatch");
5649 torture_assert_mem_equal(tctx
, w_data
, data
.data
, offered
, "winreg buffer mismatch");
5652 torture_assert(tctx
,
5653 test_DeletePrinterDataEx(tctx
, b
, handle
, key_name
, value_name
),
5654 "failed to call DeletePrinterDataEx");
5661 static bool test_PrinterData_winreg(struct torture_context
*tctx
,
5662 struct dcerpc_pipe
*p
,
5663 struct policy_handle
*handle
,
5664 const char *printer_name
)
5666 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5667 struct dcerpc_pipe
*p2
;
5669 struct policy_handle hive_handle
;
5670 struct dcerpc_binding_handle
*b2
;
5672 torture_assert_ntstatus_ok(tctx
,
5673 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
5674 "could not open winreg pipe");
5675 b2
= p2
->binding_handle
;
5677 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
5679 ret
&= test_SetPrinterData_matrix(tctx
, b
, handle
, printer_name
, b2
, &hive_handle
);
5680 ret
&= test_SetPrinterDataEx_matrix(tctx
, p
, handle
, printer_name
, b2
, &hive_handle
);
5682 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
5689 static bool test_Forms_winreg(struct torture_context
*tctx
,
5690 struct dcerpc_binding_handle
*b
,
5691 struct policy_handle
*handle
,
5693 const char *printer_name
)
5695 struct dcerpc_pipe
*p2
;
5697 struct policy_handle hive_handle
;
5698 struct dcerpc_binding_handle
*b2
;
5700 torture_assert_ntstatus_ok(tctx
,
5701 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
5702 "could not open winreg pipe");
5703 b2
= p2
->binding_handle
;
5705 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
5707 ret
= test_Forms(tctx
, b
, handle
, print_server
, printer_name
, b2
, &hive_handle
);
5709 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
5716 static bool test_PrinterInfo_winreg(struct torture_context
*tctx
,
5717 struct dcerpc_pipe
*p
,
5718 struct policy_handle
*handle
,
5719 const char *printer_name
)
5721 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5722 struct dcerpc_pipe
*p2
;
5724 struct policy_handle hive_handle
;
5725 struct dcerpc_binding_handle
*b2
;
5727 torture_assert_ntstatus_ok(tctx
,
5728 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
5729 "could not open winreg pipe");
5730 b2
= p2
->binding_handle
;
5732 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
5734 ret
= test_GetPrinterInfo_winreg(tctx
, b
, handle
, printer_name
, b2
, &hive_handle
);
5736 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
5743 static bool test_DriverInfo_winreg(struct torture_context
*tctx
,
5744 struct dcerpc_pipe
*p
,
5745 struct policy_handle
*handle
,
5746 const char *printer_name
,
5747 const char *driver_name
,
5748 const char *environment
,
5749 enum spoolss_DriverOSVersion version
)
5751 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5752 struct dcerpc_pipe
*p2
;
5754 struct policy_handle hive_handle
;
5755 struct dcerpc_binding_handle
*b2
;
5757 torture_assert_ntstatus_ok(tctx
,
5758 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
5759 "could not open winreg pipe");
5760 b2
= p2
->binding_handle
;
5762 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
5764 ret
= test_GetDriverInfo_winreg(tctx
, b
, handle
, printer_name
, driver_name
, environment
, version
, b2
, &hive_handle
, NULL
);
5766 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
5773 static bool test_PrintProcessors_winreg(struct torture_context
*tctx
,
5774 struct dcerpc_binding_handle
*b
,
5775 const char *environment
)
5777 struct dcerpc_pipe
*p2
;
5779 struct policy_handle hive_handle
;
5780 struct dcerpc_binding_handle
*b2
;
5782 torture_assert_ntstatus_ok(tctx
,
5783 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
5784 "could not open winreg pipe");
5785 b2
= p2
->binding_handle
;
5787 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
5789 ret
= test_PrintProcessors(tctx
, b
, environment
, b2
, &hive_handle
);
5791 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
5798 static bool test_PrinterData_DsSpooler(struct torture_context
*tctx
,
5799 struct dcerpc_pipe
*p
,
5800 struct policy_handle
*handle
,
5801 const char *printer_name
)
5803 struct spoolss_SetPrinterInfoCtr info_ctr
;
5804 struct spoolss_DevmodeContainer devmode_ctr
;
5805 struct sec_desc_buf secdesc_ctr
;
5806 union spoolss_SetPrinterInfo sinfo
;
5807 union spoolss_PrinterInfo info
;
5808 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5811 ZERO_STRUCT(info_ctr
);
5812 ZERO_STRUCT(devmode_ctr
);
5813 ZERO_STRUCT(secdesc_ctr
);
5815 torture_comment(tctx
, "Testing DsSpooler <-> SetPrinter relations\n");
5817 torture_assert(tctx
,
5818 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
5819 "failed to query Printer level 2");
5821 torture_assert(tctx
,
5822 PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
),
5823 "failed to convert");
5826 info_ctr
.info
= sinfo
;
5828 #define TEST_SZ(wname, iname) \
5830 enum winreg_Type type;\
5835 torture_assert(tctx,\
5836 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5837 "failed to query");\
5838 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5839 blob = data_blob_const(data, needed);\
5840 torture_assert(tctx,\
5841 pull_reg_sz(tctx, &blob, &str),\
5842 "failed to pull REG_SZ");\
5843 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5847 #define TEST_SET_SZ(wname, iname, val) \
5849 enum winreg_Type type;\
5854 sinfo.info2->iname = val;\
5855 torture_assert(tctx,\
5856 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5857 "failed to call SetPrinter");\
5858 torture_assert(tctx,\
5859 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5860 "failed to query");\
5861 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5862 blob = data_blob_const(data, needed);\
5863 torture_assert(tctx,\
5864 pull_reg_sz(tctx, &blob, &str),\
5865 "failed to pull REG_SZ");\
5866 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5869 #define TEST_SET_DWORD(wname, iname, val) \
5871 enum winreg_Type type;\
5875 sinfo.info2->iname = val;\
5876 torture_assert(tctx,\
5877 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5878 "failed to call SetPrinter");\
5879 torture_assert(tctx,\
5880 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5881 "failed to query");\
5882 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5883 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5884 value = IVAL(data, 0); \
5885 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5888 TEST_SET_SZ("description", comment
, "newval");
5889 TEST_SET_SZ("location", location
, "newval");
5890 TEST_SET_SZ("driverName", drivername
, "newval");
5891 /* TEST_SET_DWORD("priority", priority, 25); */
5893 torture_assert(tctx
,
5894 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
5895 "failed to query Printer level 2");
5897 TEST_SZ("description", info
.info2
.comment
);
5898 TEST_SZ("driverName", info
.info2
.drivername
);
5899 TEST_SZ("location", info
.info2
.location
);
5901 pname
= strrchr(info
.info2
.printername
, '\\');
5902 if (pname
== NULL
) {
5903 pname
= info
.info2
.printername
;
5907 TEST_SZ("printerName", pname
);
5908 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5909 /* TEST_SZ("printShareName", info.info2.sharename); */
5911 /* FIXME gd: complete the list */
5917 torture_comment(tctx
, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5922 static bool test_print_processors_winreg(struct torture_context
*tctx
,
5925 struct test_spoolss_context
*ctx
=
5926 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
5927 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
5928 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5930 return test_PrintProcessors_winreg(tctx
, b
, ctx
->environment
);
5933 static bool test_AddPrintProcessor(struct torture_context
*tctx
,
5934 struct dcerpc_binding_handle
*b
,
5935 const char *environment
,
5936 const char *path_name
,
5937 const char *print_processor_name
,
5938 WERROR expected_error
)
5940 struct spoolss_AddPrintProcessor r
;
5943 r
.in
.architecture
= environment
;
5944 r
.in
.path_name
= path_name
;
5945 r
.in
.print_processor_name
= print_processor_name
;
5947 torture_comment(tctx
, "Testing AddPrintProcessor(%s)\n",
5948 print_processor_name
);
5950 torture_assert_ntstatus_ok(tctx
,
5951 dcerpc_spoolss_AddPrintProcessor_r(b
, tctx
, &r
),
5952 "spoolss_AddPrintProcessor failed");
5953 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_error
,
5954 "spoolss_AddPrintProcessor failed");
5959 static bool test_DeletePrintProcessor(struct torture_context
*tctx
,
5960 struct dcerpc_binding_handle
*b
,
5961 const char *environment
,
5962 const char *print_processor_name
,
5963 WERROR expected_error
)
5965 struct spoolss_DeletePrintProcessor r
;
5968 r
.in
.architecture
= environment
;
5969 r
.in
.print_processor_name
= print_processor_name
;
5971 torture_comment(tctx
, "Testing DeletePrintProcessor(%s)\n",
5972 print_processor_name
);
5974 torture_assert_ntstatus_ok(tctx
,
5975 dcerpc_spoolss_DeletePrintProcessor_r(b
, tctx
, &r
),
5976 "spoolss_DeletePrintProcessor failed");
5977 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_error
,
5978 "spoolss_DeletePrintProcessor failed");
5983 static bool test_add_print_processor(struct torture_context
*tctx
,
5986 struct test_spoolss_context
*ctx
=
5987 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
5988 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
5989 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5993 const char *environment
;
5994 const char *path_name
;
5995 const char *print_processor_name
;
5996 WERROR expected_add_result
;
5997 WERROR expected_del_result
;
6000 .environment
= ctx
->environment
,
6002 .print_processor_name
= "winprint",
6003 .expected_add_result
= WERR_PRINT_PROCESSOR_ALREADY_INSTALLED
,
6004 .expected_del_result
= WERR_CAN_NOT_COMPLETE
6006 .environment
= ctx
->environment
,
6008 .print_processor_name
= "unknown",
6009 .expected_add_result
= WERR_MOD_NOT_FOUND
,
6010 .expected_del_result
= WERR_UNKNOWN_PRINTPROCESSOR
6014 for (i
=0; i
< ARRAY_SIZE(tests
); i
++) {
6015 torture_assert(tctx
,
6016 test_AddPrintProcessor(tctx
, b
,
6017 tests
[i
].environment
,
6019 tests
[i
].print_processor_name
,
6020 tests
[i
].expected_add_result
),
6021 "add print processor failed");
6022 torture_assert(tctx
,
6023 test_DeletePrintProcessor(tctx
, b
,
6024 tests
[i
].environment
,
6025 tests
[i
].print_processor_name
,
6026 tests
[i
].expected_del_result
),
6027 "delete print processor failed");
6033 static bool test_GetChangeID_PrinterData(struct torture_context
*tctx
,
6034 struct dcerpc_binding_handle
*b
,
6035 struct policy_handle
*handle
,
6036 uint32_t *change_id
)
6038 enum winreg_Type type
;
6042 torture_assert(tctx
,
6043 test_GetPrinterData(tctx
, b
, handle
, "ChangeID", &type
, &data
, &needed
),
6044 "failed to call GetPrinterData");
6046 torture_assert(tctx
, type
== REG_DWORD
, "unexpected type");
6047 torture_assert_int_equal(tctx
, needed
, 4, "unexpected size");
6049 *change_id
= IVAL(data
, 0);
6054 static bool test_GetChangeID_PrinterDataEx(struct torture_context
*tctx
,
6055 struct dcerpc_pipe
*p
,
6056 struct policy_handle
*handle
,
6057 uint32_t *change_id
)
6059 enum winreg_Type type
;
6063 torture_assert(tctx
,
6064 test_GetPrinterDataEx(tctx
, p
, handle
, "PrinterDriverData", "ChangeID", &type
, &data
, &needed
),
6065 "failed to call GetPrinterData");
6067 torture_assert(tctx
, type
== REG_DWORD
, "unexpected type");
6068 torture_assert_int_equal(tctx
, needed
, 4, "unexpected size");
6070 *change_id
= IVAL(data
, 0);
6075 static bool test_GetChangeID_PrinterInfo(struct torture_context
*tctx
,
6076 struct dcerpc_binding_handle
*b
,
6077 struct policy_handle
*handle
,
6078 uint32_t *change_id
)
6080 union spoolss_PrinterInfo info
;
6082 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 0, &info
),
6083 "failed to query Printer level 0");
6085 *change_id
= info
.info0
.change_id
;
6090 static bool test_ChangeID(struct torture_context
*tctx
,
6091 struct dcerpc_pipe
*p
,
6092 struct policy_handle
*handle
)
6094 uint32_t change_id
, change_id_ex
, change_id_info
;
6095 uint32_t change_id2
, change_id_ex2
, change_id_info2
;
6096 union spoolss_PrinterInfo info
;
6097 const char *comment
;
6098 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6100 torture_comment(tctx
, "Testing ChangeID: id change test #1\n");
6102 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id
),
6103 "failed to query for ChangeID");
6104 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex
),
6105 "failed to query for ChangeID");
6106 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info
),
6107 "failed to query for ChangeID");
6109 torture_assert_int_equal(tctx
, change_id
, change_id_ex
,
6110 "change_ids should all be equal");
6111 torture_assert_int_equal(tctx
, change_id_ex
, change_id_info
,
6112 "change_ids should all be equal");
6115 torture_comment(tctx
, "Testing ChangeID: id change test #2\n");
6117 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id
),
6118 "failed to query for ChangeID");
6119 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
6120 "failed to query Printer level 2");
6121 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex
),
6122 "failed to query for ChangeID");
6123 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info
),
6124 "failed to query for ChangeID");
6125 torture_assert_int_equal(tctx
, change_id
, change_id_ex
,
6126 "change_id should not have changed");
6127 torture_assert_int_equal(tctx
, change_id_ex
, change_id_info
,
6128 "change_id should not have changed");
6131 torture_comment(tctx
, "Testing ChangeID: id change test #3\n");
6133 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id
),
6134 "failed to query for ChangeID");
6135 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex
),
6136 "failed to query for ChangeID");
6137 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info
),
6138 "failed to query for ChangeID");
6139 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
6140 "failed to query Printer level 2");
6141 comment
= talloc_strdup(tctx
, info
.info2
.comment
);
6144 struct spoolss_SetPrinterInfoCtr info_ctr
;
6145 struct spoolss_DevmodeContainer devmode_ctr
;
6146 struct sec_desc_buf secdesc_ctr
;
6147 union spoolss_SetPrinterInfo sinfo
;
6149 ZERO_STRUCT(info_ctr
);
6150 ZERO_STRUCT(devmode_ctr
);
6151 ZERO_STRUCT(secdesc_ctr
);
6154 torture_assert(tctx
, PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
6155 sinfo
.info2
->comment
= "torture_comment";
6158 info_ctr
.info
= sinfo
;
6160 torture_assert(tctx
, test_SetPrinter(tctx
, b
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0),
6161 "failed to call SetPrinter");
6163 sinfo
.info2
->comment
= comment
;
6165 torture_assert(tctx
, test_SetPrinter(tctx
, b
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0),
6166 "failed to call SetPrinter");
6170 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id2
),
6171 "failed to query for ChangeID");
6172 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex2
),
6173 "failed to query for ChangeID");
6174 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info2
),
6175 "failed to query for ChangeID");
6177 torture_assert_int_equal(tctx
, change_id2
, change_id_ex2
,
6178 "change_ids should all be equal");
6179 torture_assert_int_equal(tctx
, change_id_ex2
, change_id_info2
,
6180 "change_ids should all be equal");
6182 torture_assert(tctx
, (change_id
< change_id2
),
6183 talloc_asprintf(tctx
, "change_id %d needs to be larger than change_id %d",
6184 change_id2
, change_id
));
6185 torture_assert(tctx
, (change_id_ex
< change_id_ex2
),
6186 talloc_asprintf(tctx
, "change_id %d needs to be larger than change_id %d",
6187 change_id_ex2
, change_id_ex
));
6188 torture_assert(tctx
, (change_id_info
< change_id_info2
),
6189 talloc_asprintf(tctx
, "change_id %d needs to be larger than change_id %d",
6190 change_id_info2
, change_id_info
));
6192 torture_comment(tctx
, "ChangeID tests succeeded\n\n");
6197 static bool test_SecondaryClosePrinter(struct torture_context
*tctx
,
6198 struct dcerpc_pipe
*p
,
6199 struct policy_handle
*handle
)
6202 const struct dcerpc_binding
*binding2
;
6203 struct dcerpc_pipe
*p2
;
6204 struct spoolss_ClosePrinter cp
;
6206 /* only makes sense on SMB */
6207 if (p
->conn
->transport
.transport
!= NCACN_NP
) {
6211 torture_comment(tctx
, "Testing close on secondary pipe\n");
6213 binding2
= p
->binding
;
6214 status
= dcerpc_secondary_connection(p
, &p2
, binding2
);
6215 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create secondary connection");
6217 status
= dcerpc_bind_auth_none(p2
, &ndr_table_spoolss
);
6218 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create bind on secondary connection");
6220 cp
.in
.handle
= handle
;
6221 cp
.out
.handle
= handle
;
6223 status
= dcerpc_spoolss_ClosePrinter_r(p2
->binding_handle
, tctx
, &cp
);
6224 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_RPC_SS_CONTEXT_MISMATCH
,
6225 "ERROR: Allowed close on secondary connection");
6232 static bool test_OpenPrinter_badname(struct torture_context
*tctx
,
6233 struct dcerpc_binding_handle
*b
, const char *name
)
6236 struct spoolss_OpenPrinter op
;
6237 struct spoolss_OpenPrinterEx opEx
;
6238 struct policy_handle handle
;
6241 op
.in
.printername
= name
;
6242 op
.in
.datatype
= NULL
;
6243 op
.in
.devmode_ctr
.devmode
= NULL
;
6244 op
.in
.access_mask
= 0;
6245 op
.out
.handle
= &handle
;
6247 torture_comment(tctx
, "Testing OpenPrinter(%s) with bad name\n", op
.in
.printername
);
6249 status
= dcerpc_spoolss_OpenPrinter_r(b
, tctx
, &op
);
6250 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
6251 torture_assert_werr_equal(tctx
, op
.out
.result
, WERR_INVALID_PRINTER_NAME
,
6252 "unexpected result");
6254 if (W_ERROR_IS_OK(op
.out
.result
)) {
6255 ret
&=test_ClosePrinter(tctx
, b
, &handle
);
6258 opEx
.in
.printername
= name
;
6259 opEx
.in
.datatype
= NULL
;
6260 opEx
.in
.devmode_ctr
.devmode
= NULL
;
6261 opEx
.in
.access_mask
= 0;
6262 opEx
.in
.userlevel_ctr
.level
= 1;
6263 opEx
.in
.userlevel_ctr
.user_info
.level1
= NULL
;
6264 opEx
.out
.handle
= &handle
;
6266 torture_comment(tctx
, "Testing OpenPrinterEx(%s) with bad name\n", opEx
.in
.printername
);
6268 status
= dcerpc_spoolss_OpenPrinterEx_r(b
, tctx
, &opEx
);
6269 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinterEx failed");
6270 torture_assert_werr_equal(tctx
, opEx
.out
.result
, WERR_INVALID_PARAM
,
6271 "unexpected result");
6273 if (W_ERROR_IS_OK(opEx
.out
.result
)) {
6274 ret
&=test_ClosePrinter(tctx
, b
, &handle
);
6280 static bool test_OpenPrinter_badname_list(struct torture_context
*tctx
,
6283 struct test_spoolss_context
*ctx
=
6284 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
6286 const char *badnames
[] = {
6287 "__INVALID_PRINTER__",
6288 "\\\\__INVALID_HOST__",
6291 "\\\\\\__INVALID_PRINTER__"
6293 const char *badname
;
6294 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
6295 const char *server_name
= dcerpc_server_name(p
);
6296 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6299 for (i
=0; i
< ARRAY_SIZE(badnames
); i
++) {
6300 torture_assert(tctx
,
6301 test_OpenPrinter_badname(tctx
, b
, badnames
[i
]),
6305 badname
= talloc_asprintf(tctx
, "\\\\%s\\", server_name
);
6306 torture_assert(tctx
,
6307 test_OpenPrinter_badname(tctx
, b
, badname
),
6310 badname
= talloc_asprintf(tctx
, "\\\\%s\\__INVALID_PRINTER__", server_name
);
6311 torture_assert(tctx
,
6312 test_OpenPrinter_badname(tctx
, b
, badname
),
6318 static bool test_OpenPrinter(struct torture_context
*tctx
,
6319 struct dcerpc_pipe
*p
,
6321 const char *environment
,
6325 struct spoolss_OpenPrinter r
;
6326 struct policy_handle handle
;
6328 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6330 r
.in
.printername
= name
;
6331 r
.in
.datatype
= NULL
;
6332 r
.in
.devmode_ctr
.devmode
= NULL
;
6333 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
6334 r
.out
.handle
= &handle
;
6336 torture_comment(tctx
, "Testing OpenPrinter(%s)\n", r
.in
.printername
);
6338 status
= dcerpc_spoolss_OpenPrinter_r(b
, tctx
, &r
);
6340 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
6342 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenPrinter failed");
6348 if (!test_GetPrinter(tctx
, b
, &handle
, environment
)) {
6352 if (!torture_setting_bool(tctx
, "samba3", false)) {
6353 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
6359 if (!test_ClosePrinter(tctx
, b
, &handle
)) {
6366 static bool test_OpenPrinterEx(struct torture_context
*tctx
,
6367 struct dcerpc_binding_handle
*b
,
6368 const char *printername
,
6369 const char *datatype
,
6370 struct spoolss_DeviceMode
*devmode
,
6371 uint32_t access_mask
,
6372 struct spoolss_UserLevelCtr
*userlevel_ctr
,
6373 struct policy_handle
*handle
,
6374 WERROR expected_result
)
6376 struct spoolss_OpenPrinterEx r
;
6378 r
.in
.printername
= printername
;
6379 r
.in
.datatype
= datatype
;
6380 r
.in
.devmode_ctr
.devmode
= devmode
;
6381 r
.in
.access_mask
= access_mask
;
6382 r
.in
.userlevel_ctr
= *userlevel_ctr
;
6383 r
.out
.handle
= handle
;
6385 torture_comment(tctx
, "Testing OpenPrinterEx(%s)\n", r
.in
.printername
);
6387 torture_assert_ntstatus_ok(tctx
,
6388 dcerpc_spoolss_OpenPrinterEx_r(b
, tctx
, &r
),
6389 "OpenPrinterEx failed");
6391 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
6392 "OpenPrinterEx failed");
6397 static bool call_OpenPrinterEx(struct torture_context
*tctx
,
6398 struct dcerpc_pipe
*p
,
6400 struct spoolss_DeviceMode
*devmode
,
6401 struct policy_handle
*handle
)
6403 struct spoolss_UserLevelCtr userlevel_ctr
;
6404 struct spoolss_UserLevel1 userlevel1
;
6405 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6407 userlevel1
.size
= 1234;
6408 userlevel1
.client
= "hello";
6409 userlevel1
.user
= "spottyfoot!";
6410 userlevel1
.build
= 1;
6411 userlevel1
.major
= 2;
6412 userlevel1
.minor
= 3;
6413 userlevel1
.processor
= 4;
6415 userlevel_ctr
.level
= 1;
6416 userlevel_ctr
.user_info
.level1
= &userlevel1
;
6418 return test_OpenPrinterEx(tctx
, b
, name
, NULL
, devmode
,
6419 SEC_FLAG_MAXIMUM_ALLOWED
,
6425 static bool test_printer_rename(struct torture_context
*tctx
,
6428 struct torture_printer_context
*t
=
6429 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
6430 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
6433 union spoolss_PrinterInfo info
;
6434 union spoolss_SetPrinterInfo sinfo
;
6435 struct spoolss_SetPrinterInfoCtr info_ctr
;
6436 struct spoolss_DevmodeContainer devmode_ctr
;
6437 struct sec_desc_buf secdesc_ctr
;
6438 const char *printer_name
;
6439 const char *printer_name_orig
;
6440 const char *printer_name_new
= "SAMBA smbtorture Test Printer (Copy 2)";
6441 struct policy_handle new_handle
;
6443 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6445 ZERO_STRUCT(devmode_ctr
);
6446 ZERO_STRUCT(secdesc_ctr
);
6448 torture_comment(tctx
, "Testing Printer rename operations\n");
6450 torture_assert(tctx
,
6451 test_GetPrinter_level(tctx
, b
, &t
->handle
, 2, &info
),
6452 "failed to call GetPrinter level 2");
6454 printer_name_orig
= talloc_strdup(tctx
, info
.info2
.printername
);
6456 q
= strrchr(info
.info2
.printername
, '\\');
6458 torture_warning(tctx
,
6459 "server returns printername %s incl. servername although we did not set servername", info
.info2
.printername
);
6462 torture_assert(tctx
,
6463 PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
6465 sinfo
.info2
->printername
= printer_name_new
;
6468 info_ctr
.info
= sinfo
;
6470 torture_assert(tctx
,
6471 test_SetPrinter(tctx
, b
, &t
->handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0),
6472 "failed to call SetPrinter level 2");
6474 torture_assert(tctx
,
6475 test_GetPrinter_level(tctx
, b
, &t
->handle
, 2, &info
),
6476 "failed to call GetPrinter level 2");
6478 printer_name
= talloc_strdup(tctx
, info
.info2
.printername
);
6480 q
= strrchr(info
.info2
.printername
, '\\');
6482 torture_warning(tctx
,
6483 "server returns printername %s incl. servername although we did not set servername", info
.info2
.printername
);
6488 torture_assert_str_equal(tctx
, printer_name
, printer_name_new
,
6489 "new printer name was not set");
6491 /* samba currently cannot fully rename printers */
6492 if (!torture_setting_bool(tctx
, "samba3", false)) {
6493 torture_assert(tctx
,
6494 test_OpenPrinter_badname(tctx
, b
, printer_name_orig
),
6495 "still can open printer with oldname after rename");
6497 torture_warning(tctx
, "*not* checking for open with oldname after rename for samba3");
6500 torture_assert(tctx
,
6501 call_OpenPrinterEx(tctx
, p
, printer_name_new
, NULL
, &new_handle
),
6502 "failed to open printer with new name");
6504 torture_assert(tctx
,
6505 test_GetPrinter_level(tctx
, b
, &new_handle
, 2, &info
),
6506 "failed to call GetPrinter level 2");
6508 torture_assert_str_equal(tctx
, info
.info2
.printername
, printer_name_new
,
6509 "new printer name was not set");
6511 torture_assert(tctx
,
6512 test_ClosePrinter(tctx
, b
, &new_handle
),
6513 "failed to close printer");
6515 torture_comment(tctx
, "Printer rename operations test succeeded\n\n");
6520 static bool test_openprinter(struct torture_context
*tctx
,
6521 struct dcerpc_binding_handle
*b
,
6522 const char *real_printername
)
6524 struct spoolss_UserLevelCtr userlevel_ctr
;
6525 struct policy_handle handle
;
6526 struct spoolss_UserLevel1 userlevel1
;
6527 const char *printername
= NULL
;
6532 WERROR expected_result
;
6535 .suffix
= "rubbish",
6536 .expected_result
= WERR_INVALID_PRINTER_NAME
6538 .suffix
= ", LocalOnl",
6539 .expected_result
= WERR_INVALID_PRINTER_NAME
6541 .suffix
= ", localOnly",
6542 .expected_result
= WERR_INVALID_PRINTER_NAME
6544 .suffix
= ", localonl",
6545 .expected_result
= WERR_INVALID_PRINTER_NAME
6547 .suffix
= ",LocalOnl",
6548 .expected_result
= WERR_INVALID_PRINTER_NAME
6550 .suffix
= ",localOnl2",
6551 .expected_result
= WERR_INVALID_PRINTER_NAME
6553 .suffix
= ", DrvConver2t",
6554 .expected_result
= WERR_INVALID_PRINTER_NAME
6556 .suffix
= ", drvconvert",
6557 .expected_result
= WERR_INVALID_PRINTER_NAME
6559 .suffix
= ",drvconvert",
6560 .expected_result
= WERR_INVALID_PRINTER_NAME
6562 .suffix
= ", DrvConvert",
6563 .expected_result
= WERR_OK
6565 .suffix
= " , DrvConvert",
6566 .expected_result
= WERR_INVALID_PRINTER_NAME
6568 .suffix
= ",DrvConvert",
6569 .expected_result
= WERR_OK
6571 .suffix
= ", DrvConvertsadfasdf",
6572 .expected_result
= WERR_OK
6574 .suffix
= ",DrvConvertasdfasd",
6575 .expected_result
= WERR_OK
6577 .suffix
= ", LocalOnly",
6578 .expected_result
= WERR_OK
6580 .suffix
= " , LocalOnly",
6581 .expected_result
= WERR_INVALID_PRINTER_NAME
6583 .suffix
= ",LocalOnly",
6584 .expected_result
= WERR_OK
6586 .suffix
= ", LocalOnlysagi4gjfkd",
6587 .expected_result
= WERR_OK
6589 .suffix
= ",LocalOnlysagi4gjfkd",
6590 .expected_result
= WERR_OK
6594 userlevel1
.size
= 1234;
6595 userlevel1
.client
= "hello";
6596 userlevel1
.user
= "spottyfoot!";
6597 userlevel1
.build
= 1;
6598 userlevel1
.major
= 2;
6599 userlevel1
.minor
= 3;
6600 userlevel1
.processor
= 4;
6602 userlevel_ctr
.level
= 1;
6603 userlevel_ctr
.user_info
.level1
= &userlevel1
;
6605 torture_comment(tctx
, "Testing openprinterex printername pattern\n");
6607 torture_assert(tctx
,
6608 test_OpenPrinterEx(tctx
, b
, real_printername
, NULL
, NULL
, 0,
6609 &userlevel_ctr
, &handle
,
6611 "OpenPrinterEx failed");
6612 test_ClosePrinter(tctx
, b
, &handle
);
6614 for (i
=0; i
< ARRAY_SIZE(tests
); i
++) {
6616 printername
= talloc_asprintf(tctx
, "%s%s",
6620 torture_assert(tctx
,
6621 test_OpenPrinterEx(tctx
, b
, printername
, NULL
, NULL
, 0,
6622 &userlevel_ctr
, &handle
,
6623 tests
[i
].expected_result
),
6624 "OpenPrinterEx failed");
6625 if (W_ERROR_IS_OK(tests
[i
].expected_result
)) {
6626 test_ClosePrinter(tctx
, b
, &handle
);
6634 static bool test_existing_printer_openprinterex(struct torture_context
*tctx
,
6635 struct dcerpc_pipe
*p
,
6637 const char *environment
)
6639 struct policy_handle handle
;
6641 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6643 if (!test_openprinter(tctx
, b
, name
)) {
6647 if (!call_OpenPrinterEx(tctx
, p
, name
, NULL
, &handle
)) {
6651 if (!test_PrinterInfo_SD(tctx
, b
, &handle
)) {
6655 if (!test_GetPrinter(tctx
, b
, &handle
, environment
)) {
6659 if (!test_EnumForms_all(tctx
, b
, &handle
, false)) {
6663 if (!test_Forms(tctx
, b
, &handle
, false, name
, NULL
, NULL
)) {
6667 if (!test_Forms_winreg(tctx
, b
, &handle
, false, name
)) {
6671 if (!test_EnumPrinterData_all(tctx
, p
, &handle
)) {
6675 if (!test_EnumPrinterDataEx(tctx
, b
, &handle
, "PrinterDriverData", NULL
, NULL
)) {
6679 if (!test_EnumPrinterData_consistency(tctx
, p
, &handle
)) {
6683 if (!test_printer_all_keys(tctx
, b
, &handle
)) {
6687 if (!test_PausePrinter(tctx
, b
, &handle
)) {
6691 if (!test_DoPrintTest(tctx
, b
, &handle
)) {
6695 if (!test_ResumePrinter(tctx
, b
, &handle
)) {
6699 if (!test_SetPrinterData_matrix(tctx
, b
, &handle
, name
, NULL
, NULL
)) {
6703 if (!test_SetPrinterDataEx_matrix(tctx
, p
, &handle
, name
, NULL
, NULL
)) {
6707 if (!torture_setting_bool(tctx
, "samba3", false)) {
6708 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
6713 if (!test_ClosePrinter(tctx
, b
, &handle
)) {
6720 static bool test_EnumPrinters_old(struct torture_context
*tctx
,
6723 struct test_spoolss_context
*ctx
=
6724 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
6725 struct spoolss_EnumPrinters r
;
6727 uint16_t levels
[] = {1, 2, 4, 5};
6730 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
6731 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6733 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
6734 union spoolss_PrinterInfo
*info
;
6739 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
6741 r
.in
.level
= levels
[i
];
6744 r
.out
.needed
= &needed
;
6745 r
.out
.count
= &count
;
6748 torture_comment(tctx
, "Testing EnumPrinters level %u\n", r
.in
.level
);
6750 status
= dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &r
);
6751 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
6753 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
6754 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
6755 r
.in
.buffer
= &blob
;
6756 r
.in
.offered
= needed
;
6757 status
= dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &r
);
6760 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
6762 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
6764 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters
, info
, r
.in
.level
, count
, needed
, 4);
6767 torture_comment(tctx
, "No printers returned\n");
6771 for (j
=0;j
<count
;j
++) {
6772 if (r
.in
.level
== 1) {
6773 char *unc
= talloc_strdup(tctx
, info
[j
].info1
.name
);
6774 char *slash
, *name
, *full_name
;
6776 if (unc
[0] == '\\' && unc
[1] == '\\') {
6779 slash
= strchr(unc
, '\\');
6784 full_name
= talloc_asprintf(tctx
, "\\\\%s\\%s",
6785 dcerpc_server_name(p
), name
);
6786 if (!test_OpenPrinter(tctx
, p
, name
, ctx
->environment
, true)) {
6789 if (!test_OpenPrinter(tctx
, p
, full_name
, ctx
->environment
, true)) {
6792 if (!test_OpenPrinter(tctx
, p
, name
, ctx
->environment
, false)) {
6795 if (!test_existing_printer_openprinterex(tctx
, p
, name
, ctx
->environment
)) {
6805 static bool test_EnumPrinters_level(struct torture_context
*tctx
,
6806 struct dcerpc_binding_handle
*b
,
6808 const char *servername
,
6811 union spoolss_PrinterInfo
**info_p
)
6813 struct spoolss_EnumPrinters r
;
6814 union spoolss_PrinterInfo
*info
;
6819 r
.in
.server
= servername
;
6823 r
.out
.needed
= &needed
;
6824 r
.out
.count
= &count
;
6827 torture_comment(tctx
, "Testing EnumPrinters(%s) level %u\n",
6828 r
.in
.server
, r
.in
.level
);
6830 torture_assert_ntstatus_ok(tctx
,
6831 dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &r
),
6832 "EnumPrinters failed");
6833 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
6834 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
6835 r
.in
.buffer
= &blob
;
6836 r
.in
.offered
= needed
;
6837 torture_assert_ntstatus_ok(tctx
,
6838 dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &r
),
6839 "EnumPrinters failed");
6842 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
6844 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters
, info
, r
.in
.level
, count
, needed
, 4);
6856 static const char *get_short_printername(struct torture_context
*tctx
,
6859 const char *short_name
;
6861 if (name
[0] == '\\' && name
[1] == '\\') {
6863 short_name
= strchr(name
, '\\');
6865 return talloc_strdup(tctx
, short_name
+1);
6872 static const char *get_full_printername(struct torture_context
*tctx
,
6875 const char *full_name
= talloc_strdup(tctx
, name
);
6878 if (name
&& name
[0] == '\\' && name
[1] == '\\') {
6880 p
= strchr(name
, '\\');
6889 static bool test_OnePrinter_servername(struct torture_context
*tctx
,
6890 struct dcerpc_pipe
*p
,
6891 struct dcerpc_binding_handle
*b
,
6892 const char *servername
,
6893 const char *printername
)
6895 union spoolss_PrinterInfo info
;
6896 const char *short_name
= get_short_printername(tctx
, printername
);
6897 const char *full_name
= get_full_printername(tctx
, printername
);
6900 struct policy_handle handle
;
6901 torture_assert(tctx
,
6902 call_OpenPrinterEx(tctx
, p
, short_name
, NULL
, &handle
),
6903 "failed to open printer");
6905 torture_assert(tctx
,
6906 test_GetPrinter_level(tctx
, b
, &handle
, 2, &info
),
6907 "failed to get printer info");
6909 torture_assert_casestr_equal(tctx
, info
.info2
.servername
, NULL
,
6910 "unexpected servername");
6911 torture_assert_casestr_equal(tctx
, info
.info2
.printername
, short_name
,
6912 "unexpected printername");
6914 if (info
.info2
.devmode
) {
6915 const char *expected_devicename
;
6916 expected_devicename
= talloc_strndup(tctx
, short_name
, MIN(strlen(short_name
), 31));
6917 torture_assert_casestr_equal(tctx
, info
.info2
.devmode
->devicename
, expected_devicename
,
6918 "unexpected devicemode devicename");
6921 torture_assert(tctx
,
6922 test_ClosePrinter(tctx
, b
, &handle
),
6923 "failed to close printer");
6927 struct policy_handle handle
;
6929 torture_assert(tctx
,
6930 call_OpenPrinterEx(tctx
, p
, full_name
, NULL
, &handle
),
6931 "failed to open printer");
6933 torture_assert(tctx
,
6934 test_GetPrinter_level(tctx
, b
, &handle
, 2, &info
),
6935 "failed to get printer info");
6937 torture_assert_casestr_equal(tctx
, info
.info2
.servername
, servername
,
6938 "unexpected servername");
6939 torture_assert_casestr_equal(tctx
, info
.info2
.printername
, full_name
,
6940 "unexpected printername");
6942 if (info
.info2
.devmode
) {
6943 const char *expected_devicename
;
6944 expected_devicename
= talloc_strndup(tctx
, full_name
, MIN(strlen(full_name
), 31));
6945 torture_assert_casestr_equal(tctx
, info
.info2
.devmode
->devicename
, expected_devicename
,
6946 "unexpected devicemode devicename");
6949 torture_assert(tctx
,
6950 test_ClosePrinter(tctx
, b
, &handle
),
6951 "failed to close printer");
6957 static bool test_EnumPrinters_servername(struct torture_context
*tctx
,
6960 struct test_spoolss_context
*ctx
=
6961 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
6963 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
6964 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6966 union spoolss_PrinterInfo
*info
;
6967 const char *servername
;
6968 uint32_t flags
= PRINTER_ENUM_NAME
|PRINTER_ENUM_LOCAL
;
6970 torture_comment(tctx
, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6972 servername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
6974 torture_assert(tctx
,
6975 test_EnumPrinters_level(tctx
, b
, flags
, servername
, 2, &count
, &info
),
6976 "failed to enumerate printers");
6978 for (i
=0; i
< count
; i
++) {
6980 torture_assert_casestr_equal(tctx
, info
[i
].info2
.servername
, servername
,
6981 "unexpected servername");
6983 torture_assert(tctx
,
6984 test_OnePrinter_servername(tctx
, p
, b
, servername
, info
[i
].info2
.printername
),
6985 "failed to check printer");
6990 torture_assert(tctx
,
6991 test_EnumPrinters_level(tctx
, b
, flags
, servername
, 2, &count
, &info
),
6992 "failed to enumerate printers");
6994 for (i
=0; i
< count
; i
++) {
6996 torture_assert_casestr_equal(tctx
, info
[i
].info2
.servername
, NULL
,
6997 "unexpected servername");
6999 torture_assert(tctx
,
7000 test_OnePrinter_servername(tctx
, p
, b
, servername
, info
[i
].info2
.printername
),
7001 "failed to check printer");
7009 static bool test_GetPrinterDriver(struct torture_context
*tctx
,
7010 struct dcerpc_binding_handle
*b
,
7011 struct policy_handle
*handle
,
7012 const char *driver_name
)
7014 struct spoolss_GetPrinterDriver r
;
7017 r
.in
.handle
= handle
;
7018 r
.in
.architecture
= "W32X86";
7022 r
.out
.needed
= &needed
;
7024 torture_comment(tctx
, "Testing GetPrinterDriver level %d\n", r
.in
.level
);
7026 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver_r(b
, tctx
, &r
),
7027 "failed to call GetPrinterDriver");
7028 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
7029 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
7030 r
.in
.buffer
= &blob
;
7031 r
.in
.offered
= needed
;
7032 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver_r(b
, tctx
, &r
),
7033 "failed to call GetPrinterDriver");
7036 torture_assert_werr_ok(tctx
, r
.out
.result
,
7037 "failed to call GetPrinterDriver");
7039 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo
, r
.out
.info
, r
.in
.level
, needed
, 4);
7045 static bool test_GetPrinterDriver2_level(struct torture_context
*tctx
,
7046 struct dcerpc_binding_handle
*b
,
7047 struct policy_handle
*handle
,
7048 const char *driver_name
,
7049 const char *architecture
,
7051 uint32_t client_major_version
,
7052 uint32_t client_minor_version
,
7053 union spoolss_DriverInfo
*info_p
,
7057 struct spoolss_GetPrinterDriver2 r
;
7059 uint32_t server_major_version
;
7060 uint32_t server_minor_version
;
7062 r
.in
.handle
= handle
;
7063 r
.in
.architecture
= architecture
;
7064 r
.in
.client_major_version
= client_major_version
;
7065 r
.in
.client_minor_version
= client_minor_version
;
7069 r
.out
.needed
= &needed
;
7070 r
.out
.server_major_version
= &server_major_version
;
7071 r
.out
.server_minor_version
= &server_minor_version
;
7073 torture_comment(tctx
, "Testing GetPrinterDriver2(%s) level %d\n",
7074 driver_name
, r
.in
.level
);
7076 torture_assert_ntstatus_ok(tctx
,
7077 dcerpc_spoolss_GetPrinterDriver2_r(b
, tctx
, &r
),
7078 "failed to call GetPrinterDriver2");
7079 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
7080 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
7081 r
.in
.buffer
= &blob
;
7082 r
.in
.offered
= needed
;
7083 torture_assert_ntstatus_ok(tctx
,
7084 dcerpc_spoolss_GetPrinterDriver2_r(b
, tctx
, &r
),
7085 "failed to call GetPrinterDriver2");
7089 *result_p
= r
.out
.result
;
7092 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INVALID_LEVEL
)) {
7093 switch (r
.in
.level
) {
7096 torture_comment(tctx
,
7097 "level %d not implemented, not considering as an error\n",
7105 torture_assert_werr_ok(tctx
, r
.out
.result
,
7106 "failed to call GetPrinterDriver2");
7108 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo
, r
.out
.info
, r
.in
.level
, needed
, 4);
7111 *info_p
= *r
.out
.info
;
7117 static bool test_GetPrinterDriver2(struct torture_context
*tctx
,
7118 struct dcerpc_binding_handle
*b
,
7119 struct policy_handle
*handle
,
7120 const char *driver_name
,
7121 const char *architecture
)
7123 uint16_t levels
[] = {1, 2, 3, 4, 5, 6, 8, 101 };
7127 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
7129 torture_assert(tctx
,
7130 test_GetPrinterDriver2_level(tctx
, b
, handle
, driver_name
, architecture
, levels
[i
], 3, 0, NULL
, NULL
),
7137 static bool test_EnumPrinterDrivers_old(struct torture_context
*tctx
,
7140 struct test_spoolss_context
*ctx
=
7141 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
7142 uint16_t levels
[] = {1, 2, 3, 4, 5, 6};
7144 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
7145 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7146 const char *server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
7148 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
7151 union spoolss_DriverInfo
*info
;
7153 torture_assert(tctx
,
7154 test_EnumPrinterDrivers_args(tctx
, b
, server_name
, ctx
->environment
, levels
[i
], &count
, &info
),
7155 "failed to enumerate drivers");
7158 torture_comment(tctx
, "No printer drivers returned\n");
7166 static bool test_DeletePrinter(struct torture_context
*tctx
,
7167 struct dcerpc_binding_handle
*b
,
7168 struct policy_handle
*handle
)
7170 struct spoolss_DeletePrinter r
;
7172 torture_comment(tctx
, "Testing DeletePrinter\n");
7174 r
.in
.handle
= handle
;
7176 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_DeletePrinter_r(b
, tctx
, &r
),
7177 "failed to delete printer");
7178 torture_assert_werr_ok(tctx
, r
.out
.result
,
7179 "failed to delete printer");
7184 static bool test_EnumPrinters_findname(struct torture_context
*tctx
,
7185 struct dcerpc_binding_handle
*b
,
7191 struct spoolss_EnumPrinters e
;
7193 union spoolss_PrinterInfo
*info
;
7204 e
.out
.count
= &count
;
7206 e
.out
.needed
= &needed
;
7208 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &e
),
7209 "failed to enum printers");
7211 if (W_ERROR_EQUAL(e
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
7212 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
7213 e
.in
.buffer
= &blob
;
7214 e
.in
.offered
= needed
;
7216 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &e
),
7217 "failed to enum printers");
7220 torture_assert_werr_ok(tctx
, e
.out
.result
,
7221 "failed to enum printers");
7223 for (i
=0; i
< count
; i
++) {
7225 const char *current
= NULL
;
7230 current
= info
[i
].info1
.name
;
7234 if (strequal(current
, name
)) {
7239 q
= strrchr(current
, '\\');
7242 torture_warning(tctx
,
7243 "server returns printername %s incl. servername although we did not set servername", current
);
7246 if (strequal(q
, name
)) {
7256 static bool test_AddPrinter_wellknown(struct torture_context
*tctx
,
7257 struct dcerpc_pipe
*p
,
7258 const char *printername
,
7262 struct spoolss_AddPrinter r
;
7263 struct spoolss_AddPrinterEx rex
;
7264 struct spoolss_SetPrinterInfoCtr info_ctr
;
7265 struct spoolss_SetPrinterInfo1 info1
;
7266 struct spoolss_DevmodeContainer devmode_ctr
;
7267 struct sec_desc_buf secdesc_ctr
;
7268 struct spoolss_UserLevelCtr userlevel_ctr
;
7269 struct policy_handle handle
;
7271 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7273 ZERO_STRUCT(devmode_ctr
);
7274 ZERO_STRUCT(secdesc_ctr
);
7275 ZERO_STRUCT(userlevel_ctr
);
7278 torture_comment(tctx
, "Testing AddPrinter%s(%s) level 1\n",
7279 ex
? "Ex":"", printername
);
7281 /* try to add printer to wellknown printer list (level 1) */
7283 userlevel_ctr
.level
= 1;
7285 info_ctr
.info
.info1
= &info1
;
7288 rex
.in
.server
= NULL
;
7289 rex
.in
.info_ctr
= &info_ctr
;
7290 rex
.in
.devmode_ctr
= &devmode_ctr
;
7291 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
7292 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
7293 rex
.out
.handle
= &handle
;
7296 r
.in
.info_ctr
= &info_ctr
;
7297 r
.in
.devmode_ctr
= &devmode_ctr
;
7298 r
.in
.secdesc_ctr
= &secdesc_ctr
;
7299 r
.out
.handle
= &handle
;
7301 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7302 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7303 "failed to add printer");
7304 result
= ex
? rex
.out
.result
: r
.out
.result
;
7305 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
7306 "unexpected result code");
7308 info1
.name
= printername
;
7309 info1
.flags
= PRINTER_ATTRIBUTE_SHARED
;
7311 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7312 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7313 "failed to add printer");
7314 result
= ex
? rex
.out
.result
: r
.out
.result
;
7315 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
7316 "unexpected result code");
7318 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7319 better do a real check to see the printer is really there */
7321 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, b
,
7322 PRINTER_ENUM_NETWORK
, 1,
7325 "failed to enum printers");
7327 torture_assert(tctx
, found
, "failed to find newly added printer");
7331 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7332 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7333 "failed to add printer");
7334 result
= ex
? rex
.out
.result
: r
.out
.result
;
7335 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
7336 "unexpected result code");
7338 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7339 better do a real check to see the printer has really been removed
7340 from the well known printer list */
7344 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, b
,
7345 PRINTER_ENUM_NETWORK
, 1,
7348 "failed to enum printers");
7350 torture_assert(tctx
, !found
, "printer still in well known printer list");
7355 static bool test_AddPrinter_normal(struct torture_context
*tctx
,
7356 struct dcerpc_pipe
*p
,
7357 struct policy_handle
*handle_p
,
7358 const char *printername
,
7359 const char *drivername
,
7360 const char *portname
,
7361 struct spoolss_DeviceMode
*devmode
,
7365 struct spoolss_AddPrinter r
;
7366 struct spoolss_AddPrinterEx rex
;
7367 struct spoolss_SetPrinterInfoCtr info_ctr
;
7368 struct spoolss_SetPrinterInfo2 info2
;
7369 struct spoolss_DevmodeContainer devmode_ctr
;
7370 struct sec_desc_buf secdesc_ctr
;
7371 struct spoolss_UserLevelCtr userlevel_ctr
;
7372 struct policy_handle handle
;
7374 bool existing_printer_deleted
= false;
7375 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7377 ZERO_STRUCT(devmode_ctr
);
7378 ZERO_STRUCT(secdesc_ctr
);
7379 ZERO_STRUCT(userlevel_ctr
);
7381 torture_comment(tctx
, "Testing AddPrinter%s(%s) level 2\n",
7382 ex
? "Ex":"", printername
);
7384 devmode_ctr
.devmode
= devmode
;
7386 userlevel_ctr
.level
= 1;
7388 rex
.in
.server
= NULL
;
7389 rex
.in
.info_ctr
= &info_ctr
;
7390 rex
.in
.devmode_ctr
= &devmode_ctr
;
7391 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
7392 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
7393 rex
.out
.handle
= &handle
;
7396 r
.in
.info_ctr
= &info_ctr
;
7397 r
.in
.devmode_ctr
= &devmode_ctr
;
7398 r
.in
.secdesc_ctr
= &secdesc_ctr
;
7399 r
.out
.handle
= &handle
;
7403 /* try to add printer to printer list (level 2) */
7407 info_ctr
.info
.info2
= &info2
;
7410 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7411 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7412 "failed to add printer");
7413 result
= ex
? rex
.out
.result
: r
.out
.result
;
7414 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
7415 "unexpected result code");
7417 info2
.printername
= printername
;
7419 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7420 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7421 "failed to add printer");
7422 result
= ex
? rex
.out
.result
: r
.out
.result
;
7424 if (W_ERROR_EQUAL(result
, WERR_PRINTER_ALREADY_EXISTS
)) {
7425 struct policy_handle printer_handle
;
7427 if (existing_printer_deleted
) {
7428 torture_fail(tctx
, "already deleted printer still existing?");
7431 torture_assert(tctx
, call_OpenPrinterEx(tctx
, p
, printername
, NULL
, &printer_handle
),
7432 "failed to open printer handle");
7434 torture_assert(tctx
, test_DeletePrinter(tctx
, b
, &printer_handle
),
7435 "failed to delete printer");
7437 torture_assert(tctx
, test_ClosePrinter(tctx
, b
, &printer_handle
),
7438 "failed to close server handle");
7440 existing_printer_deleted
= true;
7445 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PORT
,
7446 "unexpected result code");
7448 info2
.portname
= portname
;
7450 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7451 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7452 "failed to add printer");
7453 result
= ex
? rex
.out
.result
: r
.out
.result
;
7454 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTER_DRIVER
,
7455 "unexpected result code");
7457 info2
.drivername
= drivername
;
7459 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7460 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7461 "failed to add printer");
7462 result
= ex
? rex
.out
.result
: r
.out
.result
;
7464 /* w2k8r2 allows to add printer w/o defining printprocessor */
7466 if (!W_ERROR_IS_OK(result
)) {
7467 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTPROCESSOR
,
7468 "unexpected result code");
7470 info2
.printprocessor
= "winprint";
7472 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7473 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7474 "failed to add printer");
7475 result
= ex
? rex
.out
.result
: r
.out
.result
;
7476 torture_assert_werr_ok(tctx
, result
,
7477 "failed to add printer");
7482 /* we are paranoid, really check if the printer is there now */
7484 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, b
,
7485 PRINTER_ENUM_LOCAL
, 1,
7488 "failed to enum printers");
7489 torture_assert(tctx
, found
, "failed to find newly added printer");
7491 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7492 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7493 "failed to add printer");
7494 result
= ex
? rex
.out
.result
: r
.out
.result
;
7495 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
7496 "unexpected result code");
7501 static bool test_printer_info(struct torture_context
*tctx
,
7504 struct torture_printer_context
*t
=
7505 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
7506 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
7507 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7511 if (torture_setting_bool(tctx
, "samba3", false)) {
7512 torture_skip(tctx
, "skipping printer info cross tests against samba 3");
7515 if (!test_PrinterInfo(tctx
, b
, &t
->handle
)) {
7519 if (!test_SetPrinter_errors(tctx
, b
, &t
->handle
)) {
7526 static bool test_EnumPrinterKey(struct torture_context
*tctx
,
7527 struct dcerpc_binding_handle
*b
,
7528 struct policy_handle
*handle
,
7529 const char *key_name
,
7530 const char ***array
)
7532 struct spoolss_EnumPrinterKey r
;
7533 uint32_t needed
= 0;
7534 union spoolss_KeyNames key_buffer
;
7535 int32_t offered
[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7539 r
.in
.handle
= handle
;
7540 r
.in
.key_name
= key_name
;
7541 r
.out
.key_buffer
= &key_buffer
;
7542 r
.out
.needed
= &needed
;
7543 r
.out
._ndr_size
= &_ndr_size
;
7545 for (i
=0; i
< ARRAY_SIZE(offered
); i
++) {
7547 if (offered
[i
] < 0 && needed
) {
7551 r
.in
.offered
= needed
+ offered
[i
];
7553 r
.in
.offered
= offered
[i
];
7556 ZERO_STRUCT(key_buffer
);
7558 torture_comment(tctx
, "Testing EnumPrinterKey(%s) with %d offered\n", r
.in
.key_name
, r
.in
.offered
);
7560 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterKey_r(b
, tctx
, &r
),
7561 "failed to call EnumPrinterKey");
7562 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
7564 torture_assert(tctx
, (_ndr_size
== r
.in
.offered
/2),
7565 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7566 _ndr_size
, r
.in
.offered
/2));
7568 r
.in
.offered
= needed
;
7569 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterKey_r(b
, tctx
, &r
),
7570 "failed to call EnumPrinterKey");
7573 if (offered
[i
] > 0) {
7574 torture_assert_werr_ok(tctx
, r
.out
.result
,
7575 "failed to call EnumPrinterKey");
7578 torture_assert(tctx
, (_ndr_size
== r
.in
.offered
/2),
7579 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7580 _ndr_size
, r
.in
.offered
/2));
7582 torture_assert(tctx
, (*r
.out
.needed
<= r
.in
.offered
),
7583 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r
.out
.needed
, r
.in
.offered
));
7585 torture_assert(tctx
, (*r
.out
.needed
<= _ndr_size
* 2),
7586 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r
.out
.needed
, _ndr_size
));
7588 if (key_buffer
.string_array
) {
7589 uint32_t calc_needed
= 0;
7591 for (s
=0; key_buffer
.string_array
[s
]; s
++) {
7592 calc_needed
+= strlen_m_term(key_buffer
.string_array
[s
])*2;
7594 if (!key_buffer
.string_array
[0]) {
7599 torture_assert_int_equal(tctx
, *r
.out
.needed
, calc_needed
,
7600 "EnumPrinterKey unexpected size");
7605 *array
= key_buffer
.string_array
;
7611 bool test_printer_all_keys(struct torture_context
*tctx
,
7612 struct dcerpc_binding_handle
*b
,
7613 struct policy_handle
*handle
)
7615 const char **key_array
= NULL
;
7618 torture_comment(tctx
, "Testing Printer Keys\n");
7620 torture_assert(tctx
, test_EnumPrinterKey(tctx
, b
, handle
, "", &key_array
),
7621 "failed to call test_EnumPrinterKey");
7623 for (i
=0; key_array
&& key_array
[i
]; i
++) {
7624 torture_assert(tctx
, test_EnumPrinterKey(tctx
, b
, handle
, key_array
[i
], NULL
),
7625 "failed to call test_EnumPrinterKey");
7627 for (i
=0; key_array
&& key_array
[i
]; i
++) {
7628 torture_assert(tctx
, test_EnumPrinterDataEx(tctx
, b
, handle
, key_array
[i
], NULL
, NULL
),
7629 "failed to call test_EnumPrinterDataEx");
7632 torture_comment(tctx
, "Printer Keys test succeeded\n\n");
7637 static bool test_openprinter_wrap(struct torture_context
*tctx
,
7640 struct torture_printer_context
*t
=
7641 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
7642 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
7643 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7644 const char *printername
= t
->info2
.printername
;
7646 return test_openprinter(tctx
, b
, printername
);
7649 static bool test_csetprinter(struct torture_context
*tctx
,
7652 struct torture_printer_context
*t
=
7653 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
7654 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
7656 const char *printername
= talloc_asprintf(tctx
, "%s2", t
->info2
.printername
);
7657 const char *drivername
= t
->added_driver
? t
->driver
.info8
.driver_name
: t
->info2
.drivername
;
7658 const char *portname
= t
->info2
.portname
;
7660 union spoolss_PrinterInfo info
;
7661 struct policy_handle new_handle
, new_handle2
;
7662 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7664 torture_comment(tctx
, "Testing c_setprinter\n");
7666 torture_assert(tctx
,
7667 test_GetPrinter_level(tctx
, b
, &t
->handle
, 0, &info
),
7668 "failed to get level 0 printer info");
7669 torture_comment(tctx
, "csetprinter on initial printer handle: %d\n",
7670 info
.info0
.c_setprinter
);
7672 /* check if c_setprinter on 1st handle increases after a printer has
7675 torture_assert(tctx
,
7676 test_AddPrinter_normal(tctx
, p
, &new_handle
, printername
, drivername
, portname
, NULL
, false),
7677 "failed to add new printer");
7678 torture_assert(tctx
,
7679 test_GetPrinter_level(tctx
, b
, &t
->handle
, 0, &info
),
7680 "failed to get level 0 printer info");
7681 torture_comment(tctx
, "csetprinter on initial printer handle (after add): %d\n",
7682 info
.info0
.c_setprinter
);
7684 /* check if c_setprinter on new handle increases after a printer has
7687 torture_assert(tctx
,
7688 test_GetPrinter_level(tctx
, b
, &new_handle
, 0, &info
),
7689 "failed to get level 0 printer info");
7690 torture_comment(tctx
, "csetprinter on created handle: %d\n",
7691 info
.info0
.c_setprinter
);
7693 /* open the new printer and check if c_setprinter increases */
7695 torture_assert(tctx
,
7696 call_OpenPrinterEx(tctx
, p
, printername
, NULL
, &new_handle2
),
7697 "failed to open created printer");
7698 torture_assert(tctx
,
7699 test_GetPrinter_level(tctx
, b
, &new_handle2
, 0, &info
),
7700 "failed to get level 0 printer info");
7701 torture_comment(tctx
, "csetprinter on new handle (after openprinter): %d\n",
7702 info
.info0
.c_setprinter
);
7706 torture_assert(tctx
,
7707 test_ClosePrinter(tctx
, b
, &new_handle2
),
7708 "failed to close printer");
7709 torture_assert(tctx
,
7710 test_DeletePrinter(tctx
, b
, &new_handle
),
7711 "failed to delete new printer");
7716 static bool compose_local_driver_directory(struct torture_context
*tctx
,
7717 const char *environment
,
7718 const char *local_dir
,
7723 p
= strrchr(local_dir
, '/');
7729 if (strequal(environment
, "Windows x64")) {
7730 if (!strequal(p
, "x64")) {
7731 *path
= talloc_asprintf(tctx
, "%s/x64", local_dir
);
7733 } else if (strequal(environment
, "Windows NT x86")) {
7734 if (!strequal(p
, "i386")) {
7735 *path
= talloc_asprintf(tctx
, "%s/i386", local_dir
);
7738 torture_assert(tctx
, "unknown environment: '%s'\n", environment
);
7745 static struct spoolss_DeviceMode
*torture_devicemode(TALLOC_CTX
*mem_ctx
,
7746 const char *devicename
)
7748 struct spoolss_DeviceMode
*r
;
7750 r
= talloc_zero(mem_ctx
, struct spoolss_DeviceMode
);
7755 r
->devicename
= talloc_strdup(r
, devicename
);
7756 r
->specversion
= DMSPEC_NT4_AND_ABOVE
;
7757 r
->driverversion
= 0x0600;
7759 r
->__driverextra_length
= 0;
7760 r
->fields
= DEVMODE_FORMNAME
|
7762 DEVMODE_PRINTQUALITY
|
7763 DEVMODE_DEFAULTSOURCE
|
7767 DEVMODE_ORIENTATION
;
7768 r
->orientation
= DMORIENT_PORTRAIT
;
7769 r
->papersize
= DMPAPER_LETTER
;
7774 r
->defaultsource
= DMBIN_FORMSOURCE
;
7775 r
->printquality
= DMRES_HIGH
;
7776 r
->color
= DMRES_MONOCHROME
;
7777 r
->duplex
= DMDUP_SIMPLEX
;
7779 r
->ttoption
= DMTT_SUBDEV
;
7780 r
->collate
= DMCOLLATE_FALSE
;
7781 r
->formname
= talloc_strdup(r
, "Letter");
7787 static bool test_architecture_buffer(struct torture_context
*tctx
,
7790 struct test_spoolss_context
*ctx
=
7791 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
7793 struct spoolss_OpenPrinterEx r
;
7794 struct spoolss_UserLevel1 u1
;
7795 struct policy_handle handle
;
7796 uint32_t architectures
[] = {
7797 PROCESSOR_ARCHITECTURE_INTEL
,
7798 PROCESSOR_ARCHITECTURE_IA64
,
7799 PROCESSOR_ARCHITECTURE_AMD64
7803 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
7804 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7806 for (i
=0; i
< ARRAY_SIZE(architectures
); i
++) {
7808 torture_comment(tctx
, "Testing OpenPrinterEx with architecture %d\n", architectures
[i
]);
7816 u1
.processor
= architectures
[i
];
7818 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
7819 r
.in
.datatype
= NULL
;
7820 r
.in
.devmode_ctr
.devmode
= NULL
;
7821 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
7822 r
.in
.userlevel_ctr
.level
= 1;
7823 r
.in
.userlevel_ctr
.user_info
.level1
= &u1
;
7824 r
.out
.handle
= &handle
;
7826 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_OpenPrinterEx_r(b
, tctx
, &r
), "");
7827 torture_assert_werr_ok(tctx
, r
.out
.result
, "");
7830 struct spoolss_EnumPrinters e
;
7832 union spoolss_PrinterInfo
*info
;
7834 e
.in
.flags
= PRINTER_ENUM_LOCAL
;
7839 e
.out
.count
= &count
;
7841 e
.out
.needed
= &needed
[i
];
7843 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &e
), "");
7845 torture_comment(tctx
, "needed was %d\n", needed
[i
]);
7849 torture_assert(tctx
, test_ClosePrinter(tctx
, b
, &handle
), "");
7852 for (i
=1; i
< ARRAY_SIZE(architectures
); i
++) {
7853 if (needed
[i
-1] != needed
[i
]) {
7855 talloc_asprintf(tctx
, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7856 needed
[i
-1], architectures
[i
-1], needed
[i
], architectures
[i
]));
7863 static bool test_PrintServer_Forms_Winreg(struct torture_context
*tctx
,
7866 struct test_spoolss_context
*ctx
=
7867 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
7868 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
7869 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7871 return test_Forms_winreg(tctx
, b
, &ctx
->server_handle
, true, NULL
);
7874 static bool test_PrintServer_Forms(struct torture_context
*tctx
,
7877 struct test_spoolss_context
*ctx
=
7878 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
7879 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
7880 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7882 return test_Forms(tctx
, b
, &ctx
->server_handle
, true, NULL
, NULL
, NULL
);
7885 static bool test_PrintServer_EnumForms(struct torture_context
*tctx
,
7888 struct test_spoolss_context
*ctx
=
7889 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
7890 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
7891 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7893 return test_EnumForms_all(tctx
, b
, &ctx
->server_handle
, true);
7896 static bool torture_rpc_spoolss_setup_common(struct torture_context
*tctx
, struct test_spoolss_context
*t
)
7900 status
= torture_rpc_connection(tctx
, &t
->spoolss_pipe
, &ndr_table_spoolss
);
7902 torture_assert_ntstatus_ok(tctx
, status
, "Error connecting to server");
7904 torture_assert(tctx
,
7905 test_OpenPrinter_server(tctx
, t
->spoolss_pipe
, &t
->server_handle
),
7906 "failed to open printserver");
7907 torture_assert(tctx
,
7908 test_get_environment(tctx
, t
->spoolss_pipe
->binding_handle
, &t
->server_handle
, &t
->environment
),
7909 "failed to get environment");
7914 static bool torture_rpc_spoolss_setup(struct torture_context
*tctx
, void **data
)
7916 struct test_spoolss_context
*t
;
7918 *data
= t
= talloc_zero(tctx
, struct test_spoolss_context
);
7920 return torture_rpc_spoolss_setup_common(tctx
, t
);
7923 static bool torture_rpc_spoolss_teardown_common(struct torture_context
*tctx
, struct test_spoolss_context
*t
)
7925 test_ClosePrinter(tctx
, t
->spoolss_pipe
->binding_handle
, &t
->server_handle
);
7930 static bool torture_rpc_spoolss_teardown(struct torture_context
*tctx
, void *data
)
7932 struct test_spoolss_context
*t
= talloc_get_type(data
, struct test_spoolss_context
);
7935 ret
= torture_rpc_spoolss_teardown_common(tctx
, t
);
7941 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context
*tctx
, struct torture_printer_context
*t
)
7943 struct dcerpc_pipe
*p
;
7944 struct dcerpc_binding_handle
*b
;
7945 const char *server_name_slash
;
7946 const char *driver_name
;
7947 const char *printer_name
;
7948 const char *port_name
;
7950 torture_assert_ntstatus_ok(tctx
,
7951 torture_rpc_connection(tctx
, &t
->spoolss_pipe
, &ndr_table_spoolss
),
7952 "Error connecting to server");
7954 p
= t
->spoolss_pipe
;
7955 b
= p
->binding_handle
;
7956 server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
7958 t
->driver
.info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
7959 t
->driver
.info8
.driver_name
= TORTURE_DRIVER
;
7960 t
->driver
.info8
.driver_path
= "pscript5.dll";
7961 t
->driver
.info8
.data_file
= "cups6.ppd";
7962 t
->driver
.info8
.config_file
= "ps5ui.dll";
7963 t
->driver
.info8
.help_file
= "pscript.hlp";
7964 t
->driver
.info8
.default_datatype
= "RAW";
7965 t
->driver
.info8
.dependent_files
= talloc_zero(t
, struct spoolss_StringArray
);
7966 t
->driver
.info8
.dependent_files
->string
= talloc_zero_array(t
, const char *, 8 + 1);
7967 t
->driver
.info8
.dependent_files
->string
[0] = "pscript5.dll";
7968 t
->driver
.info8
.dependent_files
->string
[1] = "cups6.ppd";
7969 t
->driver
.info8
.dependent_files
->string
[2] = "ps5ui.dll";
7970 t
->driver
.info8
.dependent_files
->string
[3] = "pscript.hlp";
7971 t
->driver
.info8
.dependent_files
->string
[4] = "pscript.ntf";
7972 t
->driver
.info8
.dependent_files
->string
[5] = "cups6.ini";
7973 t
->driver
.info8
.dependent_files
->string
[6] = "cupsps6.dll";
7974 t
->driver
.info8
.dependent_files
->string
[7] = "cupsui6.dll";
7976 t
->driver
.local
.driver_directory
= "/usr/share/cups/drivers";
7978 t
->info2
.portname
= "LPT1:";
7980 printer_name
= t
->info2
.printername
;
7981 port_name
= t
->info2
.portname
;
7983 torture_assert(tctx
,
7984 fillup_printserver_info(tctx
, p
, &t
->driver
),
7985 "failed to fillup printserver info");
7987 t
->driver
.info8
.architecture
= talloc_strdup(t
, t
->driver
.remote
.environment
);
7989 torture_assert(tctx
,
7990 compose_local_driver_directory(tctx
, t
->driver
.remote
.environment
,
7991 t
->driver
.local
.driver_directory
,
7992 &t
->driver
.local
.driver_directory
),
7993 "failed to compose local driver directory");
7995 t
->info2
.drivername
= "Microsoft XPS Document Writer";
7997 if (test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, t
->driver
.remote
.environment
, 3, t
->info2
.drivername
, NULL
)) {
7998 torture_comment(tctx
, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7999 t
->info2
.drivername
, t
->driver
.remote
.environment
);
8000 t
->have_driver
= true;
8004 torture_comment(tctx
, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
8005 t
->info2
.drivername
, t
->driver
.remote
.environment
);
8007 t
->info2
.drivername
= "Microsoft XPS Document Writer v4";
8009 if (test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, t
->driver
.remote
.environment
, 3, t
->info2
.drivername
, NULL
)) {
8010 torture_comment(tctx
, "driver '%s' (architecture: %s, version: 4) is present on server\n",
8011 t
->info2
.drivername
, t
->driver
.remote
.environment
);
8012 t
->have_driver
= true;
8016 torture_comment(tctx
, "trying to upload own driver\n");
8018 if (!directory_exist(t
->driver
.local
.driver_directory
)) {
8019 torture_warning(tctx
, "no local driver is available!");
8020 t
->have_driver
= false;
8024 torture_assert(tctx
,
8025 upload_printer_driver(tctx
, dcerpc_server_name(p
), &t
->driver
),
8026 "failed to upload printer driver");
8028 torture_assert(tctx
,
8029 test_AddPrinterDriver_args_level_3(tctx
, b
, server_name_slash
, &t
->driver
.info8
, 0, false, NULL
),
8030 "failed to add driver");
8032 t
->added_driver
= true;
8033 t
->have_driver
= true;
8036 driver_name
= t
->added_driver
? t
->driver
.info8
.driver_name
: t
->info2
.drivername
;
8039 torture_assert(tctx
,
8040 test_AddPrinter_wellknown(tctx
, p
, printer_name
, t
->ex
),
8041 "failed to add wellknown printer");
8043 torture_assert(tctx
,
8044 test_AddPrinter_normal(tctx
, p
, &t
->handle
, printer_name
, driver_name
, port_name
, t
->devmode
, t
->ex
),
8045 "failed to add printer");
8051 static bool torture_rpc_spoolss_printer_setup(struct torture_context
*tctx
, void **data
)
8053 struct torture_printer_context
*t
;
8055 *data
= t
= talloc_zero(tctx
, struct torture_printer_context
);
8058 t
->wellknown
= false;
8059 t
->info2
.printername
= TORTURE_PRINTER
;
8062 return torture_rpc_spoolss_printer_setup_common(tctx
, t
);
8065 static bool torture_rpc_spoolss_printerex_setup(struct torture_context
*tctx
, void **data
)
8067 struct torture_printer_context
*t
;
8069 *data
= t
= talloc_zero(tctx
, struct torture_printer_context
);
8072 t
->wellknown
= false;
8073 t
->info2
.printername
= TORTURE_PRINTER_EX
;
8076 return torture_rpc_spoolss_printer_setup_common(tctx
, t
);
8079 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context
*tctx
, void **data
)
8081 struct torture_printer_context
*t
;
8083 *data
= t
= talloc_zero(tctx
, struct torture_printer_context
);
8086 t
->wellknown
= true;
8087 t
->info2
.printername
= TORTURE_WELLKNOWN_PRINTER
;
8092 torture_skip(tctx
, "skipping AddPrinter level 1");
8095 return torture_rpc_spoolss_printer_setup_common(tctx
, t
);
8098 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context
*tctx
, void **data
)
8100 struct torture_printer_context
*t
;
8102 *data
= t
= talloc_zero(tctx
, struct torture_printer_context
);
8105 t
->wellknown
= true;
8106 t
->info2
.printername
= TORTURE_WELLKNOWN_PRINTER_EX
;
8111 torture_skip(tctx
, "skipping AddPrinterEx level 1");
8114 return torture_rpc_spoolss_printer_setup_common(tctx
, t
);
8118 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context
*tctx
, void **data
)
8120 struct torture_printer_context
*t
;
8122 *data
= t
= talloc_zero(tctx
, struct torture_printer_context
);
8125 t
->wellknown
= false;
8126 t
->info2
.printername
= TORTURE_PRINTER_EX
;
8127 t
->devmode
= torture_devicemode(t
, TORTURE_PRINTER_EX
);
8129 return torture_rpc_spoolss_printer_setup_common(tctx
, t
);
8133 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context
*tctx
, struct torture_printer_context
*t
)
8136 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8137 struct dcerpc_binding_handle
*b
;
8138 const char *printer_name
= t
->info2
.printername
;
8140 if (t
->added_driver
) {
8141 torture_assert(tctx
,
8142 remove_printer_driver(tctx
, dcerpc_server_name(t
->spoolss_pipe
), &t
->driver
),
8143 "failed to remove printer driver");
8146 if (p
&& !t
->wellknown
) {
8147 b
= p
->binding_handle
;
8149 torture_assert(tctx
,
8150 test_DeletePrinter(tctx
, b
, &t
->handle
),
8151 "failed to delete printer");
8153 torture_assert(tctx
,
8154 test_EnumPrinters_findname(tctx
, b
, PRINTER_ENUM_LOCAL
, 1,
8155 printer_name
, &found
),
8156 "failed to enumerate printers");
8158 torture_assert(tctx
, !found
, "deleted printer still there");
8164 static bool torture_rpc_spoolss_printer_teardown(struct torture_context
*tctx
, void *data
)
8166 struct torture_printer_context
*t
= talloc_get_type(data
, struct torture_printer_context
);
8169 ret
= torture_rpc_spoolss_printer_teardown_common(tctx
, t
);
8175 static bool test_print_test(struct torture_context
*tctx
,
8178 struct torture_printer_context
*t
=
8179 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8180 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8181 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8183 torture_assert(tctx
,
8184 test_PausePrinter(tctx
, b
, &t
->handle
),
8185 "failed to pause printer");
8187 torture_assert(tctx
,
8188 test_DoPrintTest(tctx
, b
, &t
->handle
),
8189 "failed to do print test");
8191 torture_assert(tctx
,
8192 test_ResumePrinter(tctx
, b
, &t
->handle
),
8193 "failed to resume printer");
8198 static bool test_print_test_extended(struct torture_context
*tctx
,
8201 struct torture_printer_context
*t
=
8202 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8203 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8204 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8207 torture_assert(tctx
,
8208 test_PausePrinter(tctx
, b
, &t
->handle
),
8209 "failed to pause printer");
8211 ret
= test_DoPrintTest_extended(tctx
, b
, &t
->handle
);
8213 torture_comment(tctx
, "WARNING! failed to do extended print test\n");
8214 if (torture_setting_bool(tctx
, "samba3", false)) {
8215 torture_comment(tctx
, "non-critical for samba3\n");
8217 tctx
->last_result
= TORTURE_SKIP
;
8221 torture_assert(tctx
,
8222 test_ResumePrinter(tctx
, b
, &t
->handle
),
8223 "failed to resume printer");
8228 static bool test_print_test_properties(struct torture_context
*tctx
,
8231 struct torture_printer_context
*t
=
8232 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8233 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8234 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8236 if (torture_setting_bool(tctx
, "samba3", false)) {
8237 torture_skip(tctx
, "skip printer job property tests against samba");
8240 torture_assert(tctx
,
8241 test_PausePrinter(tctx
, b
, &t
->handle
),
8242 "failed to pause printer");
8244 torture_assert(tctx
,
8245 test_DoPrintTest_properties(tctx
, b
, &t
->handle
),
8246 "failed to test print job properties");
8248 torture_assert(tctx
,
8249 test_ResumePrinter(tctx
, b
, &t
->handle
),
8250 "failed to resume printer");
8255 /* use smbd file IO to spool a print job */
8256 static bool test_print_test_smbd(struct torture_context
*tctx
,
8259 struct torture_printer_context
*t
=
8260 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8261 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8262 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8265 union spoolss_JobInfo
*info
= NULL
;
8268 struct smb2_tree
*tree
;
8269 struct smb2_handle job_h
;
8270 struct cli_credentials
*credentials
= cmdline_credentials
;
8271 struct smbcli_options options
;
8272 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
8274 * Do not test against the dynamically added printers, printing via
8275 * smbd means that a different spoolss process may handle the
8276 * OpenPrinter request to the one that handled the AddPrinter request.
8277 * This currently leads to an ugly race condition where one process
8278 * sees the new printer and one doesn't.
8280 const char *share
= TORTURE_PRINTER_STATIC1
;
8282 torture_comment(tctx
, "Testing smbd job spooling\n");
8283 lpcfg_smbcli_options(tctx
->lp_ctx
, &options
);
8285 status
= smb2_connect(mem_ctx
,
8286 torture_setting_string(tctx
, "host", NULL
),
8287 lpcfg_smb_ports(tctx
->lp_ctx
),
8289 lpcfg_resolve_context(tctx
->lp_ctx
),
8294 lpcfg_socket_options(tctx
->lp_ctx
),
8295 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
));
8296 if (!NT_STATUS_IS_OK(status
)) {
8297 printf("Failed to connect to SMB2 printer %s - %s\n",
8298 share
, nt_errstr(status
));
8302 status
= torture_smb2_testfile(tree
, "smbd_spooler_job", &job_h
);
8303 torture_assert_ntstatus_ok(tctx
, status
, "smbd spool job create");
8305 status
= smb2_util_write(tree
, job_h
, "exciting print job data", 0,
8306 sizeof("exciting print job data"));
8307 torture_assert_ntstatus_ok(tctx
, status
, "smbd spool job write");
8309 /* check back end spoolss job was created */
8310 torture_assert(tctx
,
8311 test_EnumJobs_args(tctx
, b
, &t
->handle
, 1, WERR_OK
,
8313 "EnumJobs level 1 failed");
8315 for (i
= 0; i
< count
; i
++) {
8316 if (!strcmp(info
[i
].info1
.document_name
, "smbd_spooler_job")) {
8320 torture_assert(tctx
, (i
!= count
), "smbd_spooler_job not found");
8322 status
= smb2_util_close(tree
, job_h
);
8323 torture_assert_ntstatus_ok(tctx
, status
, "smbd spool job close");
8325 /* disconnect from printer share */
8326 talloc_free(mem_ctx
);
8331 static bool test_print_test_purge(struct torture_context
*tctx
,
8334 struct torture_printer_context
*t
=
8335 (struct torture_printer_context
*)talloc_get_type_abort(private_data
,
8336 struct torture_printer_context
);
8337 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8338 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8339 uint32_t num_jobs
= 8;
8344 union spoolss_JobInfo
*info
;
8346 torture_assert(tctx
,
8347 test_PausePrinter(tctx
, b
, &t
->handle
),
8348 "failed to pause printer");
8350 job_ids
= talloc_zero_array(tctx
, uint32_t, num_jobs
);
8351 for (i
=0; i
< num_jobs
; i
++) {
8352 ret
= test_DoPrintTest_add_one_job(tctx
, b
, &t
->handle
,
8355 torture_assert(tctx
, ret
, "failed to add print job");
8358 torture_assert(tctx
,
8359 test_EnumJobs_args(tctx
, b
, &t
->handle
, 1, WERR_OK
,
8361 "EnumJobs level 1 failed");
8363 torture_assert_int_equal(tctx
, count
, num_jobs
,
8364 "unexpected number of jobs in queue");
8366 torture_assert(tctx
,
8367 test_printer_purge(tctx
, b
, &t
->handle
),
8368 "failed to purge printer");
8370 torture_assert(tctx
,
8371 test_EnumJobs_args(tctx
, b
, &t
->handle
, 1, WERR_OK
,
8373 "EnumJobs level 1 failed");
8375 torture_assert_int_equal(tctx
, count
, 0,
8376 "unexpected number of jobs in queue");
8378 torture_assert(tctx
,
8379 test_ResumePrinter(tctx
, b
, &t
->handle
),
8380 "failed to resume printer");
8385 static bool test_printer_sd(struct torture_context
*tctx
,
8388 struct torture_printer_context
*t
=
8389 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8390 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8391 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8393 torture_assert(tctx
,
8394 test_PrinterInfo_SD(tctx
, b
, &t
->handle
),
8395 "failed to test security descriptors");
8400 static bool test_printer_dm(struct torture_context
*tctx
,
8403 struct torture_printer_context
*t
=
8404 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8405 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8407 torture_assert(tctx
,
8408 test_PrinterInfo_DevMode(tctx
, p
, &t
->handle
, t
->info2
.printername
, t
->devmode
),
8409 "failed to test devicemodes");
8414 static bool test_printer_info_winreg(struct torture_context
*tctx
,
8417 struct torture_printer_context
*t
=
8418 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8419 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8421 torture_assert(tctx
,
8422 test_PrinterInfo_winreg(tctx
, p
, &t
->handle
, t
->info2
.printername
),
8423 "failed to test printer info winreg");
8428 static bool test_printer_change_id(struct torture_context
*tctx
,
8431 struct torture_printer_context
*t
=
8432 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8433 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8435 torture_assert(tctx
,
8436 test_ChangeID(tctx
, p
, &t
->handle
),
8437 "failed to test change id");
8442 static bool test_printer_keys(struct torture_context
*tctx
,
8445 struct torture_printer_context
*t
=
8446 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8447 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8448 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8450 torture_assert(tctx
,
8451 test_printer_all_keys(tctx
, b
, &t
->handle
),
8452 "failed to test printer keys");
8457 static bool test_printer_data_consistency(struct torture_context
*tctx
,
8460 struct torture_printer_context
*t
=
8461 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8462 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8464 torture_assert(tctx
,
8465 test_EnumPrinterData_consistency(tctx
, p
, &t
->handle
),
8466 "failed to test printer data consistency");
8471 static bool test_printer_data_keys(struct torture_context
*tctx
,
8474 struct torture_printer_context
*t
=
8475 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8476 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8478 torture_assert(tctx
,
8479 test_SetPrinterDataEx_keys(tctx
, p
, &t
->handle
),
8480 "failed to test printer data keys");
8485 static bool test_printer_data_values(struct torture_context
*tctx
,
8488 struct torture_printer_context
*t
=
8489 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8490 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8492 torture_assert(tctx
,
8493 test_SetPrinterDataEx_values(tctx
, p
, &t
->handle
),
8494 "failed to test printer data values");
8499 static bool test_printer_data_set(struct torture_context
*tctx
,
8502 struct torture_printer_context
*t
=
8503 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8504 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8506 torture_assert(tctx
,
8507 test_SetPrinterDataEx_matrix(tctx
, p
, &t
->handle
, t
->info2
.printername
, NULL
, NULL
),
8508 "failed to test printer data set");
8513 static bool test_printer_data_winreg(struct torture_context
*tctx
,
8516 struct torture_printer_context
*t
=
8517 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8518 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8520 torture_assert(tctx
,
8521 test_PrinterData_winreg(tctx
, p
, &t
->handle
, t
->info2
.printername
),
8522 "failed to test printer data winreg");
8527 static bool test_printer_data_dsspooler(struct torture_context
*tctx
,
8530 struct torture_printer_context
*t
=
8531 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8532 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8534 torture_assert(tctx
,
8535 test_PrinterData_DsSpooler(tctx
, p
, &t
->handle
, t
->info2
.printername
),
8536 "failed to test printer data winreg dsspooler");
8541 static bool test_printer_ic(struct torture_context
*tctx
,
8544 struct torture_printer_context
*t
=
8545 talloc_get_type_abort(private_data
,
8546 struct torture_printer_context
);
8547 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8548 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8549 struct policy_handle gdi_handle
;
8551 if (torture_setting_bool(tctx
, "samba3", false)) {
8552 torture_skip(tctx
, "skip printer information context tests against samba");
8556 struct spoolss_CreatePrinterIC r
;
8557 struct spoolss_DevmodeContainer devmode_ctr
;
8559 ZERO_STRUCT(devmode_ctr
);
8561 r
.in
.handle
= &t
->handle
;
8562 r
.in
.devmode_ctr
= &devmode_ctr
;
8563 r
.out
.gdi_handle
= &gdi_handle
;
8565 torture_assert_ntstatus_ok(tctx
,
8566 dcerpc_spoolss_CreatePrinterIC_r(b
, tctx
, &r
),
8567 "CreatePrinterIC failed");
8568 torture_assert_werr_ok(tctx
, r
.out
.result
,
8569 "CreatePrinterIC failed");
8573 struct spoolss_PlayGDIScriptOnPrinterIC r
;
8576 uint32_t num_fonts
= 0;
8578 in
= data_blob_string_const("");
8580 r
.in
.gdi_handle
= &gdi_handle
;
8582 r
.in
.cIn
= in
.length
;
8585 for (i
= 0; i
< 4; i
++) {
8587 out
= data_blob_talloc_zero(tctx
, i
);
8589 r
.in
.cOut
= out
.length
;
8590 r
.out
.pOut
= out
.data
;
8592 torture_assert_ntstatus_ok(tctx
,
8593 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b
, tctx
, &r
),
8594 "PlayGDIScriptOnPrinterIC failed");
8595 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_NOMEM
,
8596 "PlayGDIScriptOnPrinterIC failed");
8599 out
= data_blob_talloc_zero(tctx
, 4);
8601 r
.in
.cOut
= out
.length
;
8602 r
.out
.pOut
= out
.data
;
8604 torture_assert_ntstatus_ok(tctx
,
8605 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b
, tctx
, &r
),
8606 "PlayGDIScriptOnPrinterIC failed");
8607 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_OK
,
8608 "PlayGDIScriptOnPrinterIC failed");
8610 /* now we should have the required length, so retry with a
8611 * buffer which is large enough to carry all font ids */
8613 num_fonts
= IVAL(r
.out
.pOut
, 0);
8615 torture_comment(tctx
, "PlayGDIScriptOnPrinterIC gave font count of %d\n", num_fonts
);
8617 out
= data_blob_talloc_zero(tctx
,
8618 num_fonts
* sizeof(struct UNIVERSAL_FONT_ID
) + 4);
8620 r
.in
.cOut
= out
.length
;
8621 r
.out
.pOut
= out
.data
;
8623 torture_assert_ntstatus_ok(tctx
,
8624 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b
, tctx
, &r
),
8625 "PlayGDIScriptOnPrinterIC failed");
8626 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_OK
,
8627 "PlayGDIScriptOnPrinterIC failed");
8632 struct spoolss_DeletePrinterIC r
;
8634 r
.in
.gdi_handle
= &gdi_handle
;
8635 r
.out
.gdi_handle
= &gdi_handle
;
8637 torture_assert_ntstatus_ok(tctx
,
8638 dcerpc_spoolss_DeletePrinterIC_r(b
, tctx
, &r
),
8639 "DeletePrinterIC failed");
8640 torture_assert_werr_ok(tctx
, r
.out
.result
,
8641 "DeletePrinterIC failed");
8648 static bool test_printer_bidi(struct torture_context
*tctx
,
8651 struct torture_printer_context
*t
=
8652 talloc_get_type_abort(private_data
,
8653 struct torture_printer_context
);
8654 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8655 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8656 struct spoolss_RpcSendRecvBidiData r
;
8657 struct RPC_BIDI_REQUEST_CONTAINER bidi_req
;
8658 struct RPC_BIDI_RESPONSE_CONTAINER
*bidi_rep
= NULL
;
8660 if (torture_setting_bool(tctx
, "samba3", false)) {
8661 torture_skip(tctx
, "skip printer bidirectional tests against samba");
8664 ZERO_STRUCT(bidi_req
);
8666 r
.in
.hPrinter
= t
->handle
;
8667 r
.in
.pAction
= "foobar";
8668 r
.in
.pReqData
= &bidi_req
;
8669 r
.out
.ppRespData
= &bidi_rep
;
8671 torture_assert_ntstatus_ok(tctx
,
8672 dcerpc_spoolss_RpcSendRecvBidiData_r(b
, tctx
, &r
),
8673 "RpcSendRecvBidiData failed");
8674 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_NOT_SUPPORTED
,
8675 "RpcSendRecvBidiData failed");
8677 if (!(t
->info2
.attributes
& PRINTER_ATTRIBUTE_ENABLE_BIDI
)) {
8678 torture_skip(tctx
, "skipping further tests as printer is not BIDI enabled");
8681 r
.in
.pAction
= BIDI_ACTION_ENUM_SCHEMA
;
8683 torture_assert_ntstatus_ok(tctx
,
8684 dcerpc_spoolss_RpcSendRecvBidiData_r(b
, tctx
, &r
),
8685 "RpcSendRecvBidiData failed");
8686 torture_assert_werr_ok(tctx
, r
.out
.result
,
8687 "RpcSendRecvBidiData failed");
8692 static bool test_printer_set_publish(struct torture_context
*tctx
,
8693 struct dcerpc_binding_handle
*b
,
8694 struct policy_handle
*handle
)
8696 union spoolss_PrinterInfo info
;
8697 struct spoolss_SetPrinterInfo7 info7
;
8698 struct spoolss_SetPrinterInfoCtr info_ctr
;
8699 struct spoolss_DevmodeContainer devmode_ctr
;
8700 struct sec_desc_buf secdesc_ctr
;
8703 info7
.action
= DSPRINT_PUBLISH
;
8705 ZERO_STRUCT(info_ctr
);
8706 ZERO_STRUCT(devmode_ctr
);
8707 ZERO_STRUCT(secdesc_ctr
);
8709 info_ctr
.info
.info7
= &info7
;
8711 torture_assert(tctx
,
8712 test_SetPrinter(tctx
, b
, handle
, &info_ctr
,
8713 &devmode_ctr
, &secdesc_ctr
, 0), "");
8715 torture_assert(tctx
,
8716 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
8718 torture_assert(tctx
,
8719 (info
.info2
.attributes
& PRINTER_ATTRIBUTE_PUBLISHED
),
8720 "info2 publish flag not set");
8721 torture_assert(tctx
,
8722 test_GetPrinter_level(tctx
, b
, handle
, 7, &info
),
8724 if (info
.info7
.action
& DSPRINT_PENDING
) {
8725 torture_comment(tctx
, "publish is pending\n");
8726 torture_assert_int_equal(tctx
,
8728 (DSPRINT_PENDING
| DSPRINT_PUBLISH
),
8729 "info7 publish flag not set");
8732 torture_assert_int_equal(tctx
,
8735 "info7 publish flag not set");
8736 torture_assert_ntstatus_ok(tctx
,
8737 GUID_from_string(info
.info7
.guid
,
8739 "invalid published printer GUID");
8745 static bool test_printer_set_unpublish(struct torture_context
*tctx
,
8746 struct dcerpc_binding_handle
*b
,
8747 struct policy_handle
*handle
)
8749 union spoolss_PrinterInfo info
;
8750 struct spoolss_SetPrinterInfo7 info7
;
8751 struct spoolss_SetPrinterInfoCtr info_ctr
;
8752 struct spoolss_DevmodeContainer devmode_ctr
;
8753 struct sec_desc_buf secdesc_ctr
;
8755 info7
.action
= DSPRINT_UNPUBLISH
;
8758 ZERO_STRUCT(info_ctr
);
8759 ZERO_STRUCT(devmode_ctr
);
8760 ZERO_STRUCT(secdesc_ctr
);
8762 info_ctr
.info
.info7
= &info7
;
8764 torture_assert(tctx
,
8765 test_SetPrinter(tctx
, b
, handle
, &info_ctr
,
8766 &devmode_ctr
, &secdesc_ctr
, 0), "");
8768 torture_assert(tctx
,
8769 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
8771 torture_assert(tctx
,
8772 !(info
.info2
.attributes
& PRINTER_ATTRIBUTE_PUBLISHED
),
8773 "info2 publish flag still set");
8774 torture_assert(tctx
,
8775 test_GetPrinter_level(tctx
, b
, handle
, 7, &info
),
8778 if (info
.info7
.action
& DSPRINT_PENDING
) {
8780 torture_comment(tctx
, "unpublish is pending\n");
8781 torture_assert_int_equal(tctx
,
8783 (DSPRINT_PENDING
| DSPRINT_UNPUBLISH
),
8784 "info7 unpublish flag not set");
8785 torture_assert_ntstatus_ok(tctx
,
8786 GUID_from_string(info
.info7
.guid
,
8788 "invalid printer GUID");
8790 torture_assert_int_equal(tctx
,
8791 info
.info7
.action
, DSPRINT_UNPUBLISH
,
8792 "info7 unpublish flag not set");
8798 static bool test_printer_publish_toggle(struct torture_context
*tctx
,
8801 struct torture_printer_context
*t
=
8802 talloc_get_type_abort(private_data
,
8803 struct torture_printer_context
);
8804 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8805 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8806 struct policy_handle
*handle
= &t
->handle
;
8807 union spoolss_PrinterInfo info7
;
8808 union spoolss_PrinterInfo info2
;
8810 /* check publish status via level 7 and level 2 */
8811 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 7, &info7
),
8813 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info2
),
8816 if (info2
.info2
.attributes
& PRINTER_ATTRIBUTE_PUBLISHED
) {
8817 torture_assert_int_equal(tctx
,
8818 info7
.info7
.action
, DSPRINT_PUBLISH
,
8819 "info7 publish flag not set");
8820 torture_assert(tctx
, test_printer_set_unpublish(tctx
, b
, handle
), "");
8821 torture_assert(tctx
, test_printer_set_publish(tctx
, b
, handle
), "");
8823 torture_assert_int_equal(tctx
,
8824 info7
.info7
.action
, DSPRINT_UNPUBLISH
,
8825 "info7 unpublish flag not set");
8826 torture_assert(tctx
, test_printer_set_publish(tctx
, b
, handle
), "");
8827 torture_assert(tctx
, test_printer_set_unpublish(tctx
, b
, handle
), "");
8833 static bool test_driver_info_winreg(struct torture_context
*tctx
,
8836 struct torture_printer_context
*t
=
8837 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8838 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8839 const char *driver_name
= t
->added_driver
? t
->driver
.info8
.driver_name
: t
->info2
.drivername
;
8841 if (!t
->have_driver
) {
8842 torture_skip(tctx
, "skipping driver info winreg test as we don't have a driver");
8845 torture_assert(tctx
,
8846 test_DriverInfo_winreg(tctx
, p
, &t
->handle
, t
->info2
.printername
, driver_name
, t
->driver
.remote
.environment
, 3),
8847 "failed to test driver info winreg");
8852 static bool test_print_job_enum(struct torture_context
*tctx
,
8855 struct torture_printer_context
*t
=
8856 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8857 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8858 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8860 uint32_t num_jobs
= 8;
8863 union spoolss_JobInfo
*info
= NULL
;
8866 torture_assert(tctx
,
8867 test_PausePrinter(tctx
, b
, &t
->handle
),
8868 "failed to pause printer");
8870 /* purge in case of any jobs from previous tests */
8871 torture_assert(tctx
,
8872 test_printer_purge(tctx
, b
, &t
->handle
),
8873 "failed to purge printer");
8875 /* enum before jobs, valid level */
8876 torture_assert(tctx
,
8877 test_EnumJobs_args(tctx
, b
, &t
->handle
, 1, WERR_OK
,
8879 "EnumJobs with valid level");
8880 torture_assert_int_equal(tctx
, count
, 0, "EnumJobs count");
8881 torture_assert(tctx
,
8882 test_EnumJobs_args(tctx
, b
, &t
->handle
, 2, WERR_OK
,
8884 "EnumJobs with valid level");
8885 torture_assert_int_equal(tctx
, count
, 0, "EnumJobs count");
8886 /* enum before jobs, invalid level - expect failure */
8887 torture_assert(tctx
,
8888 test_EnumJobs_args(tctx
, b
, &t
->handle
, 100,
8891 "EnumJobs with invalid level");
8893 job_ids
= talloc_zero_array(tctx
, uint32_t, num_jobs
);
8895 for (i
= 0; i
< num_jobs
; i
++) {
8896 ret
= test_DoPrintTest_add_one_job(tctx
, b
, &t
->handle
,
8899 torture_assert(tctx
, ret
, "failed to add print job");
8902 /* enum after jobs, valid level */
8903 torture_assert(tctx
,
8904 test_EnumJobs_args(tctx
, b
, &t
->handle
, 1, WERR_OK
,
8906 "EnumJobs with valid level");
8907 torture_assert_int_equal(tctx
, count
, num_jobs
, "EnumJobs count");
8908 torture_assert(tctx
,
8909 test_EnumJobs_args(tctx
, b
, &t
->handle
, 2, WERR_OK
,
8911 "EnumJobs with valid level");
8912 torture_assert_int_equal(tctx
, count
, num_jobs
, "EnumJobs count");
8913 /* enum after jobs, invalid level - expect failure */
8914 torture_assert(tctx
,
8915 test_EnumJobs_args(tctx
, b
, &t
->handle
, 100,
8918 "EnumJobs with invalid level");
8920 for (i
= 0; i
< num_jobs
; i
++) {
8921 test_SetJob(tctx
, b
, &t
->handle
, job_ids
[i
], NULL
,
8922 SPOOLSS_JOB_CONTROL_DELETE
);
8925 torture_assert(tctx
,
8926 test_ResumePrinter(tctx
, b
, &t
->handle
),
8927 "failed to resume printer");
8932 void torture_tcase_printer(struct torture_tcase
*tcase
)
8934 torture_tcase_add_simple_test(tcase
, "openprinter", test_openprinter_wrap
);
8935 torture_tcase_add_simple_test(tcase
, "csetprinter", test_csetprinter
);
8936 torture_tcase_add_simple_test(tcase
, "print_test", test_print_test
);
8937 torture_tcase_add_simple_test(tcase
, "print_test_extended", test_print_test_extended
);
8938 torture_tcase_add_simple_test(tcase
, "print_test_smbd", test_print_test_smbd
);
8939 torture_tcase_add_simple_test(tcase
, "print_test_properties", test_print_test_properties
);
8940 torture_tcase_add_simple_test(tcase
, "print_test_purge", test_print_test_purge
);
8941 torture_tcase_add_simple_test(tcase
, "printer_info", test_printer_info
);
8942 torture_tcase_add_simple_test(tcase
, "sd", test_printer_sd
);
8943 torture_tcase_add_simple_test(tcase
, "dm", test_printer_dm
);
8944 torture_tcase_add_simple_test(tcase
, "printer_info_winreg", test_printer_info_winreg
);
8945 torture_tcase_add_simple_test(tcase
, "change_id", test_printer_change_id
);
8946 torture_tcase_add_simple_test(tcase
, "keys", test_printer_keys
);
8947 torture_tcase_add_simple_test(tcase
, "printerdata_consistency", test_printer_data_consistency
);
8948 torture_tcase_add_simple_test(tcase
, "printerdata_keys", test_printer_data_keys
);
8949 torture_tcase_add_simple_test(tcase
, "printerdata_values", test_printer_data_values
);
8950 torture_tcase_add_simple_test(tcase
, "printerdata_set", test_printer_data_set
);
8951 torture_tcase_add_simple_test(tcase
, "printerdata_winreg", test_printer_data_winreg
);
8952 torture_tcase_add_simple_test(tcase
, "printerdata_dsspooler", test_printer_data_dsspooler
);
8953 torture_tcase_add_simple_test(tcase
, "driver_info_winreg", test_driver_info_winreg
);
8954 torture_tcase_add_simple_test(tcase
, "printer_rename", test_printer_rename
);
8955 torture_tcase_add_simple_test(tcase
, "printer_ic", test_printer_ic
);
8956 torture_tcase_add_simple_test(tcase
, "bidi", test_printer_bidi
);
8957 torture_tcase_add_simple_test(tcase
, "publish_toggle",
8958 test_printer_publish_toggle
);
8959 torture_tcase_add_simple_test(tcase
, "print_job_enum", test_print_job_enum
);
8962 struct torture_suite
*torture_rpc_spoolss_printer(TALLOC_CTX
*mem_ctx
)
8964 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "printer");
8965 struct torture_tcase
*tcase
;
8967 tcase
= torture_suite_add_tcase(suite
, "addprinter");
8969 torture_tcase_set_fixture(tcase
,
8970 torture_rpc_spoolss_printer_setup
,
8971 torture_rpc_spoolss_printer_teardown
);
8973 torture_tcase_printer(tcase
);
8975 tcase
= torture_suite_add_tcase(suite
, "addprinterex");
8977 torture_tcase_set_fixture(tcase
,
8978 torture_rpc_spoolss_printerex_setup
,
8979 torture_rpc_spoolss_printer_teardown
);
8981 torture_tcase_printer(tcase
);
8983 tcase
= torture_suite_add_tcase(suite
, "addprinterwkn");
8985 torture_tcase_set_fixture(tcase
,
8986 torture_rpc_spoolss_printerwkn_setup
,
8987 torture_rpc_spoolss_printer_teardown
);
8989 tcase
= torture_suite_add_tcase(suite
, "addprinterexwkn");
8991 torture_tcase_set_fixture(tcase
,
8992 torture_rpc_spoolss_printerexwkn_setup
,
8993 torture_rpc_spoolss_printer_teardown
);
8996 /* test is not correct */
8997 tcase
= torture_suite_add_tcase(suite
, "addprinterdm");
8999 torture_tcase_set_fixture(tcase
,
9000 torture_rpc_spoolss_printerdm_setup
,
9001 torture_rpc_spoolss_printer_teardown
);
9003 torture_tcase_printer(tcase
);
9008 struct torture_suite
*torture_rpc_spoolss(TALLOC_CTX
*mem_ctx
)
9010 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "spoolss");
9011 struct torture_tcase
*tcase
= torture_suite_add_tcase(suite
, "printserver");
9013 torture_tcase_set_fixture(tcase
,
9014 torture_rpc_spoolss_setup
,
9015 torture_rpc_spoolss_teardown
);
9017 torture_tcase_add_simple_test(tcase
, "openprinter_badnamelist", test_OpenPrinter_badname_list
);
9018 torture_tcase_add_simple_test(tcase
, "printer_data_list", test_GetPrinterData_list
);
9019 torture_tcase_add_simple_test(tcase
, "enum_forms", test_PrintServer_EnumForms
);
9020 torture_tcase_add_simple_test(tcase
, "forms", test_PrintServer_Forms
);
9021 torture_tcase_add_simple_test(tcase
, "forms_winreg", test_PrintServer_Forms_Winreg
);
9022 torture_tcase_add_simple_test(tcase
, "enum_ports", test_EnumPorts
);
9023 torture_tcase_add_simple_test(tcase
, "add_port", test_AddPort
);
9024 torture_tcase_add_simple_test(tcase
, "get_printer_driver_directory", test_GetPrinterDriverDirectory
);
9025 torture_tcase_add_simple_test(tcase
, "get_print_processor_directory", test_GetPrintProcessorDirectory
);
9026 torture_tcase_add_simple_test(tcase
, "enum_printer_drivers", test_EnumPrinterDrivers
);
9027 torture_tcase_add_simple_test(tcase
, "enum_monitors", test_EnumMonitors
);
9028 torture_tcase_add_simple_test(tcase
, "enum_print_processors", test_EnumPrintProcessors
);
9029 torture_tcase_add_simple_test(tcase
, "print_processors_winreg", test_print_processors_winreg
);
9030 torture_tcase_add_simple_test(tcase
, "add_processor", test_add_print_processor
);
9031 torture_tcase_add_simple_test(tcase
, "enum_printprocdata", test_EnumPrintProcDataTypes
);
9032 torture_tcase_add_simple_test(tcase
, "enum_printers", test_EnumPrinters
);
9033 torture_tcase_add_simple_test(tcase
, "enum_ports_old", test_EnumPorts_old
);
9034 torture_tcase_add_simple_test(tcase
, "enum_printers_old", test_EnumPrinters_old
);
9035 torture_tcase_add_simple_test(tcase
, "enum_printers_servername", test_EnumPrinters_servername
);
9036 torture_tcase_add_simple_test(tcase
, "enum_printer_drivers_old", test_EnumPrinterDrivers_old
);
9037 torture_tcase_add_simple_test(tcase
, "architecture_buffer", test_architecture_buffer
);
9039 torture_suite_add_suite(suite
, torture_rpc_spoolss_printer(suite
));
9044 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context
*tctx
,
9045 struct dcerpc_binding_handle
*b
,
9047 const char *environment
,
9050 struct spoolss_GetPrinterDriverDirectory r
;
9053 r
.in
.server
= server
;
9054 r
.in
.environment
= environment
;
9058 r
.out
.needed
= &needed
;
9060 torture_assert_ntstatus_ok(tctx
,
9061 dcerpc_spoolss_GetPrinterDriverDirectory_r(b
, tctx
, &r
),
9062 "failed to query driver directory");
9064 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
9065 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
9066 r
.in
.buffer
= &blob
;
9067 r
.in
.offered
= needed
;
9069 torture_assert_ntstatus_ok(tctx
,
9070 dcerpc_spoolss_GetPrinterDriverDirectory_r(b
, tctx
, &r
),
9071 "failed to query driver directory");
9074 torture_assert_werr_ok(tctx
, r
.out
.result
,
9075 "failed to query driver directory");
9078 *dir_p
= r
.out
.info
->info1
.directory_name
;
9084 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr
*info_ctr
)
9086 if (info_ctr
== NULL
) {
9090 switch (info_ctr
->level
) {
9092 return info_ctr
->info
.info1
->driver_name
;
9094 return info_ctr
->info
.info2
->driver_name
;
9096 return info_ctr
->info
.info3
->driver_name
;
9098 return info_ctr
->info
.info4
->driver_name
;
9100 return info_ctr
->info
.info6
->driver_name
;
9102 return info_ctr
->info
.info8
->driver_name
;
9108 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr
*info_ctr
)
9110 if (info_ctr
== NULL
) {
9114 switch (info_ctr
->level
) {
9116 return info_ctr
->info
.info2
->architecture
;
9118 return info_ctr
->info
.info3
->architecture
;
9120 return info_ctr
->info
.info4
->architecture
;
9122 return info_ctr
->info
.info6
->architecture
;
9124 return info_ctr
->info
.info8
->architecture
;
9131 static bool test_AddPrinterDriver_exp(struct torture_context
*tctx
,
9132 struct dcerpc_binding_handle
*b
,
9133 const char *servername
,
9134 struct spoolss_AddDriverInfoCtr
*info_ctr
,
9135 WERROR expected_result
)
9137 struct spoolss_AddPrinterDriver r
;
9138 const char *drivername
= get_driver_from_info(info_ctr
);
9139 const char *environment
= get_environment_from_info(info_ctr
);
9141 r
.in
.servername
= servername
;
9142 r
.in
.info_ctr
= info_ctr
;
9144 torture_comment(tctx
, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
9145 drivername
, info_ctr
->level
, environment
);
9147 torture_assert_ntstatus_ok(tctx
,
9148 dcerpc_spoolss_AddPrinterDriver_r(b
, tctx
, &r
),
9149 "spoolss_AddPrinterDriver failed");
9150 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
9151 "spoolss_AddPrinterDriver failed with unexpected result");
9157 static bool test_AddPrinterDriverEx_exp(struct torture_context
*tctx
,
9158 struct dcerpc_binding_handle
*b
,
9159 const char *servername
,
9160 struct spoolss_AddDriverInfoCtr
*info_ctr
,
9162 WERROR expected_result
)
9164 struct spoolss_AddPrinterDriverEx r
;
9165 const char *drivername
= get_driver_from_info(info_ctr
);
9166 const char *environment
= get_environment_from_info(info_ctr
);
9168 r
.in
.servername
= servername
;
9169 r
.in
.info_ctr
= info_ctr
;
9172 torture_comment(tctx
, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
9173 drivername
, info_ctr
->level
, environment
);
9175 torture_assert_ntstatus_ok(tctx
,
9176 dcerpc_spoolss_AddPrinterDriverEx_r(b
, tctx
, &r
),
9177 "AddPrinterDriverEx failed");
9178 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
9179 "AddPrinterDriverEx failed with unexpected result");
9184 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
9185 if (path && strlen(path)) {\
9186 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
9189 static bool test_AddPrinterDriver_args_level_1(struct torture_context
*tctx
,
9190 struct dcerpc_binding_handle
*b
,
9191 const char *server_name
,
9192 struct spoolss_AddDriverInfo8
*r
,
9195 const char *remote_driver_dir
)
9197 struct spoolss_AddDriverInfoCtr info_ctr
;
9198 struct spoolss_AddDriverInfo1 info1
;
9203 info_ctr
.info
.info1
= &info1
;
9206 torture_assert(tctx
,
9207 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_UNKNOWN_LEVEL
),
9208 "failed to test AddPrinterDriverEx level 1");
9210 torture_assert(tctx
,
9211 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_UNKNOWN_LEVEL
),
9212 "failed to test AddPrinterDriver level 1");
9215 info1
.driver_name
= r
->driver_name
;
9218 torture_assert(tctx
,
9219 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_UNKNOWN_LEVEL
),
9220 "failed to test AddPrinterDriverEx level 1");
9222 torture_assert(tctx
,
9223 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_UNKNOWN_LEVEL
),
9224 "failed to test AddPrinterDriver level 1");
9230 static bool test_AddPrinterDriver_args_level_2(struct torture_context
*tctx
,
9231 struct dcerpc_binding_handle
*b
,
9232 const char *server_name
,
9233 struct spoolss_AddDriverInfo8
*r
,
9236 const char *remote_driver_dir
)
9238 struct spoolss_AddDriverInfoCtr info_ctr
;
9239 struct spoolss_AddDriverInfo2 info2
;
9240 union spoolss_DriverInfo info
;
9245 info_ctr
.info
.info2
= &info2
;
9248 torture_assert(tctx
,
9249 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAM
),
9250 "failed to test AddPrinterDriverEx level 2");
9252 torture_assert(tctx
,
9253 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAM
),
9254 "failed to test AddPrinterDriver level 2");
9257 info2
.driver_name
= r
->driver_name
;
9260 torture_assert(tctx
,
9261 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAM
),
9262 "failed to test AddPrinterDriverEx level 2");
9264 torture_assert(tctx
,
9265 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAM
),
9266 "failed to test AddPrinterDriver level 2");
9269 info2
.version
= r
->version
;
9272 torture_assert(tctx
,
9273 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAM
),
9274 "failed to test AddPrinterDriverEx level 2");
9276 torture_assert(tctx
,
9277 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAM
),
9278 "failed to test AddPrinterDriver level 2");
9281 info2
.architecture
= r
->architecture
;
9284 torture_assert(tctx
,
9285 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAM
),
9286 "failed to test AddPrinterDriverEx level 2");
9288 torture_assert(tctx
,
9289 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAM
),
9290 "failed to test AddPrinterDriver level 2");
9293 info2
.driver_path
= r
->driver_path
;
9296 torture_assert(tctx
,
9297 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAM
),
9298 "failed to test AddPrinterDriverEx level 2");
9300 torture_assert(tctx
,
9301 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAM
),
9302 "failed to test AddPrinterDriver level 2");
9305 info2
.data_file
= r
->data_file
;
9308 torture_assert(tctx
,
9309 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAM
),
9310 "failed to test AddPrinterDriverEx level 2");
9312 torture_assert(tctx
,
9313 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAM
),
9314 "failed to test AddPrinterDriver level 2");
9317 info2
.config_file
= r
->config_file
;
9320 torture_assert(tctx
,
9321 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, 0, WERR_INVALID_PARAM
),
9322 "failed to test AddPrinterDriverEx");
9326 torture_assert(tctx
,
9327 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_OK
),
9328 "failed to test AddPrinterDriverEx level 2");
9330 torture_assert(tctx
,
9331 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_OK
),
9332 "failed to test AddPrinterDriver level 2");
9335 torture_assert(tctx
,
9336 test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, r
->architecture
, 2, r
->driver_name
, &info
),
9337 "failed to find added printer driver");
9339 if (remote_driver_dir
) {
9340 ASSERT_DRIVER_PATH(tctx
, info
.info2
.driver_path
, remote_driver_dir
, "unexpected path");
9341 ASSERT_DRIVER_PATH(tctx
, info
.info2
.data_file
, remote_driver_dir
, "unexpected path");
9342 ASSERT_DRIVER_PATH(tctx
, info
.info2
.config_file
, remote_driver_dir
, "unexpected path");
9348 static bool test_AddPrinterDriver_args_level_3(struct torture_context
*tctx
,
9349 struct dcerpc_binding_handle
*b
,
9350 const char *server_name
,
9351 struct spoolss_AddDriverInfo8
*r
,
9354 const char *remote_driver_dir
)
9356 struct spoolss_AddDriverInfoCtr info_ctr
;
9357 struct spoolss_AddDriverInfo3 info3
;
9358 union spoolss_DriverInfo info
;
9360 info3
.driver_name
= r
->driver_name
;
9361 info3
.version
= r
->version
;
9362 info3
.architecture
= r
->architecture
;
9363 info3
.driver_path
= r
->driver_path
;
9364 info3
.data_file
= r
->data_file
;
9365 info3
.config_file
= r
->config_file
;
9366 info3
.help_file
= r
->help_file
;
9367 info3
.monitor_name
= r
->monitor_name
;
9368 info3
.default_datatype
= r
->default_datatype
;
9369 info3
._ndr_size_dependent_files
= r
->_ndr_size_dependent_files
;
9370 info3
.dependent_files
= r
->dependent_files
;
9373 info_ctr
.info
.info3
= &info3
;
9376 torture_assert(tctx
,
9377 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_OK
),
9378 "failed to test AddPrinterDriverEx level 3");
9380 torture_assert(tctx
,
9381 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_OK
),
9382 "failed to test AddPrinterDriver level 3");
9385 torture_assert(tctx
,
9386 test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, r
->architecture
, 3, r
->driver_name
, &info
),
9387 "failed to find added printer driver");
9389 if (remote_driver_dir
) {
9391 ASSERT_DRIVER_PATH(tctx
, info
.info3
.driver_path
, remote_driver_dir
, "unexpected path");
9392 ASSERT_DRIVER_PATH(tctx
, info
.info3
.data_file
, remote_driver_dir
, "unexpected path");
9393 ASSERT_DRIVER_PATH(tctx
, info
.info3
.config_file
, remote_driver_dir
, "unexpected path");
9394 ASSERT_DRIVER_PATH(tctx
, info
.info3
.help_file
, remote_driver_dir
, "unexpected path");
9395 for (i
=0; info
.info3
.dependent_files
&& info
.info3
.dependent_files
[i
] != NULL
; i
++) {
9396 ASSERT_DRIVER_PATH(tctx
, info
.info3
.dependent_files
[i
], remote_driver_dir
, "unexpected path");
9403 static bool test_AddPrinterDriver_args_level_4(struct torture_context
*tctx
,
9404 struct dcerpc_binding_handle
*b
,
9405 const char *server_name
,
9406 struct spoolss_AddDriverInfo8
*r
,
9409 const char *remote_driver_dir
)
9411 struct spoolss_AddDriverInfoCtr info_ctr
;
9412 struct spoolss_AddDriverInfo4 info4
;
9413 union spoolss_DriverInfo info
;
9415 info4
.version
= r
->version
;
9416 info4
.driver_name
= r
->driver_name
;
9417 info4
.architecture
= r
->architecture
;
9418 info4
.driver_path
= r
->driver_path
;
9419 info4
.data_file
= r
->data_file
;
9420 info4
.config_file
= r
->config_file
;
9421 info4
.help_file
= r
->help_file
;
9422 info4
.monitor_name
= r
->monitor_name
;
9423 info4
.default_datatype
= r
->default_datatype
;
9424 info4
._ndr_size_dependent_files
= r
->_ndr_size_dependent_files
;
9425 info4
.dependent_files
= r
->dependent_files
;
9426 info4
._ndr_size_previous_names
= r
->_ndr_size_previous_names
;
9427 info4
.previous_names
= r
->previous_names
;
9430 info_ctr
.info
.info4
= &info4
;
9433 torture_assert(tctx
,
9434 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_OK
),
9435 "failed to test AddPrinterDriverEx level 4");
9437 torture_assert(tctx
,
9438 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_OK
),
9439 "failed to test AddPrinterDriver level 4");
9442 torture_assert(tctx
,
9443 test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, r
->architecture
, 4, r
->driver_name
, &info
),
9444 "failed to find added printer driver");
9446 if (remote_driver_dir
) {
9448 ASSERT_DRIVER_PATH(tctx
, info
.info4
.driver_path
, remote_driver_dir
, "unexpected path");
9449 ASSERT_DRIVER_PATH(tctx
, info
.info4
.data_file
, remote_driver_dir
, "unexpected path");
9450 ASSERT_DRIVER_PATH(tctx
, info
.info4
.config_file
, remote_driver_dir
, "unexpected path");
9451 ASSERT_DRIVER_PATH(tctx
, info
.info4
.help_file
, remote_driver_dir
, "unexpected path");
9452 for (i
=0; info
.info4
.dependent_files
&& info
.info4
.dependent_files
[i
] != NULL
; i
++) {
9453 ASSERT_DRIVER_PATH(tctx
, info
.info4
.dependent_files
[i
], remote_driver_dir
, "unexpected path");
9460 static bool test_AddPrinterDriver_args_level_6(struct torture_context
*tctx
,
9461 struct dcerpc_binding_handle
*b
,
9462 const char *server_name
,
9463 struct spoolss_AddDriverInfo8
*r
,
9466 const char *remote_driver_dir
)
9468 struct spoolss_AddDriverInfoCtr info_ctr
;
9469 struct spoolss_AddDriverInfo6 info6
;
9470 union spoolss_DriverInfo info
;
9472 info6
.version
= r
->version
;
9473 info6
.driver_name
= r
->driver_name
;
9474 info6
.architecture
= r
->architecture
;
9475 info6
.driver_path
= r
->driver_path
;
9476 info6
.data_file
= r
->data_file
;
9477 info6
.config_file
= r
->config_file
;
9478 info6
.help_file
= r
->help_file
;
9479 info6
.monitor_name
= r
->monitor_name
;
9480 info6
.default_datatype
= r
->default_datatype
;
9481 info6
._ndr_size_dependent_files
= r
->_ndr_size_dependent_files
;
9482 info6
.dependent_files
= r
->dependent_files
;
9483 info6
._ndr_size_previous_names
= r
->_ndr_size_previous_names
;
9484 info6
.previous_names
= r
->previous_names
;
9485 info6
.driver_date
= r
->driver_date
;
9486 info6
.driver_version
= r
->driver_version
;
9487 info6
.manufacturer_name
= r
->manufacturer_name
;
9488 info6
.manufacturer_url
= r
->manufacturer_url
;
9489 info6
.hardware_id
= r
->hardware_id
;
9490 info6
.provider
= r
->provider
;
9493 info_ctr
.info
.info6
= &info6
;
9496 torture_assert(tctx
,
9497 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_OK
),
9498 "failed to test AddPrinterDriverEx level 6");
9500 torture_assert(tctx
,
9501 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_UNKNOWN_LEVEL
),
9502 "failed to test AddPrinterDriver level 6");
9505 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9511 torture_assert(tctx
,
9512 test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, r
->architecture
, 6, r
->driver_name
, &info
),
9513 "failed to find added printer driver");
9515 if (remote_driver_dir
) {
9517 ASSERT_DRIVER_PATH(tctx
, info
.info6
.driver_path
, remote_driver_dir
, "unexpected path");
9518 ASSERT_DRIVER_PATH(tctx
, info
.info6
.data_file
, remote_driver_dir
, "unexpected path");
9519 ASSERT_DRIVER_PATH(tctx
, info
.info6
.config_file
, remote_driver_dir
, "unexpected path");
9520 ASSERT_DRIVER_PATH(tctx
, info
.info6
.help_file
, remote_driver_dir
, "unexpected path");
9521 for (i
=0; info
.info6
.dependent_files
&& info
.info6
.dependent_files
[i
] != NULL
; i
++) {
9522 ASSERT_DRIVER_PATH(tctx
, info
.info6
.dependent_files
[i
], remote_driver_dir
, "unexpected path");
9526 torture_assert_nttime_equal(tctx
, info
.info6
.driver_date
, info6
.driver_date
, "driverdate mismatch");
9527 torture_assert_u64_equal(tctx
, info
.info6
.driver_version
, info6
.driver_version
, "driverversion mismatch");
9532 static bool test_AddPrinterDriver_args_level_8(struct torture_context
*tctx
,
9533 struct dcerpc_binding_handle
*b
,
9534 const char *server_name
,
9535 struct spoolss_AddDriverInfo8
*r
,
9538 const char *remote_driver_dir
)
9540 struct spoolss_AddDriverInfoCtr info_ctr
;
9541 union spoolss_DriverInfo info
;
9544 info_ctr
.info
.info8
= r
;
9547 torture_assert(tctx
,
9548 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_OK
),
9549 "failed to test AddPrinterDriverEx level 8");
9551 torture_assert(tctx
,
9552 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_UNKNOWN_LEVEL
),
9553 "failed to test AddPrinterDriver level 8");
9556 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9562 torture_assert(tctx
,
9563 test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, r
->architecture
, 8, r
->driver_name
, &info
),
9564 "failed to find added printer driver");
9566 if (remote_driver_dir
) {
9568 ASSERT_DRIVER_PATH(tctx
, info
.info8
.driver_path
, remote_driver_dir
, "unexpected path");
9569 ASSERT_DRIVER_PATH(tctx
, info
.info8
.data_file
, remote_driver_dir
, "unexpected path");
9570 ASSERT_DRIVER_PATH(tctx
, info
.info8
.config_file
, remote_driver_dir
, "unexpected path");
9571 ASSERT_DRIVER_PATH(tctx
, info
.info8
.help_file
, remote_driver_dir
, "unexpected path");
9572 for (i
=0; info
.info8
.dependent_files
&& info
.info8
.dependent_files
[i
] != NULL
; i
++) {
9573 ASSERT_DRIVER_PATH(tctx
, info
.info8
.dependent_files
[i
], remote_driver_dir
, "unexpected path");
9577 torture_assert_nttime_equal(tctx
, info
.info8
.driver_date
, r
->driver_date
, "driverdate mismatch");
9578 torture_assert_u64_equal(tctx
, info
.info8
.driver_version
, r
->driver_version
, "driverversion mismatch");
9583 #undef ASSERT_DRIVER_PATH
9585 static bool test_DeletePrinterDriver_exp(struct torture_context
*tctx
,
9586 struct dcerpc_binding_handle
*b
,
9589 const char *environment
,
9590 WERROR expected_result
)
9592 struct spoolss_DeletePrinterDriver r
;
9594 r
.in
.server
= server
;
9595 r
.in
.architecture
= environment
;
9596 r
.in
.driver
= driver
;
9598 torture_comment(tctx
, "Testing DeletePrinterDriver(%s)\n", driver
);
9600 torture_assert_ntstatus_ok(tctx
,
9601 dcerpc_spoolss_DeletePrinterDriver_r(b
, tctx
, &r
),
9602 "DeletePrinterDriver failed");
9603 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
9604 "DeletePrinterDriver failed with unexpected result");
9609 static bool test_DeletePrinterDriverEx_exp(struct torture_context
*tctx
,
9610 struct dcerpc_binding_handle
*b
,
9613 const char *environment
,
9614 uint32_t delete_flags
,
9616 WERROR expected_result
)
9618 struct spoolss_DeletePrinterDriverEx r
;
9620 r
.in
.server
= server
;
9621 r
.in
.architecture
= environment
;
9622 r
.in
.driver
= driver
;
9623 r
.in
.delete_flags
= delete_flags
;
9624 r
.in
.version
= version
;
9626 torture_comment(tctx
, "Testing DeletePrinterDriverEx(%s)\n", driver
);
9628 torture_assert_ntstatus_ok(tctx
,
9629 dcerpc_spoolss_DeletePrinterDriverEx_r(b
, tctx
, &r
),
9630 "DeletePrinterDriverEx failed");
9631 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
9632 "DeletePrinterDriverEx failed with unexpected result");
9637 static bool test_DeletePrinterDriver(struct torture_context
*tctx
,
9638 struct dcerpc_binding_handle
*b
,
9639 const char *server_name
,
9641 const char *environment
)
9643 torture_assert(tctx
,
9644 test_DeletePrinterDriver_exp(tctx
, b
, server_name
, driver
, "FOOBAR", WERR_INVALID_ENVIRONMENT
),
9645 "failed to delete driver");
9647 torture_assert(tctx
,
9648 test_DeletePrinterDriver_exp(tctx
, b
, server_name
, driver
, environment
, WERR_OK
),
9649 "failed to delete driver");
9651 if (test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, environment
, 1, driver
, NULL
)) {
9652 torture_fail(tctx
, "deleted driver still enumerated");
9655 torture_assert(tctx
,
9656 test_DeletePrinterDriver_exp(tctx
, b
, server_name
, driver
, environment
, WERR_UNKNOWN_PRINTER_DRIVER
),
9657 "2nd delete failed");
9662 static bool test_DeletePrinterDriverEx(struct torture_context
*tctx
,
9663 struct dcerpc_binding_handle
*b
,
9664 const char *server_name
,
9666 const char *environment
,
9667 uint32_t delete_flags
,
9670 torture_assert(tctx
,
9671 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name
, driver
, "FOOBAR", delete_flags
, version
, WERR_INVALID_ENVIRONMENT
),
9672 "failed to delete driver");
9674 torture_assert(tctx
,
9675 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name
, driver
, environment
, delete_flags
, version
, WERR_OK
),
9676 "failed to delete driver");
9678 if (test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, environment
, 1, driver
, NULL
)) {
9679 torture_fail(tctx
, "deleted driver still enumerated");
9682 torture_assert(tctx
,
9683 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name
, driver
, environment
, delete_flags
, version
, WERR_UNKNOWN_PRINTER_DRIVER
),
9684 "2nd delete failed");
9689 static bool test_PrinterDriver_args(struct torture_context
*tctx
,
9690 struct dcerpc_binding_handle
*b
,
9691 const char *server_name
,
9693 struct spoolss_AddDriverInfo8
*r
,
9695 uint32_t delete_flags
,
9696 uint32_t delete_version
,
9698 const char *remote_driver_dir
)
9704 ret
= test_AddPrinterDriver_args_level_1(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
9707 ret
= test_AddPrinterDriver_args_level_2(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
9710 ret
= test_AddPrinterDriver_args_level_3(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
9713 ret
= test_AddPrinterDriver_args_level_4(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
9716 ret
= test_AddPrinterDriver_args_level_6(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
9719 ret
= test_AddPrinterDriver_args_level_8(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
9733 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9735 if (!ex
&& (level
== 6 || level
== 8)) {
9740 struct dcerpc_pipe
*p2
;
9741 struct policy_handle hive_handle
;
9742 struct dcerpc_binding_handle
*b2
;
9744 torture_assert_ntstatus_ok(tctx
,
9745 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
9746 "could not open winreg pipe");
9747 b2
= p2
->binding_handle
;
9749 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
9751 ret
= test_GetDriverInfo_winreg(tctx
, b
, NULL
, NULL
, r
->driver_name
, r
->architecture
, r
->version
, b2
, &hive_handle
, server_name
);
9753 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
9759 return test_DeletePrinterDriverEx(tctx
, b
, server_name
, r
->driver_name
, r
->architecture
, delete_flags
, r
->version
);
9761 return test_DeletePrinterDriver(tctx
, b
, server_name
, r
->driver_name
, r
->architecture
);
9765 static bool fillup_printserver_info(struct torture_context
*tctx
,
9766 struct dcerpc_pipe
*p
,
9767 struct torture_driver_context
*d
)
9769 struct policy_handle server_handle
;
9770 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
9771 const char *server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
9773 torture_assert(tctx
,
9774 test_OpenPrinter_server(tctx
, p
, &server_handle
),
9775 "failed to open printserver");
9776 torture_assert(tctx
,
9777 test_get_environment(tctx
, b
, &server_handle
, &d
->remote
.environment
),
9778 "failed to get environment");
9779 torture_assert(tctx
,
9780 test_ClosePrinter(tctx
, b
, &server_handle
),
9781 "failed to close printserver");
9783 torture_assert(tctx
,
9784 test_GetPrinterDriverDirectory_getdir(tctx
, b
, server_name_slash
,
9785 d
->local
.environment
? d
->local
.environment
: d
->remote
.environment
,
9786 &d
->remote
.driver_directory
),
9787 "failed to get driver directory");
9792 static const char *driver_directory_dir(const char *driver_directory
)
9796 p
= strrchr(driver_directory
, '\\');
9804 static const char *driver_directory_share(struct torture_context
*tctx
,
9805 const char *driver_directory
)
9810 if (driver_directory
[0] == '\\' && driver_directory
[1] == '\\') {
9811 driver_directory
+= 2;
9814 p
= talloc_strdup(tctx
, driver_directory
);
9816 torture_assert(tctx
,
9817 next_token_talloc(tctx
, &p
, &tok
, "\\"),
9818 "cannot explode uri");
9819 torture_assert(tctx
,
9820 next_token_talloc(tctx
, &p
, &tok
, "\\"),
9821 "cannot explode uri");
9826 static bool upload_printer_driver_file(struct torture_context
*tctx
,
9827 struct smbcli_state
*cli
,
9828 struct torture_driver_context
*d
,
9829 const char *file_name
)
9834 int maxwrite
= 64512;
9837 const char *remote_dir
= driver_directory_dir(d
->remote
.driver_directory
);
9838 const char *local_name
= talloc_asprintf(tctx
, "%s/%s", d
->local
.driver_directory
, file_name
);
9839 const char *remote_name
= talloc_asprintf(tctx
, "%s\\%s", remote_dir
, file_name
);
9841 if (!file_name
|| strlen(file_name
) == 0) {
9845 torture_comment(tctx
, "Uploading %s to %s\n", local_name
, remote_name
);
9847 fnum
= smbcli_open(cli
->tree
, remote_name
, O_RDWR
|O_CREAT
|O_TRUNC
, DENY_NONE
);
9849 torture_fail(tctx
, talloc_asprintf(tctx
, "failed to open remote file: %s\n", remote_name
));
9852 f
= x_fopen(local_name
, O_RDONLY
, 0);
9854 torture_fail(tctx
, talloc_asprintf(tctx
, "failed to open local file: %s\n", local_name
));
9857 buf
= talloc_array(tctx
, uint8_t, maxwrite
);
9863 while (!x_feof(f
)) {
9867 if ((n
= x_fread(buf
, 1, n
, f
)) < 1) {
9868 if((n
== 0) && x_feof(f
))
9869 break; /* Empty local file. */
9871 torture_warning(tctx
,
9872 "failed to read file: %s\n", strerror(errno
));
9876 ret
= smbcli_write(cli
->tree
, fnum
, 0, buf
, nread
+ start
, n
);
9879 torture_warning(tctx
,
9880 "failed to write file: %s\n", smbcli_errstr(cli
->tree
));
9889 torture_assert_ntstatus_ok(tctx
,
9890 smbcli_close(cli
->tree
, fnum
),
9891 "failed to close file");
9896 static bool connect_printer_driver_share(struct torture_context
*tctx
,
9897 const char *server_name
,
9898 const char *share_name
,
9899 struct smbcli_state
**cli
)
9901 struct smbcli_options smb_options
;
9902 struct smbcli_session_options smb_session_options
;
9904 torture_comment(tctx
, "Connecting printer driver share '%s' on '%s'\n",
9905 share_name
, server_name
);
9907 lpcfg_smbcli_options(tctx
->lp_ctx
, &smb_options
);
9908 lpcfg_smbcli_session_options(tctx
->lp_ctx
, &smb_session_options
);
9910 torture_assert_ntstatus_ok(tctx
,
9911 smbcli_full_connection(tctx
, cli
, server_name
,
9912 lpcfg_smb_ports(tctx
->lp_ctx
),
9914 lpcfg_socket_options(tctx
->lp_ctx
),
9915 cmdline_credentials
,
9916 lpcfg_resolve_context(tctx
->lp_ctx
),
9919 &smb_session_options
,
9920 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
)),
9921 "failed to open driver share");
9926 static bool upload_printer_driver(struct torture_context
*tctx
,
9927 const char *server_name
,
9928 struct torture_driver_context
*d
)
9930 struct smbcli_state
*cli
;
9931 const char *share_name
= driver_directory_share(tctx
, d
->remote
.driver_directory
);
9934 torture_assert(tctx
,
9935 connect_printer_driver_share(tctx
, server_name
, share_name
, &cli
),
9936 "failed to connect to driver share");
9938 torture_comment(tctx
, "Uploading printer driver files to \\\\%s\\%s\n",
9939 server_name
, share_name
);
9941 torture_assert(tctx
,
9942 upload_printer_driver_file(tctx
, cli
, d
, d
->info8
.driver_path
),
9943 "failed to upload driver_path");
9944 torture_assert(tctx
,
9945 upload_printer_driver_file(tctx
, cli
, d
, d
->info8
.data_file
),
9946 "failed to upload data_file");
9947 torture_assert(tctx
,
9948 upload_printer_driver_file(tctx
, cli
, d
, d
->info8
.config_file
),
9949 "failed to upload config_file");
9950 torture_assert(tctx
,
9951 upload_printer_driver_file(tctx
, cli
, d
, d
->info8
.help_file
),
9952 "failed to upload help_file");
9953 if (d
->info8
.dependent_files
) {
9954 for (i
=0; d
->info8
.dependent_files
->string
&& d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
9955 torture_assert(tctx
,
9956 upload_printer_driver_file(tctx
, cli
, d
, d
->info8
.dependent_files
->string
[i
]),
9957 "failed to upload dependent_files");
9966 static bool check_printer_driver_file(struct torture_context
*tctx
,
9967 struct smbcli_state
*cli
,
9968 struct torture_driver_context
*d
,
9969 const char *file_name
)
9971 const char *remote_arch_dir
= driver_directory_dir(d
->remote
.driver_directory
);
9972 const char *remote_name
= talloc_asprintf(tctx
, "%s\\%d\\%s",
9978 torture_assert(tctx
, (file_name
&& strlen(file_name
) != 0), "invalid filename");
9980 torture_comment(tctx
, "checking for driver file at %s\n", remote_name
);
9982 fnum
= smbcli_open(cli
->tree
, remote_name
, O_RDONLY
, DENY_NONE
);
9987 torture_assert_ntstatus_ok(tctx
,
9988 smbcli_close(cli
->tree
, fnum
),
9989 "failed to close driver file");
9994 static bool check_printer_driver_files(struct torture_context
*tctx
,
9995 const char *server_name
,
9996 struct torture_driver_context
*d
,
9999 struct smbcli_state
*cli
;
10000 const char *share_name
= driver_directory_share(tctx
, d
->remote
.driver_directory
);
10003 torture_assert(tctx
,
10004 connect_printer_driver_share(tctx
, server_name
, share_name
, &cli
),
10005 "failed to connect to driver share");
10007 torture_comment(tctx
, "checking %sexistent driver files at \\\\%s\\%s\n",
10008 (expect_exist
? "": "non-"),
10009 server_name
, share_name
);
10011 if (d
->info8
.driver_path
&& d
->info8
.driver_path
[0]) {
10012 torture_assert(tctx
,
10013 check_printer_driver_file(tctx
, cli
, d
, d
->info8
.driver_path
) == expect_exist
,
10014 "failed driver_path check");
10016 if (d
->info8
.data_file
&& d
->info8
.data_file
[0]) {
10017 torture_assert(tctx
,
10018 check_printer_driver_file(tctx
, cli
, d
, d
->info8
.data_file
) == expect_exist
,
10019 "failed data_file check");
10021 if (d
->info8
.config_file
&& d
->info8
.config_file
[0]) {
10022 torture_assert(tctx
,
10023 check_printer_driver_file(tctx
, cli
, d
, d
->info8
.config_file
) == expect_exist
,
10024 "failed config_file check");
10026 if (d
->info8
.help_file
&& d
->info8
.help_file
[0]) {
10027 torture_assert(tctx
,
10028 check_printer_driver_file(tctx
, cli
, d
, d
->info8
.help_file
) == expect_exist
,
10029 "failed help_file check");
10031 if (d
->info8
.dependent_files
) {
10032 for (i
=0; d
->info8
.dependent_files
->string
&& d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
10033 torture_assert(tctx
,
10034 check_printer_driver_file(tctx
, cli
, d
, d
->info8
.dependent_files
->string
[i
]) == expect_exist
,
10035 "failed dependent_files check");
10044 static bool remove_printer_driver_file(struct torture_context
*tctx
,
10045 struct smbcli_state
*cli
,
10046 struct torture_driver_context
*d
,
10047 const char *file_name
)
10049 const char *remote_name
;
10050 const char *remote_dir
= driver_directory_dir(d
->remote
.driver_directory
);
10052 if (!file_name
|| strlen(file_name
) == 0) {
10056 remote_name
= talloc_asprintf(tctx
, "%s\\%s", remote_dir
, file_name
);
10058 torture_comment(tctx
, "Removing %s\n", remote_name
);
10060 torture_assert_ntstatus_ok(tctx
,
10061 smbcli_unlink(cli
->tree
, remote_name
),
10062 "failed to unlink");
10067 static bool remove_printer_driver(struct torture_context
*tctx
,
10068 const char *server_name
,
10069 struct torture_driver_context
*d
)
10071 struct smbcli_state
*cli
;
10072 const char *share_name
= driver_directory_share(tctx
, d
->remote
.driver_directory
);
10075 torture_assert(tctx
,
10076 connect_printer_driver_share(tctx
, server_name
, share_name
, &cli
),
10077 "failed to connect to driver share");
10079 torture_comment(tctx
, "Removing printer driver files from \\\\%s\\%s\n",
10080 server_name
, share_name
);
10082 torture_assert(tctx
,
10083 remove_printer_driver_file(tctx
, cli
, d
, d
->info8
.driver_path
),
10084 "failed to remove driver_path");
10085 torture_assert(tctx
,
10086 remove_printer_driver_file(tctx
, cli
, d
, d
->info8
.data_file
),
10087 "failed to remove data_file");
10088 if (!strequal(d
->info8
.config_file
, d
->info8
.driver_path
)) {
10089 torture_assert(tctx
,
10090 remove_printer_driver_file(tctx
, cli
, d
, d
->info8
.config_file
),
10091 "failed to remove config_file");
10093 torture_assert(tctx
,
10094 remove_printer_driver_file(tctx
, cli
, d
, d
->info8
.help_file
),
10095 "failed to remove help_file");
10096 if (d
->info8
.dependent_files
) {
10097 for (i
=0; d
->info8
.dependent_files
->string
&& d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
10098 if (strequal(d
->info8
.dependent_files
->string
[i
], d
->info8
.driver_path
) ||
10099 strequal(d
->info8
.dependent_files
->string
[i
], d
->info8
.data_file
) ||
10100 strequal(d
->info8
.dependent_files
->string
[i
], d
->info8
.config_file
) ||
10101 strequal(d
->info8
.dependent_files
->string
[i
], d
->info8
.help_file
)) {
10104 torture_assert(tctx
,
10105 remove_printer_driver_file(tctx
, cli
, d
, d
->info8
.dependent_files
->string
[i
]),
10106 "failed to remove dependent_files");
10116 static bool test_add_driver_arg(struct torture_context
*tctx
,
10117 struct dcerpc_pipe
*p
,
10118 struct torture_driver_context
*d
)
10121 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
10122 const char *server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
10123 uint32_t levels
[] = { 1, 2, 3, 4, 6, 8 };
10125 struct spoolss_AddDriverInfo8 info8
;
10126 uint32_t add_flags
= APD_COPY_NEW_FILES
;
10127 uint32_t delete_flags
= 0;
10129 ZERO_STRUCT(info8
);
10131 torture_comment(tctx
, "Testing PrinterDriver%s '%s' for environment '%s'\n",
10132 d
->ex
? "Ex" : "", d
->info8
.driver_name
, d
->local
.environment
);
10134 torture_assert(tctx
,
10135 fillup_printserver_info(tctx
, p
, d
),
10136 "failed to fillup printserver info");
10138 if (!directory_exist(d
->local
.driver_directory
)) {
10139 torture_skip(tctx
, "Skipping Printer Driver test as no local driver is available");
10142 torture_assert(tctx
,
10143 upload_printer_driver(tctx
, dcerpc_server_name(p
), d
),
10144 "failed to upload printer driver");
10147 if (d
->info8
.dependent_files
) {
10148 info8
.dependent_files
= talloc_zero(tctx
, struct spoolss_StringArray
);
10149 if (d
->info8
.dependent_files
->string
) {
10150 for (i
=0; d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
10152 info8
.dependent_files
->string
= talloc_zero_array(info8
.dependent_files
, const char *, i
+1);
10153 for (i
=0; d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
10154 info8
.dependent_files
->string
[i
] = talloc_strdup(info8
.dependent_files
->string
, d
->info8
.dependent_files
->string
[i
]);
10158 info8
.architecture
= d
->local
.environment
;
10160 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
10162 if (torture_setting_bool(tctx
, "samba3", false)) {
10163 switch (levels
[i
]) {
10167 torture_comment(tctx
, "skipping level %d against samba\n", levels
[i
]);
10173 if (torture_setting_bool(tctx
, "w2k3", false)) {
10174 switch (levels
[i
]) {
10176 torture_comment(tctx
, "skipping level %d against w2k3\n", levels
[i
]);
10183 torture_comment(tctx
,
10184 "Testing PrinterDriver%s '%s' add & delete level %d\n",
10185 d
->ex
? "Ex" : "", info8
.driver_name
, levels
[i
]);
10187 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
);
10190 info8
.driver_path
= talloc_asprintf(tctx
, "%s\\%s", d
->remote
.driver_directory
, d
->info8
.driver_path
);
10191 info8
.data_file
= talloc_asprintf(tctx
, "%s\\%s", d
->remote
.driver_directory
, d
->info8
.data_file
);
10192 if (d
->info8
.config_file
) {
10193 info8
.config_file
= talloc_asprintf(tctx
, "%s\\%s", d
->remote
.driver_directory
, d
->info8
.config_file
);
10195 if (d
->info8
.help_file
) {
10196 info8
.help_file
= talloc_asprintf(tctx
, "%s\\%s", d
->remote
.driver_directory
, d
->info8
.help_file
);
10198 if (d
->info8
.dependent_files
&& d
->info8
.dependent_files
->string
) {
10199 for (i
=0; d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
10200 info8
.dependent_files
->string
[i
] = talloc_asprintf(tctx
, "%s\\%s", d
->remote
.driver_directory
, d
->info8
.dependent_files
->string
[i
]);
10204 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
10206 if (torture_setting_bool(tctx
, "samba3", false)) {
10207 switch (levels
[i
]) {
10211 torture_comment(tctx
, "skipping level %d against samba\n", levels
[i
]);
10217 if (torture_setting_bool(tctx
, "w2k3", false)) {
10218 switch (levels
[i
]) {
10220 torture_comment(tctx
, "skipping level %d against w2k3\n", levels
[i
]);
10227 torture_comment(tctx
,
10228 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
10229 d
->ex
? "Ex" : "", info8
.driver_name
, levels
[i
]);
10231 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
);
10234 torture_assert(tctx
,
10235 remove_printer_driver(tctx
, dcerpc_server_name(p
), d
),
10236 "failed to remove printer driver");
10238 torture_comment(tctx
, "\n");
10243 static bool test_add_driver_ex_64(struct torture_context
*tctx
,
10244 struct dcerpc_pipe
*p
)
10246 struct torture_driver_context
*d
;
10248 d
= talloc_zero(tctx
, struct torture_driver_context
);
10250 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
10251 d
->info8
.driver_name
= TORTURE_DRIVER_EX
;
10252 d
->info8
.architecture
= NULL
;
10253 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
10254 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
10255 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
10256 d
->local
.environment
= talloc_strdup(d
, "Windows x64");
10257 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/x64");
10260 return test_add_driver_arg(tctx
, p
, d
);
10263 static bool test_add_driver_ex_32(struct torture_context
*tctx
,
10264 struct dcerpc_pipe
*p
)
10266 struct torture_driver_context
*d
;
10268 d
= talloc_zero(tctx
, struct torture_driver_context
);
10270 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
10271 d
->info8
.driver_name
= TORTURE_DRIVER_EX
;
10272 d
->info8
.architecture
= NULL
;
10273 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
10274 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
10275 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
10276 d
->local
.environment
= talloc_strdup(d
, "Windows NT x86");
10277 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/i386");
10280 return test_add_driver_arg(tctx
, p
, d
);
10283 static bool test_add_driver_64(struct torture_context
*tctx
,
10284 struct dcerpc_pipe
*p
)
10286 struct torture_driver_context
*d
;
10288 d
= talloc_zero(tctx
, struct torture_driver_context
);
10290 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
10291 d
->info8
.driver_name
= TORTURE_DRIVER
;
10292 d
->info8
.architecture
= NULL
;
10293 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
10294 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
10295 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
10296 d
->local
.environment
= talloc_strdup(d
, "Windows x64");
10297 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/x64");
10300 return test_add_driver_arg(tctx
, p
, d
);
10303 static bool test_add_driver_32(struct torture_context
*tctx
,
10304 struct dcerpc_pipe
*p
)
10306 struct torture_driver_context
*d
;
10308 d
= talloc_zero(tctx
, struct torture_driver_context
);
10310 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
10311 d
->info8
.driver_name
= TORTURE_DRIVER
;
10312 d
->info8
.architecture
= NULL
;
10313 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
10314 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
10315 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
10316 d
->local
.environment
= talloc_strdup(d
, "Windows NT x86");
10317 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/i386");
10320 return test_add_driver_arg(tctx
, p
, d
);
10323 static bool test_add_driver_adobe(struct torture_context
*tctx
,
10324 struct dcerpc_pipe
*p
)
10326 struct torture_driver_context
*d
;
10328 if (!torture_setting_bool(tctx
, "samba3", false)) {
10329 torture_skip(tctx
, "skipping adobe test which only works against samba3");
10332 d
= talloc_zero(tctx
, struct torture_driver_context
);
10334 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_9X
;
10335 d
->info8
.driver_name
= TORTURE_DRIVER_ADOBE
;
10336 d
->info8
.architecture
= NULL
;
10337 d
->info8
.driver_path
= talloc_strdup(d
, "ADOBEPS4.DRV");
10338 d
->info8
.data_file
= talloc_strdup(d
, "DEFPRTR2.PPD");
10339 d
->info8
.config_file
= talloc_strdup(d
, "ADOBEPS4.DRV");
10341 d
->info8
.help_file
= talloc_strdup(d
, "ADOBEPS4.HLP");
10342 d
->info8
.monitor_name
= talloc_strdup(d
, "PSMON.DLL");
10344 d
->local
.environment
= talloc_strdup(d
, "Windows 4.0");
10345 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/adobe/");
10348 return test_add_driver_arg(tctx
, p
, d
);
10351 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context
*tctx
,
10352 struct dcerpc_pipe
*p
)
10354 struct torture_driver_context
*d
;
10355 struct spoolss_StringArray
*a
;
10357 if (!torture_setting_bool(tctx
, "samba3", false)) {
10358 torture_skip(tctx
, "skipping cupsaddsmb test which only works against samba3");
10361 d
= talloc_zero(tctx
, struct torture_driver_context
);
10363 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_9X
;
10364 d
->info8
.driver_name
= TORTURE_DRIVER_ADOBE_CUPSADDSMB
;
10365 d
->info8
.architecture
= NULL
;
10366 d
->info8
.driver_path
= talloc_strdup(d
, "ADOBEPS4.DRV");
10367 d
->info8
.data_file
= talloc_strdup(d
, "DEFPRTR2.PPD");
10368 d
->info8
.config_file
= NULL
;
10369 d
->info8
.help_file
= talloc_strdup(d
, "ADOBEPS4.HLP");
10370 d
->info8
.monitor_name
= talloc_strdup(d
, "PSMON.DLL");
10371 d
->info8
.default_datatype
= talloc_strdup(d
, "RAW");
10373 a
= talloc_zero(d
, struct spoolss_StringArray
);
10374 a
->string
= talloc_zero_array(a
, const char *, 7);
10375 a
->string
[0] = talloc_strdup(a
->string
, "ADOBEPS4.DRV");
10376 a
->string
[1] = talloc_strdup(a
->string
, "DEFPRTR2.PPD");
10377 a
->string
[2] = talloc_strdup(a
->string
, "ADOBEPS4.HLP");
10378 a
->string
[3] = talloc_strdup(a
->string
, "PSMON.DLL");
10379 a
->string
[4] = talloc_strdup(a
->string
, "ADFONTS.MFM");
10380 a
->string
[5] = talloc_strdup(a
->string
, "ICONLIB.DLL");
10382 d
->info8
.dependent_files
= a
;
10383 d
->local
.environment
= talloc_strdup(d
, "Windows 4.0");
10384 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/adobe/");
10387 return test_add_driver_arg(tctx
, p
, d
);
10390 static bool test_add_driver_timestamps(struct torture_context
*tctx
,
10391 struct dcerpc_pipe
*p
)
10393 struct torture_driver_context
*d
;
10394 struct timeval t
= timeval_current();
10396 d
= talloc_zero(tctx
, struct torture_driver_context
);
10398 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
10399 d
->info8
.driver_name
= TORTURE_DRIVER_TIMESTAMPS
;
10400 d
->info8
.architecture
= NULL
;
10401 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
10402 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
10403 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
10404 d
->info8
.driver_date
= timeval_to_nttime(&t
);
10405 d
->local
.environment
= talloc_strdup(d
, "Windows NT x86");
10406 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/i386");
10409 torture_assert(tctx
,
10410 test_add_driver_arg(tctx
, p
, d
),
10413 unix_to_nt_time(&d
->info8
.driver_date
, 1);
10415 torture_assert(tctx
,
10416 test_add_driver_arg(tctx
, p
, d
),
10422 static bool test_multiple_drivers(struct torture_context
*tctx
,
10423 struct dcerpc_pipe
*p
)
10425 struct torture_driver_context
*d
;
10426 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
10427 const char *server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
10429 struct spoolss_AddDriverInfo8 info8
;
10430 uint32_t add_flags
= APD_COPY_NEW_FILES
;
10431 uint32_t delete_flags
= 0;
10433 d
= talloc_zero(tctx
, struct torture_driver_context
);
10435 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
10436 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
10437 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
10438 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
10439 d
->local
.environment
= talloc_strdup(d
, "Windows NT x86");
10440 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/i386");
10443 torture_assert(tctx
,
10444 fillup_printserver_info(tctx
, p
, d
),
10445 "failed to fillup printserver info");
10447 if (!directory_exist(d
->local
.driver_directory
)) {
10448 torture_skip(tctx
, "Skipping Printer Driver test as no local driver is available");
10451 torture_assert(tctx
,
10452 upload_printer_driver(tctx
, dcerpc_server_name(p
), d
),
10453 "failed to upload printer driver");
10456 info8
.architecture
= d
->local
.environment
;
10458 for (i
=0; i
< 3; i
++) {
10459 info8
.driver_name
= talloc_asprintf(d
, "torture_test_driver_%d", i
);
10461 torture_assert(tctx
,
10462 test_AddPrinterDriver_args_level_3(tctx
, b
, server_name_slash
, &info8
, add_flags
, true, NULL
),
10463 "failed to add driver");
10466 torture_assert(tctx
,
10467 test_DeletePrinterDriverEx(tctx
, b
, server_name_slash
, "torture_test_driver_0", info8
.architecture
, delete_flags
, info8
.version
),
10468 "failed to delete driver");
10470 torture_assert(tctx
,
10471 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, info8
.architecture
, 3, "torture_test_driver_1", NULL
),
10472 "torture_test_driver_1 no longer on the server");
10474 torture_assert(tctx
,
10475 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, info8
.architecture
, 3, "torture_test_driver_2", NULL
),
10476 "torture_test_driver_2 no longer on the server");
10478 torture_assert(tctx
,
10479 test_DeletePrinterDriverEx(tctx
, b
, server_name_slash
, "torture_test_driver_1", info8
.architecture
, delete_flags
, info8
.version
),
10480 "failed to delete driver");
10482 torture_assert(tctx
,
10483 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, info8
.architecture
, 3, "torture_test_driver_2", NULL
),
10484 "torture_test_driver_2 no longer on the server");
10486 torture_assert(tctx
,
10487 test_DeletePrinterDriverEx(tctx
, b
, server_name_slash
, "torture_test_driver_2", info8
.architecture
, delete_flags
, info8
.version
),
10488 "failed to delete driver");
10490 torture_assert(tctx
,
10491 remove_printer_driver(tctx
, dcerpc_server_name(p
), d
),
10492 "failed to remove printer driver");
10497 static bool test_del_driver_all_files(struct torture_context
*tctx
,
10498 struct dcerpc_pipe
*p
)
10500 struct torture_driver_context
*d
;
10501 struct spoolss_StringArray
*a
;
10502 uint32_t add_flags
= APD_COPY_NEW_FILES
;
10503 uint32_t delete_flags
= DPD_DELETE_ALL_FILES
;
10504 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
10505 const char *server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
10507 d
= talloc_zero(tctx
, struct torture_driver_context
);
10510 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
10511 d
->info8
.driver_name
= TORTURE_DRIVER_DELETER
;
10512 d
->info8
.architecture
= NULL
;
10513 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
10514 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
10515 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
10516 d
->info8
.help_file
= talloc_strdup(d
, "pscript.hlp");
10517 d
->local
.environment
= talloc_strdup(d
, SPOOLSS_ARCHITECTURE_x64
);
10518 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/x64");
10520 a
= talloc_zero(d
, struct spoolss_StringArray
);
10521 a
->string
= talloc_zero_array(a
, const char *, 3);
10522 a
->string
[0] = talloc_strdup(a
->string
, "cups6.inf");
10523 a
->string
[1] = talloc_strdup(a
->string
, "cups6.ini");
10525 d
->info8
.dependent_files
= a
;
10526 d
->info8
.architecture
= d
->local
.environment
;
10528 torture_assert(tctx
,
10529 fillup_printserver_info(tctx
, p
, d
),
10530 "failed to fillup printserver info");
10532 if (!directory_exist(d
->local
.driver_directory
)) {
10533 torture_skip(tctx
, "Skipping Printer Driver test as no local driver is available");
10536 torture_assert(tctx
,
10537 upload_printer_driver(tctx
, dcerpc_server_name(p
), d
),
10538 "failed to upload printer driver");
10540 torture_assert(tctx
,
10541 test_AddPrinterDriver_args_level_3(tctx
, b
, server_name_slash
, &d
->info8
, add_flags
, true, NULL
),
10542 "failed to add driver");
10544 torture_assert(tctx
,
10545 test_DeletePrinterDriverEx(tctx
, b
, server_name_slash
,
10546 d
->info8
.driver_name
,
10547 d
->local
.environment
,
10550 "failed to delete driver");
10552 torture_assert(tctx
,
10553 check_printer_driver_files(tctx
, dcerpc_server_name(p
), d
, false),
10554 "printer driver file check failed");
10560 static bool test_del_driver_unused_files(struct torture_context
*tctx
,
10561 struct dcerpc_pipe
*p
)
10563 struct torture_driver_context
*d1
;
10564 struct torture_driver_context
*d2
;
10565 uint32_t add_flags
= APD_COPY_NEW_FILES
;
10566 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
10567 const char *server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
10569 d1
= talloc_zero(tctx
, struct torture_driver_context
);
10571 d1
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
10572 d1
->info8
.driver_name
= TORTURE_DRIVER_DELETER
;
10573 d1
->info8
.architecture
= NULL
;
10574 d1
->info8
.driver_path
= talloc_strdup(d1
, "pscript5.dll");
10575 d1
->info8
.data_file
= talloc_strdup(d1
, "cups6.ppd");
10576 d1
->info8
.config_file
= talloc_strdup(d1
, "cupsui6.dll");
10577 d1
->info8
.help_file
= talloc_strdup(d1
, "pscript.hlp");
10578 d1
->local
.environment
= talloc_strdup(d1
, SPOOLSS_ARCHITECTURE_x64
);
10579 d1
->local
.driver_directory
= talloc_strdup(d1
, "/usr/share/cups/drivers/x64");
10580 d1
->info8
.architecture
= d1
->local
.environment
;
10582 d2
= talloc_zero(tctx
, struct torture_driver_context
);
10584 d2
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
10585 d2
->info8
.driver_name
= TORTURE_DRIVER_DELETERIN
;
10586 d2
->info8
.architecture
= NULL
;
10587 d2
->info8
.driver_path
= talloc_strdup(d2
, "pscript5.dll"); /* overlapping */
10588 d2
->info8
.data_file
= talloc_strdup(d2
, "cupsps6.dll");
10589 d2
->info8
.config_file
= talloc_strdup(d2
, "cups6.ini");
10590 d2
->info8
.help_file
= talloc_strdup(d2
, "pscript.hlp"); /* overlapping */
10591 d2
->local
.environment
= talloc_strdup(d2
, SPOOLSS_ARCHITECTURE_x64
);
10592 d2
->local
.driver_directory
= talloc_strdup(d2
, "/usr/share/cups/drivers/x64");
10593 d2
->info8
.architecture
= d2
->local
.environment
;
10595 torture_assert(tctx
,
10596 fillup_printserver_info(tctx
, p
, d1
),
10597 "failed to fillup printserver info");
10598 torture_assert(tctx
,
10599 fillup_printserver_info(tctx
, p
, d2
),
10600 "failed to fillup printserver info");
10602 if (!directory_exist(d1
->local
.driver_directory
)) {
10603 torture_skip(tctx
, "Skipping Printer Driver test as no local driver is available");
10606 torture_assert(tctx
,
10607 upload_printer_driver(tctx
, dcerpc_server_name(p
), d1
),
10608 "failed to upload printer driver");
10609 torture_assert(tctx
,
10610 test_AddPrinterDriver_args_level_3(tctx
, b
, server_name_slash
, &d1
->info8
, add_flags
, true, NULL
),
10611 "failed to add driver");
10613 torture_assert(tctx
,
10614 upload_printer_driver(tctx
, dcerpc_server_name(p
), d2
),
10615 "failed to upload printer driver");
10616 torture_assert(tctx
,
10617 test_AddPrinterDriver_args_level_3(tctx
, b
, server_name_slash
, &d2
->info8
, add_flags
, true, NULL
),
10618 "failed to add driver");
10620 /* some files are in use by a separate driver, should fail */
10621 torture_assert(tctx
,
10622 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name_slash
,
10623 d1
->info8
.driver_name
,
10624 d1
->local
.environment
,
10625 DPD_DELETE_ALL_FILES
,
10627 WERR_PRINTER_DRIVER_IN_USE
),
10628 "invalid delete driver response");
10630 /* should only delete files not in use by other driver */
10631 torture_assert(tctx
,
10632 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name_slash
,
10633 d1
->info8
.driver_name
,
10634 d1
->local
.environment
,
10635 DPD_DELETE_UNUSED_FILES
,
10638 "failed to delete driver (unused files)");
10640 /* check non-overlapping were deleted */
10641 d1
->info8
.driver_path
= NULL
;
10642 d1
->info8
.help_file
= NULL
;
10643 torture_assert(tctx
,
10644 check_printer_driver_files(tctx
, dcerpc_server_name(p
), d1
, false),
10645 "printer driver file check failed");
10646 /* d2 files should be uneffected */
10647 torture_assert(tctx
,
10648 check_printer_driver_files(tctx
, dcerpc_server_name(p
), d2
, true),
10649 "printer driver file check failed");
10651 torture_assert(tctx
,
10652 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name_slash
,
10653 d2
->info8
.driver_name
,
10654 d2
->local
.environment
,
10655 DPD_DELETE_ALL_FILES
,
10658 "failed to delete driver");
10660 torture_assert(tctx
,
10661 check_printer_driver_files(tctx
, dcerpc_server_name(p
), d2
, false),
10662 "printer driver file check failed");
10669 struct torture_suite
*torture_rpc_spoolss_driver(TALLOC_CTX
*mem_ctx
)
10671 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "spoolss.driver");
10673 struct torture_rpc_tcase
*tcase
= torture_suite_add_rpc_iface_tcase(suite
,
10674 "driver", &ndr_table_spoolss
);
10675 torture_rpc_tcase_add_test(tcase
, "add_driver_64", test_add_driver_64
);
10676 torture_rpc_tcase_add_test(tcase
, "add_driver_ex_64", test_add_driver_ex_64
);
10678 torture_rpc_tcase_add_test(tcase
, "add_driver_32", test_add_driver_32
);
10679 torture_rpc_tcase_add_test(tcase
, "add_driver_ex_32", test_add_driver_ex_32
);
10681 torture_rpc_tcase_add_test(tcase
, "add_driver_adobe", test_add_driver_adobe
);
10683 torture_rpc_tcase_add_test(tcase
, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb
);
10685 torture_rpc_tcase_add_test(tcase
, "add_driver_timestamps", test_add_driver_timestamps
);
10687 torture_rpc_tcase_add_test(tcase
, "multiple_drivers", test_multiple_drivers
);
10689 torture_rpc_tcase_add_test(tcase
, "del_driver_all_files", test_del_driver_all_files
);
10691 torture_rpc_tcase_add_test(tcase
, "del_driver_unused_files", test_del_driver_unused_files
);