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
,
3259 union spoolss_JobInfo
**info_p
)
3262 struct spoolss_EnumJobs r
;
3265 union spoolss_JobInfo
*info
;
3267 r
.in
.handle
= handle
;
3269 r
.in
.numjobs
= 0xffffffff;
3273 r
.out
.needed
= &needed
;
3274 r
.out
.count
= &count
;
3277 torture_comment(tctx
, "Testing EnumJobs level %d\n", level
);
3279 status
= dcerpc_spoolss_EnumJobs_r(b
, tctx
, &r
);
3281 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
3283 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
3284 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
3285 r
.in
.buffer
= &blob
;
3286 r
.in
.offered
= needed
;
3288 status
= dcerpc_spoolss_EnumJobs_r(b
, tctx
, &r
);
3290 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
3291 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumJobs failed");
3292 torture_assert(tctx
, info
, "No jobs returned");
3294 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs
, *r
.out
.info
, r
.in
.level
, count
, needed
, 4);
3297 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumJobs failed");
3310 static bool test_JobPropertiesEnum(struct torture_context
*tctx
,
3311 struct dcerpc_binding_handle
*b
,
3312 struct policy_handle
*handle
,
3315 struct spoolss_RpcEnumJobNamedProperties r
;
3316 uint32_t pcProperties
= 0;
3317 struct RPC_PrintNamedProperty
*ppProperties
= NULL
;
3319 r
.in
.hPrinter
= handle
;
3320 r
.in
.JobId
= job_id
;
3321 r
.out
.pcProperties
= &pcProperties
;
3322 r
.out
.ppProperties
= &ppProperties
;
3324 torture_comment(tctx
, "Testing RpcEnumJobNamedProperties(%d)\n", job_id
);
3326 torture_assert_ntstatus_ok(tctx
,
3327 dcerpc_spoolss_RpcEnumJobNamedProperties_r(b
, tctx
, &r
),
3328 "spoolss_RpcEnumJobNamedProperties failed");
3329 torture_assert_werr_ok(tctx
, r
.out
.result
,
3330 "spoolss_RpcEnumJobNamedProperties failed");
3335 static bool test_JobPropertySet(struct torture_context
*tctx
,
3336 struct dcerpc_binding_handle
*b
,
3337 struct policy_handle
*handle
,
3339 struct RPC_PrintNamedProperty
*property
)
3341 struct spoolss_RpcSetJobNamedProperty r
;
3343 r
.in
.hPrinter
= handle
;
3344 r
.in
.JobId
= job_id
;
3345 r
.in
.pProperty
= property
;
3347 torture_comment(tctx
, "Testing RpcSetJobNamedProperty(%d) %s - %d\n",
3348 job_id
, property
->propertyName
,
3349 property
->propertyValue
.ePropertyType
);
3351 torture_assert_ntstatus_ok(tctx
,
3352 dcerpc_spoolss_RpcSetJobNamedProperty_r(b
, tctx
, &r
),
3353 "spoolss_RpcSetJobNamedProperty failed");
3354 torture_assert_werr_ok(tctx
, r
.out
.result
,
3355 "spoolss_RpcSetJobNamedProperty failed");
3360 static bool test_JobPropertyGetValue(struct torture_context
*tctx
,
3361 struct dcerpc_binding_handle
*b
,
3362 struct policy_handle
*handle
,
3364 const char *property_name
,
3365 struct RPC_PrintPropertyValue
*value
)
3367 struct spoolss_RpcGetJobNamedPropertyValue r
;
3369 r
.in
.hPrinter
= handle
;
3370 r
.in
.JobId
= job_id
;
3371 r
.in
.pszName
= property_name
;
3372 r
.out
.pValue
= value
;
3374 torture_comment(tctx
, "Testing RpcGetJobNamedPropertyValue(%d) %s\n",
3375 job_id
, property_name
);
3377 torture_assert_ntstatus_ok(tctx
,
3378 dcerpc_spoolss_RpcGetJobNamedPropertyValue_r(b
, tctx
, &r
),
3379 "spoolss_RpcGetJobNamedPropertyValue failed");
3380 torture_assert_werr_ok(tctx
, r
.out
.result
,
3381 "spoolss_RpcGetJobNamedPropertyValue failed");
3386 static bool test_JobPropertyDelete(struct torture_context
*tctx
,
3387 struct dcerpc_binding_handle
*b
,
3388 struct policy_handle
*handle
,
3390 const char *property_name
)
3392 struct spoolss_RpcDeleteJobNamedProperty r
;
3394 r
.in
.hPrinter
= handle
;
3395 r
.in
.JobId
= job_id
;
3396 r
.in
.pszName
= property_name
;
3398 torture_comment(tctx
, "Testing RpcDeleteJobNamedProperty(%d) %s\n",
3399 job_id
, property_name
);
3401 torture_assert_ntstatus_ok(tctx
,
3402 dcerpc_spoolss_RpcDeleteJobNamedProperty_r(b
, tctx
, &r
),
3403 "spoolss_RpcDeleteJobNamedProperty failed");
3404 torture_assert_werr_ok(tctx
, r
.out
.result
,
3405 "spoolss_RpcDeleteJobNamedProperty failed");
3410 static bool test_DoPrintTest_add_one_job_common(struct torture_context
*tctx
,
3411 struct dcerpc_binding_handle
*b
,
3412 struct policy_handle
*handle
,
3413 const char *document_name
,
3414 const char *datatype
,
3418 struct spoolss_StartDocPrinter s
;
3419 struct spoolss_DocumentInfoCtr info_ctr
;
3420 struct spoolss_DocumentInfo1 info1
;
3421 struct spoolss_StartPagePrinter sp
;
3422 struct spoolss_WritePrinter w
;
3423 struct spoolss_EndPagePrinter ep
;
3424 struct spoolss_EndDocPrinter e
;
3426 uint32_t num_written
;
3428 torture_comment(tctx
, "Testing StartDocPrinter\n");
3430 s
.in
.handle
= handle
;
3431 s
.in
.info_ctr
= &info_ctr
;
3432 s
.out
.job_id
= job_id
;
3434 info1
.document_name
= document_name
;
3435 info1
.output_file
= NULL
;
3436 info1
.datatype
= datatype
;
3439 info_ctr
.info
.info1
= &info1
;
3441 status
= dcerpc_spoolss_StartDocPrinter_r(b
, tctx
, &s
);
3442 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_StartDocPrinter failed");
3443 torture_assert_werr_ok(tctx
, s
.out
.result
, "StartDocPrinter failed");
3445 for (i
=1; i
< 4; i
++) {
3446 torture_comment(tctx
, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i
, *job_id
);
3448 sp
.in
.handle
= handle
;
3450 status
= dcerpc_spoolss_StartPagePrinter_r(b
, tctx
, &sp
);
3451 torture_assert_ntstatus_ok(tctx
, status
,
3452 "dcerpc_spoolss_StartPagePrinter failed");
3453 torture_assert_werr_ok(tctx
, sp
.out
.result
, "StartPagePrinter failed");
3455 torture_comment(tctx
, "Testing WritePrinter: Page[%d], JobId[%d]\n", i
, *job_id
);
3457 w
.in
.handle
= handle
;
3458 w
.in
.data
= data_blob_string_const(talloc_asprintf(tctx
,"TortureTestPage: %d\nData\n",i
));
3459 w
.out
.num_written
= &num_written
;
3461 status
= dcerpc_spoolss_WritePrinter_r(b
, tctx
, &w
);
3462 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_WritePrinter failed");
3463 torture_assert_werr_ok(tctx
, w
.out
.result
, "WritePrinter failed");
3465 torture_comment(tctx
, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i
, *job_id
);
3467 ep
.in
.handle
= handle
;
3469 status
= dcerpc_spoolss_EndPagePrinter_r(b
, tctx
, &ep
);
3470 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndPagePrinter failed");
3471 torture_assert_werr_ok(tctx
, ep
.out
.result
, "EndPagePrinter failed");
3474 torture_comment(tctx
, "Testing EndDocPrinter: JobId[%d]\n", *job_id
);
3476 e
.in
.handle
= handle
;
3478 status
= dcerpc_spoolss_EndDocPrinter_r(b
, tctx
, &e
);
3479 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndDocPrinter failed");
3480 torture_assert_werr_ok(tctx
, e
.out
.result
, "EndDocPrinter failed");
3485 static bool test_DoPrintTest_add_one_job(struct torture_context
*tctx
,
3486 struct dcerpc_binding_handle
*b
,
3487 struct policy_handle
*handle
,
3488 const char *document_name
,
3491 test_DoPrintTest_add_one_job_common(tctx
, b
, handle
, document_name
, "RAW", job_id
);
3496 static bool test_DoPrintTest_add_one_job_v4(struct torture_context
*tctx
,
3497 struct dcerpc_binding_handle
*b
,
3498 struct policy_handle
*handle
,
3499 const char *document_name
,
3502 test_DoPrintTest_add_one_job_common(tctx
, b
, handle
, document_name
, "XPS_PASS", job_id
);
3508 static bool test_DoPrintTest_check_jobs(struct torture_context
*tctx
,
3509 struct dcerpc_binding_handle
*b
,
3510 struct policy_handle
*handle
,
3515 union spoolss_JobInfo
*info
= NULL
;
3518 torture_assert(tctx
,
3519 test_AddJob(tctx
, b
, handle
),
3522 torture_assert(tctx
,
3523 test_EnumJobs_args(tctx
, b
, handle
, 1, &count
, &info
),
3524 "EnumJobs level 1 failed");
3526 torture_assert_int_equal(tctx
, count
, num_jobs
, "unexpected number of jobs in queue");
3528 for (i
=0; i
< num_jobs
; i
++) {
3529 union spoolss_JobInfo ginfo
;
3530 const char *document_name
;
3531 const char *new_document_name
= "any_other_docname";
3532 struct spoolss_JobInfoContainer ctr
;
3533 struct spoolss_SetJobInfo1 info1
;
3535 torture_assert_int_equal(tctx
, info
[i
].info1
.job_id
, job_ids
[i
], "job id mismatch");
3537 torture_assert(tctx
,
3538 test_GetJob_args(tctx
, b
, handle
, info
[i
].info1
.job_id
, 1, &ginfo
),
3539 "failed to call test_GetJob");
3541 torture_assert_int_equal(tctx
, ginfo
.info1
.job_id
, info
[i
].info1
.job_id
, "job id mismatch");
3543 document_name
= ginfo
.info1
.document_name
;
3545 info1
.job_id
= ginfo
.info1
.job_id
;
3546 info1
.printer_name
= ginfo
.info1
.printer_name
;
3547 info1
.server_name
= ginfo
.info1
.server_name
;
3548 info1
.user_name
= ginfo
.info1
.user_name
;
3549 info1
.document_name
= new_document_name
;
3550 info1
.data_type
= ginfo
.info1
.data_type
;
3551 info1
.text_status
= ginfo
.info1
.text_status
;
3552 info1
.status
= ginfo
.info1
.status
;
3553 info1
.priority
= ginfo
.info1
.priority
;
3554 info1
.position
= ginfo
.info1
.position
;
3555 info1
.total_pages
= ginfo
.info1
.total_pages
;
3556 info1
.pages_printed
= ginfo
.info1
.pages_printed
;
3557 info1
.submitted
= ginfo
.info1
.submitted
;
3560 ctr
.info
.info1
= &info1
;
3562 torture_assert(tctx
,
3563 test_SetJob(tctx
, b
, handle
, info
[i
].info1
.job_id
, &ctr
, 0),
3564 "failed to call test_SetJob level 1");
3566 torture_assert(tctx
,
3567 test_GetJob_args(tctx
, b
, handle
, info
[i
].info1
.job_id
, 1, &ginfo
),
3568 "failed to call test_GetJob");
3570 if (strequal(ginfo
.info1
.document_name
, document_name
)) {
3571 torture_warning(tctx
,
3572 "document_name did *NOT* change from '%s' to '%s'\n",
3573 document_name
, new_document_name
);
3577 for (i
=0; i
< num_jobs
; i
++) {
3578 if (!test_SetJob(tctx
, b
, handle
, info
[i
].info1
.job_id
, NULL
, SPOOLSS_JOB_CONTROL_PAUSE
)) {
3579 torture_warning(tctx
, "failed to pause printjob\n");
3581 if (!test_SetJob(tctx
, b
, handle
, info
[i
].info1
.job_id
, NULL
, SPOOLSS_JOB_CONTROL_RESUME
)) {
3582 torture_warning(tctx
, "failed to resume printjob\n");
3589 static bool test_DoPrintTest(struct torture_context
*tctx
,
3590 struct dcerpc_binding_handle
*b
,
3591 struct policy_handle
*handle
)
3594 uint32_t num_jobs
= 8;
3598 torture_comment(tctx
, "Testing real print operations\n");
3600 job_ids
= talloc_zero_array(tctx
, uint32_t, num_jobs
);
3602 for (i
=0; i
< num_jobs
; i
++) {
3603 ret
&= test_DoPrintTest_add_one_job(tctx
, b
, handle
, "TorturePrintJob", &job_ids
[i
]);
3606 for (i
=0; i
< num_jobs
; i
++) {
3607 ret
&= test_SetJob(tctx
, b
, handle
, job_ids
[i
], NULL
, SPOOLSS_JOB_CONTROL_DELETE
);
3610 for (i
=0; i
< num_jobs
; i
++) {
3611 ret
&= test_DoPrintTest_add_one_job_v4(tctx
, b
, handle
, "TorturePrintJob v4", &job_ids
[i
]);
3614 for (i
=0; i
< num_jobs
; i
++) {
3615 ret
&= test_SetJob(tctx
, b
, handle
, job_ids
[i
], NULL
, SPOOLSS_JOB_CONTROL_DELETE
);
3619 torture_comment(tctx
, "real print operations test succeeded\n\n");
3625 static bool test_DoPrintTest_extended(struct torture_context
*tctx
,
3626 struct dcerpc_binding_handle
*b
,
3627 struct policy_handle
*handle
)
3630 uint32_t num_jobs
= 8;
3633 torture_comment(tctx
, "Testing real print operations (extended)\n");
3635 job_ids
= talloc_zero_array(tctx
, uint32_t, num_jobs
);
3637 for (i
=0; i
< num_jobs
; i
++) {
3638 ret
&= test_DoPrintTest_add_one_job(tctx
, b
, handle
, "TorturePrintJob", &job_ids
[i
]);
3641 ret
&= test_DoPrintTest_check_jobs(tctx
, b
, handle
, num_jobs
, job_ids
);
3643 for (i
=0; i
< num_jobs
; i
++) {
3644 ret
&= test_SetJob(tctx
, b
, handle
, job_ids
[i
], NULL
, SPOOLSS_JOB_CONTROL_DELETE
);
3648 torture_comment(tctx
, "real print operations (extended) test succeeded\n\n");
3654 static bool test_JobPrintProperties_equal(struct torture_context
*tctx
,
3655 struct RPC_PrintPropertyValue
*got
,
3656 struct RPC_PrintNamedProperty
*exp
)
3658 torture_assert_int_equal(tctx
,
3660 exp
->propertyValue
.ePropertyType
,
3663 switch (exp
->propertyValue
.ePropertyType
) {
3664 case kRpcPropertyTypeString
:
3665 torture_assert_str_equal(tctx
,
3666 got
->value
.propertyString
,
3667 exp
->propertyValue
.value
.propertyString
,
3670 case kRpcPropertyTypeInt32
:
3671 torture_assert_int_equal(tctx
,
3672 got
->value
.propertyInt32
,
3673 exp
->propertyValue
.value
.propertyInt32
,
3676 case kRpcPropertyTypeInt64
:
3677 torture_assert_u64_equal(tctx
,
3678 got
->value
.propertyInt64
,
3679 exp
->propertyValue
.value
.propertyInt64
,
3682 case kRpcPropertyTypeByte
:
3683 torture_assert_int_equal(tctx
,
3684 got
->value
.propertyByte
,
3685 exp
->propertyValue
.value
.propertyByte
,
3688 case kRpcPropertyTypeBuffer
:
3689 torture_assert_int_equal(tctx
,
3690 got
->value
.propertyBlob
.cbBuf
,
3691 exp
->propertyValue
.value
.propertyBlob
.cbBuf
,
3692 "propertyBlob.cbBuf");
3693 torture_assert_mem_equal(tctx
,
3694 got
->value
.propertyBlob
.pBuf
,
3695 exp
->propertyValue
.value
.propertyBlob
.pBuf
,
3696 exp
->propertyValue
.value
.propertyBlob
.cbBuf
,
3697 "propertyBlob.pBuf");
3706 static bool test_JobPrintProperties(struct torture_context
*tctx
,
3707 struct dcerpc_binding_handle
*b
,
3708 struct policy_handle
*handle
,
3711 struct RPC_PrintNamedProperty in
;
3712 struct RPC_PrintPropertyValue out
;
3714 DATA_BLOB blob
= data_blob_string_const("blob");
3716 const char *property_name
;
3717 enum RPC_EPrintPropertyType type
;
3718 union RPC_PrintPropertyValueUnion value
;
3719 WERROR expected_result
;
3722 .property_name
= "torture_property_string",
3723 .type
= kRpcPropertyTypeString
,
3724 .value
.propertyString
= "torture_property_value_string",
3726 .property_name
= "torture_property_int32",
3727 .type
= kRpcPropertyTypeInt32
,
3728 .value
.propertyInt32
= 42,
3730 .property_name
= "torture_property_int64",
3731 .type
= kRpcPropertyTypeInt64
,
3732 .value
.propertyInt64
= 0xaffe,
3734 .property_name
= "torture_property_byte",
3735 .type
= kRpcPropertyTypeByte
,
3736 .value
.propertyByte
= 0xab,
3738 .property_name
= "torture_property_buffer",
3739 .type
= kRpcPropertyTypeBuffer
,
3740 .value
.propertyBlob
.cbBuf
= blob
.length
,
3741 .value
.propertyBlob
.pBuf
= blob
.data
,
3745 torture_assert(tctx
,
3746 test_JobPropertiesEnum(tctx
, b
, handle
, job_id
),
3747 "failed to enum properties");
3749 for (i
=0; i
<ARRAY_SIZE(tests
); i
++) {
3751 in
.propertyName
= tests
[i
].property_name
;
3752 in
.propertyValue
.ePropertyType
= tests
[i
].type
;
3753 in
.propertyValue
.value
= tests
[i
].value
;
3755 torture_assert(tctx
,
3756 test_JobPropertySet(tctx
, b
, handle
, job_id
, &in
),
3757 "failed to set property");
3759 torture_assert(tctx
,
3760 test_JobPropertyGetValue(tctx
, b
, handle
, job_id
, in
.propertyName
, &out
),
3761 "failed to get property");
3763 torture_assert(tctx
,
3764 test_JobPrintProperties_equal(tctx
, &out
, &in
),
3765 "property unequal");
3767 torture_assert(tctx
,
3768 test_JobPropertiesEnum(tctx
, b
, handle
, job_id
),
3769 "failed to enum properties");
3771 torture_assert(tctx
,
3772 test_JobPropertyDelete(tctx
, b
, handle
, job_id
, in
.propertyName
),
3773 "failed to delete job property");
3776 torture_assert(tctx
,
3777 test_JobPropertiesEnum(tctx
, b
, handle
, job_id
),
3778 "failed to enum properties");
3783 static bool test_DoPrintTest_properties(struct torture_context
*tctx
,
3784 struct dcerpc_binding_handle
*b
,
3785 struct policy_handle
*handle
)
3787 uint32_t num_jobs
= 8;
3790 torture_comment(tctx
, "Testing real print operations (properties)\n");
3792 job_ids
= talloc_zero_array(tctx
, uint32_t, num_jobs
);
3794 for (i
=0; i
< num_jobs
; i
++) {
3795 torture_assert(tctx
,
3796 test_DoPrintTest_add_one_job(tctx
, b
, handle
, "TorturePrintJob", &job_ids
[i
]),
3797 "failed to create print job");
3800 for (i
=0; i
< num_jobs
; i
++) {
3801 torture_assert(tctx
,
3802 test_JobPrintProperties(tctx
, b
, handle
, job_ids
[i
]),
3803 "failed to test job properties");
3807 for (i
=0; i
< num_jobs
; i
++) {
3808 torture_assert(tctx
,
3809 test_SetJob(tctx
, b
, handle
, job_ids
[i
], NULL
, SPOOLSS_JOB_CONTROL_DELETE
),
3810 "failed to delete printjob");
3813 torture_comment(tctx
, "real print operations (properties) test succeeded\n\n");
3818 static bool test_PausePrinter(struct torture_context
*tctx
,
3819 struct dcerpc_binding_handle
*b
,
3820 struct policy_handle
*handle
)
3823 struct spoolss_SetPrinter r
;
3824 struct spoolss_SetPrinterInfoCtr info_ctr
;
3825 struct spoolss_DevmodeContainer devmode_ctr
;
3826 struct sec_desc_buf secdesc_ctr
;
3829 info_ctr
.info
.info0
= NULL
;
3831 ZERO_STRUCT(devmode_ctr
);
3832 ZERO_STRUCT(secdesc_ctr
);
3834 r
.in
.handle
= handle
;
3835 r
.in
.info_ctr
= &info_ctr
;
3836 r
.in
.devmode_ctr
= &devmode_ctr
;
3837 r
.in
.secdesc_ctr
= &secdesc_ctr
;
3838 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
3840 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3842 status
= dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
);
3844 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
3846 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
3851 static bool test_ResumePrinter(struct torture_context
*tctx
,
3852 struct dcerpc_binding_handle
*b
,
3853 struct policy_handle
*handle
)
3856 struct spoolss_SetPrinter r
;
3857 struct spoolss_SetPrinterInfoCtr info_ctr
;
3858 struct spoolss_DevmodeContainer devmode_ctr
;
3859 struct sec_desc_buf secdesc_ctr
;
3862 info_ctr
.info
.info0
= NULL
;
3864 ZERO_STRUCT(devmode_ctr
);
3865 ZERO_STRUCT(secdesc_ctr
);
3867 r
.in
.handle
= handle
;
3868 r
.in
.info_ctr
= &info_ctr
;
3869 r
.in
.devmode_ctr
= &devmode_ctr
;
3870 r
.in
.secdesc_ctr
= &secdesc_ctr
;
3871 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
3873 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3875 status
= dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
);
3877 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
3879 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
3884 static bool test_printer_purge(struct torture_context
*tctx
,
3885 struct dcerpc_binding_handle
*b
,
3886 struct policy_handle
*handle
)
3889 struct spoolss_SetPrinter r
;
3890 struct spoolss_SetPrinterInfoCtr info_ctr
;
3891 struct spoolss_DevmodeContainer devmode_ctr
;
3892 struct sec_desc_buf secdesc_ctr
;
3895 info_ctr
.info
.info0
= NULL
;
3897 ZERO_STRUCT(devmode_ctr
);
3898 ZERO_STRUCT(secdesc_ctr
);
3900 r
.in
.handle
= handle
;
3901 r
.in
.info_ctr
= &info_ctr
;
3902 r
.in
.devmode_ctr
= &devmode_ctr
;
3903 r
.in
.secdesc_ctr
= &secdesc_ctr
;
3904 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_PURGE
;
3906 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PURGE\n");
3908 status
= dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
);
3909 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
3910 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
3915 static bool test_GetPrinterData_checktype(struct torture_context
*tctx
,
3916 struct dcerpc_binding_handle
*b
,
3917 struct policy_handle
*handle
,
3918 const char *value_name
,
3919 enum winreg_Type
*expected_type
,
3920 enum winreg_Type
*type_p
,
3925 struct spoolss_GetPrinterData r
;
3927 enum winreg_Type type
;
3928 union spoolss_PrinterData data
;
3930 r
.in
.handle
= handle
;
3931 r
.in
.value_name
= value_name
;
3933 r
.out
.needed
= &needed
;
3935 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
3937 torture_comment(tctx
, "Testing GetPrinterData(%s)\n", r
.in
.value_name
);
3939 status
= dcerpc_spoolss_GetPrinterData_r(b
, tctx
, &r
);
3940 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
3942 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
3943 if (expected_type
) {
3944 torture_assert_int_equal(tctx
, type
, *expected_type
, "unexpected type");
3946 r
.in
.offered
= needed
;
3947 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
3948 status
= dcerpc_spoolss_GetPrinterData_r(b
, tctx
, &r
);
3949 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
3952 torture_assert_werr_ok(tctx
, r
.out
.result
,
3953 talloc_asprintf(tctx
, "GetPrinterData(%s) failed", r
.in
.value_name
));
3955 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData
, &data
, type
, needed
, 1);
3962 *data_p
= r
.out
.data
;
3972 static bool test_GetPrinterData(struct torture_context
*tctx
,
3973 struct dcerpc_binding_handle
*b
,
3974 struct policy_handle
*handle
,
3975 const char *value_name
,
3976 enum winreg_Type
*type_p
,
3980 return test_GetPrinterData_checktype(tctx
, b
, handle
, value_name
,
3981 NULL
, type_p
, data_p
, needed_p
);
3984 static bool test_GetPrinterDataEx_checktype(struct torture_context
*tctx
,
3985 struct dcerpc_pipe
*p
,
3986 struct policy_handle
*handle
,
3987 const char *key_name
,
3988 const char *value_name
,
3989 enum winreg_Type
*expected_type
,
3990 enum winreg_Type
*type_p
,
3995 struct spoolss_GetPrinterDataEx r
;
3996 enum winreg_Type type
;
3998 union spoolss_PrinterData data
;
3999 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4001 r
.in
.handle
= handle
;
4002 r
.in
.key_name
= key_name
;
4003 r
.in
.value_name
= value_name
;
4006 r
.out
.needed
= &needed
;
4007 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
4009 torture_comment(tctx
, "Testing GetPrinterDataEx(%s - %s)\n",
4010 r
.in
.key_name
, r
.in
.value_name
);
4012 status
= dcerpc_spoolss_GetPrinterDataEx_r(b
, tctx
, &r
);
4013 if (!NT_STATUS_IS_OK(status
)) {
4014 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
4015 torture_skip(tctx
, "GetPrinterDataEx not supported by server\n");
4017 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
4020 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
4021 if (expected_type
) {
4022 torture_assert_int_equal(tctx
, type
, *expected_type
, "unexpected type");
4024 r
.in
.offered
= needed
;
4025 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
4026 status
= dcerpc_spoolss_GetPrinterDataEx_r(b
, tctx
, &r
);
4027 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
4030 torture_assert_werr_ok(tctx
, r
.out
.result
,
4031 talloc_asprintf(tctx
, "GetPrinterDataEx(%s - %s) failed", r
.in
.key_name
, r
.in
.value_name
));
4033 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData
, &data
, type
, needed
, 1);
4040 *data_p
= r
.out
.data
;
4050 static bool test_GetPrinterDataEx(struct torture_context
*tctx
,
4051 struct dcerpc_pipe
*p
,
4052 struct policy_handle
*handle
,
4053 const char *key_name
,
4054 const char *value_name
,
4055 enum winreg_Type
*type_p
,
4059 return test_GetPrinterDataEx_checktype(tctx
, p
, handle
, key_name
, value_name
,
4060 NULL
, type_p
, data_p
, needed_p
);
4063 static bool test_get_environment(struct torture_context
*tctx
,
4064 struct dcerpc_binding_handle
*b
,
4065 struct policy_handle
*handle
,
4066 const char **architecture
)
4069 enum winreg_Type type
;
4073 torture_assert(tctx
,
4074 test_GetPrinterData(tctx
, b
, handle
, "Architecture", &type
, &data
, &needed
),
4075 "failed to get Architecture");
4077 torture_assert_int_equal(tctx
, type
, REG_SZ
, "unexpected type");
4079 blob
= data_blob_const(data
, needed
);
4080 *architecture
= reg_val_data_string(tctx
, REG_SZ
, blob
);
4085 static bool test_GetPrinterData_list(struct torture_context
*tctx
,
4088 struct test_spoolss_context
*ctx
=
4089 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
4090 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
4091 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4092 const char *list
[] = {
4096 /* "NetPopup", not on w2k8 */
4097 /* "NetPopupToComputer", not on w2k8 */
4100 "DefaultSpoolDirectory",
4104 /* "OSVersionEx", not on s3 */
4109 for (i
=0; i
< ARRAY_SIZE(list
); i
++) {
4110 enum winreg_Type type
, type_ex
;
4111 uint8_t *data
, *data_ex
;
4112 uint32_t needed
, needed_ex
;
4114 torture_assert(tctx
, test_GetPrinterData(tctx
, b
, &ctx
->server_handle
, list
[i
], &type
, &data
, &needed
),
4115 talloc_asprintf(tctx
, "GetPrinterData failed on %s\n", list
[i
]));
4116 torture_assert(tctx
, test_GetPrinterDataEx(tctx
, p
, &ctx
->server_handle
, "random_string", list
[i
], &type_ex
, &data_ex
, &needed_ex
),
4117 talloc_asprintf(tctx
, "GetPrinterDataEx failed on %s\n", list
[i
]));
4118 torture_assert_int_equal(tctx
, type
, type_ex
, "type mismatch");
4119 torture_assert_int_equal(tctx
, needed
, needed_ex
, "needed mismatch");
4120 torture_assert_mem_equal(tctx
, data
, data_ex
, needed
, "data mismatch");
4126 static bool test_EnumPrinterData(struct torture_context
*tctx
,
4127 struct dcerpc_pipe
*p
,
4128 struct policy_handle
*handle
,
4129 uint32_t enum_index
,
4130 uint32_t value_offered
,
4131 uint32_t data_offered
,
4132 enum winreg_Type
*type_p
,
4133 uint32_t *value_needed_p
,
4134 uint32_t *data_needed_p
,
4135 const char **value_name_p
,
4139 struct spoolss_EnumPrinterData r
;
4140 uint32_t data_needed
;
4141 uint32_t value_needed
;
4142 enum winreg_Type type
;
4143 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4145 r
.in
.handle
= handle
;
4146 r
.in
.enum_index
= enum_index
;
4147 r
.in
.value_offered
= value_offered
;
4148 r
.in
.data_offered
= data_offered
;
4149 r
.out
.data_needed
= &data_needed
;
4150 r
.out
.value_needed
= &value_needed
;
4152 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.data_offered
);
4153 r
.out
.value_name
= talloc_zero_array(tctx
, const char, r
.in
.value_offered
);
4155 torture_comment(tctx
, "Testing EnumPrinterData(%d)\n", enum_index
);
4157 torture_assert_ntstatus_ok(tctx
,
4158 dcerpc_spoolss_EnumPrinterData_r(b
, tctx
, &r
),
4159 "EnumPrinterData failed");
4164 if (value_needed_p
) {
4165 *value_needed_p
= value_needed
;
4167 if (data_needed_p
) {
4168 *data_needed_p
= data_needed
;
4171 *value_name_p
= r
.out
.value_name
;
4174 *data_p
= r
.out
.data
;
4177 *result_p
= r
.out
.result
;
4184 static bool test_EnumPrinterData_all(struct torture_context
*tctx
,
4185 struct dcerpc_pipe
*p
,
4186 struct policy_handle
*handle
)
4188 uint32_t enum_index
= 0;
4189 enum winreg_Type type
;
4190 uint32_t value_needed
;
4191 uint32_t data_needed
;
4193 const char *value_name
;
4196 torture_comment(tctx
, "Testing EnumPrinterData\n");
4199 torture_assert(tctx
,
4200 test_EnumPrinterData(tctx
, p
, handle
, enum_index
, 0, 0,
4201 &type
, &value_needed
, &data_needed
,
4202 &value_name
, &data
, &result
),
4203 "EnumPrinterData failed");
4205 if (W_ERROR_EQUAL(result
, WERR_NO_MORE_ITEMS
)) {
4209 torture_assert(tctx
,
4210 test_EnumPrinterData(tctx
, p
, handle
, enum_index
, value_needed
, data_needed
,
4211 &type
, &value_needed
, &data_needed
,
4212 &value_name
, &data
, &result
),
4213 "EnumPrinterData failed");
4215 if (W_ERROR_EQUAL(result
, WERR_NO_MORE_ITEMS
)) {
4221 } while (W_ERROR_IS_OK(result
));
4223 torture_comment(tctx
, "EnumPrinterData test succeeded\n");
4228 static bool test_EnumPrinterDataEx(struct torture_context
*tctx
,
4229 struct dcerpc_binding_handle
*b
,
4230 struct policy_handle
*handle
,
4231 const char *key_name
,
4233 struct spoolss_PrinterEnumValues
**info_p
)
4235 struct spoolss_EnumPrinterDataEx r
;
4236 struct spoolss_PrinterEnumValues
*info
;
4240 r
.in
.handle
= handle
;
4241 r
.in
.key_name
= key_name
;
4243 r
.out
.needed
= &needed
;
4244 r
.out
.count
= &count
;
4247 torture_comment(tctx
, "Testing EnumPrinterDataEx(%s)\n", key_name
);
4249 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterDataEx_r(b
, tctx
, &r
),
4250 "EnumPrinterDataEx failed");
4251 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
4252 r
.in
.offered
= needed
;
4253 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterDataEx_r(b
, tctx
, &r
),
4254 "EnumPrinterDataEx failed");
4257 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDataEx failed");
4259 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx
, info
, count
, needed
, 1);
4271 static bool test_SetPrinterData(struct torture_context
*tctx
,
4272 struct dcerpc_binding_handle
*b
,
4273 struct policy_handle
*handle
,
4274 const char *value_name
,
4275 enum winreg_Type type
,
4278 static bool test_DeletePrinterData(struct torture_context
*tctx
,
4279 struct dcerpc_binding_handle
*b
,
4280 struct policy_handle
*handle
,
4281 const char *value_name
);
4283 static bool test_EnumPrinterData_consistency(struct torture_context
*tctx
,
4284 struct dcerpc_pipe
*p
,
4285 struct policy_handle
*handle
)
4288 struct spoolss_PrinterEnumValues
*info
;
4290 uint32_t value_needed
, data_needed
;
4291 uint32_t value_offered
, data_offered
;
4293 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4295 enum winreg_Type type
;
4298 torture_comment(tctx
, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
4300 torture_assert(tctx
, push_reg_sz(tctx
, &blob
, "torture_data1"), "");
4303 torture_assert(tctx
,
4304 test_SetPrinterData(tctx
, b
, handle
, "torture_value1", type
, blob
.data
, blob
.length
),
4305 "SetPrinterData failed");
4307 blob
= data_blob_string_const("torture_data2");
4309 torture_assert(tctx
,
4310 test_SetPrinterData(tctx
, b
, handle
, "torture_value2", REG_BINARY
, blob
.data
, blob
.length
),
4311 "SetPrinterData failed");
4313 blob
= data_blob_talloc(tctx
, NULL
, 4);
4314 SIVAL(blob
.data
, 0, 0x11223344);
4316 torture_assert(tctx
,
4317 test_SetPrinterData(tctx
, b
, handle
, "torture_value3", type
, blob
.data
, blob
.length
),
4318 "SetPrinterData failed");
4320 torture_assert(tctx
,
4321 test_EnumPrinterDataEx(tctx
, b
, handle
, "PrinterDriverData", &count
, &info
),
4322 "failed to call EnumPrinterDataEx");
4324 /* get the max sizes for value and data */
4326 torture_assert(tctx
,
4327 test_EnumPrinterData(tctx
, p
, handle
, 0, 0, 0,
4328 NULL
, &value_needed
, &data_needed
,
4329 NULL
, NULL
, &result
),
4330 "EnumPrinterData failed");
4331 torture_assert_werr_ok(tctx
, result
, "unexpected result");
4333 /* check if the reply from the EnumPrinterData really matches max values */
4335 for (i
=0; i
< count
; i
++) {
4336 if (info
[i
].value_name_len
> value_needed
) {
4338 talloc_asprintf(tctx
,
4339 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
4340 info
[i
].value_name_len
, value_needed
));
4342 if (info
[i
].data_length
> data_needed
) {
4344 talloc_asprintf(tctx
,
4345 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
4346 info
[i
].data_length
, data_needed
));
4350 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
4351 * sort or not sort the replies by value name, we should be able to do
4352 * the following entry comparison */
4354 data_offered
= data_needed
;
4355 value_offered
= value_needed
;
4357 for (i
=0; i
< count
; i
++) {
4359 const char *value_name
;
4362 torture_assert(tctx
,
4363 test_EnumPrinterData(tctx
, p
, handle
, i
, value_offered
, data_offered
,
4364 &type
, &value_needed
, &data_needed
,
4365 &value_name
, &data
, &result
),
4366 "EnumPrinterData failed");
4368 if (i
-1 == count
) {
4369 torture_assert_werr_equal(tctx
, result
, WERR_NO_MORE_ITEMS
,
4370 "unexpected result");
4373 torture_assert_werr_ok(tctx
, result
, "unexpected result");
4376 torture_assert_int_equal(tctx
, type
, info
[i
].type
, "type mismatch");
4377 torture_assert_int_equal(tctx
, value_needed
, info
[i
].value_name_len
, "value name length mismatch");
4378 torture_assert_str_equal(tctx
, value_name
, info
[i
].value_name
, "value name mismatch");
4379 torture_assert_int_equal(tctx
, data_needed
, info
[i
].data_length
, "data length mismatch");
4380 torture_assert_mem_equal(tctx
, data
, info
[i
].data
->data
, info
[i
].data_length
, "data mismatch");
4383 torture_assert(tctx
,
4384 test_DeletePrinterData(tctx
, b
, handle
, "torture_value1"),
4385 "DeletePrinterData failed");
4386 torture_assert(tctx
,
4387 test_DeletePrinterData(tctx
, b
, handle
, "torture_value2"),
4388 "DeletePrinterData failed");
4389 torture_assert(tctx
,
4390 test_DeletePrinterData(tctx
, b
, handle
, "torture_value3"),
4391 "DeletePrinterData failed");
4393 torture_comment(tctx
, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4398 static bool test_DeletePrinterData(struct torture_context
*tctx
,
4399 struct dcerpc_binding_handle
*b
,
4400 struct policy_handle
*handle
,
4401 const char *value_name
)
4404 struct spoolss_DeletePrinterData r
;
4406 r
.in
.handle
= handle
;
4407 r
.in
.value_name
= value_name
;
4409 torture_comment(tctx
, "Testing DeletePrinterData(%s)\n",
4412 status
= dcerpc_spoolss_DeletePrinterData_r(b
, tctx
, &r
);
4414 torture_assert_ntstatus_ok(tctx
, status
, "DeletePrinterData failed");
4415 torture_assert_werr_ok(tctx
, r
.out
.result
, "DeletePrinterData failed");
4420 static bool test_DeletePrinterDataEx(struct torture_context
*tctx
,
4421 struct dcerpc_binding_handle
*b
,
4422 struct policy_handle
*handle
,
4423 const char *key_name
,
4424 const char *value_name
)
4426 struct spoolss_DeletePrinterDataEx r
;
4428 r
.in
.handle
= handle
;
4429 r
.in
.key_name
= key_name
;
4430 r
.in
.value_name
= value_name
;
4432 torture_comment(tctx
, "Testing DeletePrinterDataEx(%s - %s)\n",
4433 r
.in
.key_name
, r
.in
.value_name
);
4435 torture_assert_ntstatus_ok(tctx
,
4436 dcerpc_spoolss_DeletePrinterDataEx_r(b
, tctx
, &r
),
4437 "DeletePrinterDataEx failed");
4438 torture_assert_werr_ok(tctx
, r
.out
.result
,
4439 "DeletePrinterDataEx failed");
4444 static bool test_DeletePrinterKey(struct torture_context
*tctx
,
4445 struct dcerpc_binding_handle
*b
,
4446 struct policy_handle
*handle
,
4447 const char *key_name
)
4449 struct spoolss_DeletePrinterKey r
;
4451 r
.in
.handle
= handle
;
4452 r
.in
.key_name
= key_name
;
4454 torture_comment(tctx
, "Testing DeletePrinterKey(%s)\n", r
.in
.key_name
);
4456 if (strequal(key_name
, "") && !torture_setting_bool(tctx
, "dangerous", false)) {
4457 torture_skip(tctx
, "not wiping out printer registry - enable dangerous tests to use\n");
4461 torture_assert_ntstatus_ok(tctx
,
4462 dcerpc_spoolss_DeletePrinterKey_r(b
, tctx
, &r
),
4463 "DeletePrinterKey failed");
4464 torture_assert_werr_ok(tctx
, r
.out
.result
,
4465 "DeletePrinterKey failed");
4470 static bool test_winreg_OpenHKLM(struct torture_context
*tctx
,
4471 struct dcerpc_binding_handle
*b
,
4472 struct policy_handle
*handle
)
4474 struct winreg_OpenHKLM r
;
4476 r
.in
.system_name
= NULL
;
4477 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4478 r
.out
.handle
= handle
;
4480 torture_comment(tctx
, "Testing winreg_OpenHKLM\n");
4482 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_OpenHKLM_r(b
, tctx
, &r
), "OpenHKLM failed");
4483 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenHKLM failed");
4488 static void init_winreg_String(struct winreg_String
*name
, const char *s
)
4492 name
->name_len
= 2 * (strlen_m(s
) + 1);
4493 name
->name_size
= name
->name_len
;
4496 name
->name_size
= 0;
4500 static bool test_winreg_OpenKey_opts(struct torture_context
*tctx
,
4501 struct dcerpc_binding_handle
*b
,
4502 struct policy_handle
*hive_handle
,
4503 const char *keyname
,
4505 struct policy_handle
*key_handle
)
4507 struct winreg_OpenKey r
;
4509 r
.in
.parent_handle
= hive_handle
;
4510 init_winreg_String(&r
.in
.keyname
, keyname
);
4511 r
.in
.options
= options
;
4512 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4513 r
.out
.handle
= key_handle
;
4515 torture_comment(tctx
, "Testing winreg_OpenKey(%s)\n", keyname
);
4517 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_OpenKey_r(b
, tctx
, &r
), "OpenKey failed");
4518 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenKey failed");
4523 static bool test_winreg_OpenKey(struct torture_context
*tctx
,
4524 struct dcerpc_binding_handle
*b
,
4525 struct policy_handle
*hive_handle
,
4526 const char *keyname
,
4527 struct policy_handle
*key_handle
)
4529 return test_winreg_OpenKey_opts(tctx
, b
, hive_handle
, keyname
,
4530 REG_OPTION_NON_VOLATILE
, key_handle
);
4533 static bool test_winreg_CloseKey(struct torture_context
*tctx
,
4534 struct dcerpc_binding_handle
*b
,
4535 struct policy_handle
*handle
)
4537 struct winreg_CloseKey r
;
4539 r
.in
.handle
= handle
;
4540 r
.out
.handle
= handle
;
4542 torture_comment(tctx
, "Testing winreg_CloseKey\n");
4544 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_CloseKey_r(b
, tctx
, &r
), "CloseKey failed");
4545 torture_assert_werr_ok(tctx
, r
.out
.result
, "CloseKey failed");
4550 bool test_winreg_QueryValue(struct torture_context
*tctx
,
4551 struct dcerpc_binding_handle
*b
,
4552 struct policy_handle
*handle
,
4553 const char *value_name
,
4554 enum winreg_Type
*type_p
,
4555 uint32_t *data_size_p
,
4556 uint32_t *data_length_p
,
4559 struct winreg_QueryValue r
;
4560 enum winreg_Type type
= REG_NONE
;
4561 uint32_t data_size
= 0;
4562 uint32_t data_length
= 0;
4563 struct winreg_String valuename
;
4564 uint8_t *data
= NULL
;
4566 init_winreg_String(&valuename
, value_name
);
4568 data
= talloc_zero_array(tctx
, uint8_t, 0);
4570 r
.in
.handle
= handle
;
4571 r
.in
.value_name
= &valuename
;
4573 r
.in
.data_size
= &data_size
;
4574 r
.in
.data_length
= &data_length
;
4578 r
.out
.data_size
= &data_size
;
4579 r
.out
.data_length
= &data_length
;
4581 torture_comment(tctx
, "Testing winreg_QueryValue(%s)\n", value_name
);
4583 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_QueryValue_r(b
, tctx
, &r
), "QueryValue failed");
4584 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
4585 *r
.in
.data_size
= *r
.out
.data_size
;
4586 data
= talloc_zero_array(tctx
, uint8_t, *r
.in
.data_size
);
4589 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_QueryValue_r(b
, tctx
, &r
), "QueryValue failed");
4591 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryValue failed");
4594 *type_p
= *r
.out
.type
;
4597 *data_size_p
= *r
.out
.data_size
;
4599 if (data_length_p
) {
4600 *data_length_p
= *r
.out
.data_length
;
4603 *data_p
= r
.out
.data
;
4609 static bool test_winreg_query_printerdata(struct torture_context
*tctx
,
4610 struct dcerpc_binding_handle
*b
,
4611 struct policy_handle
*handle
,
4612 const char *printer_name
,
4613 const char *key_name
,
4614 const char *value_name
,
4615 enum winreg_Type
*w_type
,
4620 const char *printer_key
;
4621 struct policy_handle key_handle
;
4623 printer_key
= talloc_asprintf(tctx
, "%s\\%s\\%s",
4624 TOP_LEVEL_PRINT_PRINTERS_KEY
, printer_name
, key_name
);
4626 torture_assert(tctx
,
4627 test_winreg_OpenKey(tctx
, b
, handle
, printer_key
, &key_handle
), "");
4629 torture_assert(tctx
,
4630 test_winreg_QueryValue(tctx
, b
, &key_handle
, value_name
, w_type
, w_size
, w_length
, w_data
), "");
4632 torture_assert(tctx
,
4633 test_winreg_CloseKey(tctx
, b
, &key_handle
), "");
4638 static bool test_GetForm_winreg(struct torture_context
*tctx
,
4639 struct dcerpc_binding_handle
*b
,
4640 struct policy_handle
*handle
,
4641 const char *key_name
,
4642 const char *form_name
,
4643 enum winreg_Type
*w_type
,
4648 struct policy_handle key_handle
;
4650 torture_assert(tctx
,
4651 test_winreg_OpenKey(tctx
, b
, handle
, key_name
, &key_handle
), "");
4653 torture_assert(tctx
,
4654 test_winreg_QueryValue(tctx
, b
, &key_handle
, form_name
, w_type
, w_size
, w_length
, w_data
), "");
4656 torture_assert(tctx
,
4657 test_winreg_CloseKey(tctx
, b
, &key_handle
), "");
4662 static bool test_winreg_symbolic_link(struct torture_context
*tctx
,
4663 struct dcerpc_binding_handle
*b
,
4664 struct policy_handle
*handle
,
4665 const char *symlink_keyname
,
4666 const char *symlink_destination
)
4668 /* check if the first key is a symlink to the second key */
4670 enum winreg_Type w_type
;
4674 struct policy_handle key_handle
;
4678 if (torture_setting_bool(tctx
, "samba3", false)) {
4679 torture_skip(tctx
, "skip winreg symlink test against samba");
4682 torture_assert(tctx
,
4683 test_winreg_OpenKey_opts(tctx
, b
, handle
, symlink_keyname
, REG_OPTION_OPEN_LINK
, &key_handle
),
4684 "failed to open key link");
4686 torture_assert(tctx
,
4687 test_winreg_QueryValue(tctx
, b
, &key_handle
,
4688 "SymbolicLinkValue",
4689 &w_type
, &w_size
, &w_length
, &w_data
),
4690 "failed to query for 'SymbolicLinkValue' attribute");
4692 torture_assert_int_equal(tctx
, w_type
, REG_LINK
, "unexpected type");
4694 blob
= data_blob(w_data
, w_size
);
4695 str
= reg_val_data_string(tctx
, REG_SZ
, blob
);
4697 torture_assert_str_equal(tctx
, str
, symlink_destination
, "unexpected symlink target string");
4699 torture_assert(tctx
,
4700 test_winreg_CloseKey(tctx
, b
, &key_handle
),
4701 "failed to close key link");
4706 static const char *strip_unc(const char *unc
)
4714 if (unc
[0] == '\\' && unc
[1] == '\\') {
4718 name
= strchr(unc
, '\\');
4726 static bool test_GetPrinterInfo_winreg(struct torture_context
*tctx
,
4727 struct dcerpc_binding_handle
*b
,
4728 struct policy_handle
*handle
,
4729 const char *printer_name
,
4730 struct dcerpc_binding_handle
*winreg_handle
,
4731 struct policy_handle
*hive_handle
)
4733 union spoolss_PrinterInfo info
;
4734 const char *keys
[] = {
4735 TOP_LEVEL_CONTROL_PRINTERS_KEY
,
4736 TOP_LEVEL_PRINT_PRINTERS_KEY
4739 const char *printername
, *sharename
;
4741 torture_comment(tctx
, "Testing Printer Info and winreg consistency\n");
4743 torture_assert(tctx
,
4744 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
4745 "failed to get printer info level 2");
4747 printername
= strip_unc(info
.info2
.printername
);
4748 sharename
= strip_unc(info
.info2
.sharename
);
4750 #define test_sz(wname, iname) \
4754 enum winreg_Type w_type;\
4758 torture_assert(tctx,\
4759 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4760 &w_type, &w_size, &w_length, &w_data),\
4761 "failed to query winreg");\
4762 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4763 blob = data_blob(w_data, w_size);\
4764 str = reg_val_data_string(tctx, REG_SZ, blob);\
4765 if (w_size == 2 && iname == NULL) {\
4766 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4768 torture_assert_str_equal(tctx, str, iname,\
4769 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4773 #define test_dword(wname, iname) \
4776 enum winreg_Type w_type;\
4780 torture_assert(tctx,\
4781 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4782 &w_type, &w_size, &w_length, &w_data),\
4783 "failed to query winreg");\
4784 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4785 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4786 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4787 value = IVAL(w_data, 0);\
4788 torture_assert_int_equal(tctx, value, iname,\
4789 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4792 #define test_binary(wname, iname) \
4794 enum winreg_Type w_type;\
4798 torture_assert(tctx,\
4799 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4800 &w_type, &w_size, &w_length, &w_data),\
4801 "failed to query winreg");\
4802 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4803 torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4804 torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4809 #define test_dm(wname, iname) \
4812 struct spoolss_DeviceMode dm;\
4813 enum ndr_err_code ndr_err;\
4814 enum winreg_Type w_type;\
4818 torture_assert(tctx,\
4819 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4820 &w_type, &w_size, &w_length, &w_data),\
4821 "failed to query winreg");\
4822 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4823 blob = data_blob(w_data, w_size);\
4824 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4825 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4826 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4827 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4831 #define test_sd(wname, iname) \
4834 struct security_descriptor sd;\
4835 enum ndr_err_code ndr_err;\
4836 enum winreg_Type w_type;\
4840 torture_assert(tctx,\
4841 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4842 &w_type, &w_size, &w_length, &w_data),\
4843 "failed to query winreg");\
4844 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4845 blob = data_blob(w_data, w_size);\
4846 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4847 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4848 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4849 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4853 #define test_multi_sz(wname, iname) \
4856 const char **array;\
4857 enum winreg_Type w_type;\
4862 torture_assert(tctx,\
4863 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4864 &w_type, &w_size, &w_length, &w_data),\
4865 "failed to query winreg");\
4866 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4867 blob = data_blob(w_data, w_size);\
4868 torture_assert(tctx, \
4869 pull_reg_multi_sz(tctx, &blob, &array),\
4870 "failed to pull multi sz");\
4871 for (i=0; array[i] != NULL; i++) {\
4872 torture_assert_str_equal(tctx, array[i], iname[i],\
4873 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4877 if (!test_winreg_symbolic_link(tctx
, winreg_handle
, hive_handle
,
4878 TOP_LEVEL_CONTROL_PRINTERS_KEY
,
4879 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4881 torture_warning(tctx
, "failed to check for winreg symlink");
4884 for (i
=0; i
< ARRAY_SIZE(keys
); i
++) {
4886 const char *printer_key
;
4887 struct policy_handle key_handle
;
4889 printer_key
= talloc_asprintf(tctx
, "%s\\%s",
4890 keys
[i
], printer_name
);
4892 torture_assert(tctx
,
4893 test_winreg_OpenKey(tctx
, winreg_handle
, hive_handle
, printer_key
, &key_handle
), "");
4895 test_sz("Name", printername
);
4896 test_sz("Share Name", sharename
);
4897 test_sz("Port", info
.info2
.portname
);
4898 test_sz("Printer Driver", info
.info2
.drivername
);
4899 test_sz("Description", info
.info2
.comment
);
4900 test_sz("Location", info
.info2
.location
);
4901 test_sz("Separator File", info
.info2
.sepfile
);
4902 test_sz("Print Processor", info
.info2
.printprocessor
);
4903 test_sz("Datatype", info
.info2
.datatype
);
4904 test_sz("Parameters", info
.info2
.parameters
);
4905 /* winreg: 0, spoolss not */
4906 /* test_dword("Attributes", info.info2.attributes); */
4907 test_dword("Priority", info
.info2
.priority
);
4908 test_dword("Default Priority", info
.info2
.defaultpriority
);
4909 /* winreg: 60, spoolss: 0 */
4910 /* test_dword("StartTime", info.info2.starttime); */
4911 /* test_dword("UntilTime", info.info2.untiltime); */
4912 /* winreg != spoolss */
4913 /* test_dword("Status", info.info2.status); */
4914 test_dm("Default DevMode", info
.info2
.devmode
);
4915 test_sd("Security", info
.info2
.secdesc
);
4917 torture_assert(tctx
,
4918 test_winreg_CloseKey(tctx
, winreg_handle
, &key_handle
), "");
4924 torture_comment(tctx
, "Printer Info and winreg consistency test succeeded\n\n");
4929 static bool test_PrintProcessors(struct torture_context
*tctx
,
4930 struct dcerpc_binding_handle
*b
,
4931 const char *environment
,
4932 struct dcerpc_binding_handle
*winreg_handle
,
4933 struct policy_handle
*hive_handle
)
4935 union spoolss_PrintProcessorInfo
*info
;
4939 torture_comment(tctx
, "Testing Print Processor Info and winreg consistency\n");
4941 torture_assert(tctx
,
4942 test_EnumPrintProcessors_level(tctx
, b
, environment
, 1, &count
, &info
, WERR_OK
),
4943 "failed to enum print processors level 1");
4945 for (i
=0; i
< count
; i
++) {
4947 const char *processor_key
;
4948 struct policy_handle key_handle
;
4950 processor_key
= talloc_asprintf(tctx
, "%s\\%s\\Print Processors\\%s",
4951 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY
,
4953 info
[i
].info1
.print_processor_name
);
4955 torture_assert(tctx
,
4956 test_winreg_OpenKey(tctx
, winreg_handle
, hive_handle
, processor_key
, &key_handle
), "");
4958 /* nothing to check in there so far */
4960 torture_assert(tctx
,
4961 test_winreg_CloseKey(tctx
, winreg_handle
, &key_handle
), "");
4964 torture_comment(tctx
, "Print Processor Info and winreg consistency test succeeded\n\n");
4969 static bool test_GetPrinterDriver2_level(struct torture_context
*tctx
,
4970 struct dcerpc_binding_handle
*b
,
4971 struct policy_handle
*handle
,
4972 const char *driver_name
,
4973 const char *architecture
,
4975 uint32_t client_major_version
,
4976 uint32_t client_minor_version
,
4977 union spoolss_DriverInfo
*info_p
,
4980 static const char *strip_path(const char *path
)
4988 p
= strrchr(path
, '\\');
4996 static const char **strip_paths(const char **path_array
)
5000 if (path_array
== NULL
) {
5004 for (i
=0; path_array
[i
] != NULL
; i
++) {
5005 path_array
[i
] = strip_path(path_array
[i
]);
5011 static const char *driver_winreg_date(TALLOC_CTX
*mem_ctx
, NTTIME nt
)
5017 return talloc_strdup(mem_ctx
, "01/01/1601");
5020 t
= nt_time_to_unix(nt
);
5023 return talloc_asprintf(mem_ctx
, "%02d/%02d/%04d",
5024 tm
->tm_mon
+ 1, tm
->tm_mday
, tm
->tm_year
+ 1900);
5027 static const char *driver_winreg_version(TALLOC_CTX
*mem_ctx
, uint64_t v
)
5029 return talloc_asprintf(mem_ctx
, "%u.%u.%u.%u",
5030 (unsigned)((v
>> 48) & 0xFFFF),
5031 (unsigned)((v
>> 32) & 0xFFFF),
5032 (unsigned)((v
>> 16) & 0xFFFF),
5033 (unsigned)(v
& 0xFFFF));
5036 static bool test_GetDriverInfo_winreg(struct torture_context
*tctx
,
5037 struct dcerpc_binding_handle
*b
,
5038 struct policy_handle
*handle
,
5039 const char *printer_name
,
5040 const char *driver_name
,
5041 const char *environment
,
5042 enum spoolss_DriverOSVersion version
,
5043 struct dcerpc_binding_handle
*winreg_handle
,
5044 struct policy_handle
*hive_handle
,
5045 const char *server_name_slash
)
5047 WERROR result
= WERR_OK
;
5048 union spoolss_DriverInfo info
;
5049 const char *driver_key
;
5050 struct policy_handle key_handle
;
5052 const char *driver_path
;
5053 const char *data_file
;
5054 const char *config_file
;
5055 const char *help_file
;
5056 const char **dependent_files
;
5058 const char *driver_date
;
5059 const char *inbox_driver_date
;
5061 const char *driver_version
;
5062 const char *inbox_driver_version
;
5064 ZERO_STRUCT(key_handle
);
5066 torture_comment(tctx
, "Testing Driver Info and winreg consistency\n");
5068 driver_key
= talloc_asprintf(tctx
, "%s\\%s\\Drivers\\Version-%d\\%s",
5069 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY
,
5074 torture_assert(tctx
,
5075 test_winreg_OpenKey(tctx
, winreg_handle
, hive_handle
, driver_key
, &key_handle
),
5076 "failed to open driver key");
5078 if (torture_setting_bool(tctx
, "samba3", false) ||
5079 torture_setting_bool(tctx
, "w2k3", false)) {
5084 torture_assert(tctx
,
5085 test_GetPrinterDriver2_level(tctx
, b
, handle
, driver_name
, environment
, 8, version
, 0, &info
, &result
),
5086 "failed to get driver info level 8");
5088 torture_assert(tctx
,
5089 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, environment
, 8, driver_name
, &info
),
5090 "failed to get driver info level 8");
5093 if (W_ERROR_EQUAL(result
, WERR_INVALID_LEVEL
)) {
5097 driver_path
= strip_path(info
.info8
.driver_path
);
5098 data_file
= strip_path(info
.info8
.data_file
);
5099 config_file
= strip_path(info
.info8
.config_file
);
5100 help_file
= strip_path(info
.info8
.help_file
);
5101 dependent_files
= strip_paths(info
.info8
.dependent_files
);
5103 driver_date
= driver_winreg_date(tctx
, info
.info8
.driver_date
);
5104 inbox_driver_date
= driver_winreg_date(tctx
, info
.info8
.min_inbox_driver_ver_date
);
5106 driver_version
= driver_winreg_version(tctx
, info
.info8
.driver_version
);
5107 inbox_driver_version
= driver_winreg_version(tctx
, info
.info8
.min_inbox_driver_ver_version
);
5109 test_sz("Configuration File", config_file
);
5110 test_sz("Data File", data_file
);
5111 test_sz("Datatype", info
.info8
.default_datatype
);
5112 test_sz("Driver", driver_path
);
5113 test_sz("DriverDate", driver_date
);
5114 test_sz("DriverVersion", driver_version
);
5115 test_sz("HardwareID", info
.info8
.hardware_id
);
5116 test_sz("Help File", help_file
);
5117 test_sz("InfPath", info
.info8
.inf_path
);
5118 test_sz("Manufacturer", info
.info8
.manufacturer_name
);
5119 test_sz("MinInboxDriverVerDate", inbox_driver_date
);
5120 test_sz("MinInboxDriverVerVersion", inbox_driver_version
);
5121 test_sz("Monitor", info
.info8
.monitor_name
);
5122 test_sz("OEM URL", info
.info8
.manufacturer_url
);
5123 test_sz("Print Processor", info
.info8
.print_processor
);
5124 test_sz("Provider", info
.info8
.provider
);
5125 test_sz("VendorSetup", info
.info8
.vendor_setup
);
5126 test_multi_sz("ColorProfiles", info
.info8
.color_profiles
);
5127 test_multi_sz("Dependent Files", dependent_files
);
5128 test_multi_sz("CoreDependencies", info
.info8
.core_driver_dependencies
);
5129 test_multi_sz("Previous Names", info
.info8
.previous_names
);
5130 /* test_dword("Attributes", ?); */
5131 test_dword("PrinterDriverAttributes", info
.info8
.printer_driver_attributes
);
5132 test_dword("Version", info
.info8
.version
);
5133 /* test_dword("TempDir", ?); */
5138 torture_assert(tctx
,
5139 test_GetPrinterDriver2_level(tctx
, b
, handle
, driver_name
, environment
, 6, version
, 0, &info
, &result
),
5140 "failed to get driver info level 6");
5142 torture_assert(tctx
,
5143 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, environment
, 6, driver_name
, &info
),
5144 "failed to get driver info level 6");
5147 driver_path
= strip_path(info
.info6
.driver_path
);
5148 data_file
= strip_path(info
.info6
.data_file
);
5149 config_file
= strip_path(info
.info6
.config_file
);
5150 help_file
= strip_path(info
.info6
.help_file
);
5151 dependent_files
= strip_paths(info
.info6
.dependent_files
);
5153 driver_date
= driver_winreg_date(tctx
, info
.info6
.driver_date
);
5155 driver_version
= driver_winreg_version(tctx
, info
.info6
.driver_version
);
5157 test_sz("Configuration File", config_file
);
5158 test_sz("Data File", data_file
);
5159 test_sz("Datatype", info
.info6
.default_datatype
);
5160 test_sz("Driver", driver_path
);
5161 if (torture_setting_bool(tctx
, "w2k3", false)) {
5162 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, 8);
5163 push_nttime(blob
.data
, 0, info
.info6
.driver_date
);
5164 test_binary("DriverDate", blob
);
5165 SBVAL(blob
.data
, 0, info
.info6
.driver_version
);
5166 test_binary("DriverVersion", blob
);
5168 test_sz("DriverDate", driver_date
);
5169 test_sz("DriverVersion", driver_version
);
5171 test_sz("HardwareID", info
.info6
.hardware_id
);
5172 test_sz("Help File", help_file
);
5173 test_sz("Manufacturer", info
.info6
.manufacturer_name
);
5174 test_sz("Monitor", info
.info6
.monitor_name
);
5175 test_sz("OEM URL", info
.info6
.manufacturer_url
);
5176 test_sz("Provider", info
.info6
.provider
);
5177 test_multi_sz("Dependent Files", dependent_files
);
5178 test_multi_sz("Previous Names", info
.info6
.previous_names
);
5179 /* test_dword("Attributes", ?); */
5180 test_dword("Version", info
.info6
.version
);
5181 /* test_dword("TempDir", ?); */
5184 torture_assert(tctx
,
5185 test_GetPrinterDriver2_level(tctx
, b
, handle
, driver_name
, environment
, 3, version
, 0, &info
, &result
),
5186 "failed to get driver info level 3");
5188 torture_assert(tctx
,
5189 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, environment
, 3, driver_name
, &info
),
5190 "failed to get driver info level 3");
5193 driver_path
= strip_path(info
.info3
.driver_path
);
5194 data_file
= strip_path(info
.info3
.data_file
);
5195 config_file
= strip_path(info
.info3
.config_file
);
5196 help_file
= strip_path(info
.info3
.help_file
);
5197 dependent_files
= strip_paths(info
.info3
.dependent_files
);
5199 test_sz("Configuration File", config_file
);
5200 test_sz("Data File", data_file
);
5201 test_sz("Datatype", info
.info3
.default_datatype
);
5202 test_sz("Driver", driver_path
);
5203 test_sz("Help File", help_file
);
5204 test_sz("Monitor", info
.info3
.monitor_name
);
5205 test_multi_sz("Dependent Files", dependent_files
);
5206 /* test_dword("Attributes", ?); */
5207 test_dword("Version", info
.info3
.version
);
5208 /* test_dword("TempDir", ?); */
5211 torture_assert(tctx
,
5212 test_winreg_CloseKey(tctx
, winreg_handle
, &key_handle
), "");
5214 torture_comment(tctx
, "Driver Info and winreg consistency test succeeded\n\n");
5222 static bool test_SetPrinterData(struct torture_context
*tctx
,
5223 struct dcerpc_binding_handle
*b
,
5224 struct policy_handle
*handle
,
5225 const char *value_name
,
5226 enum winreg_Type type
,
5230 struct spoolss_SetPrinterData r
;
5232 r
.in
.handle
= handle
;
5233 r
.in
.value_name
= value_name
;
5236 r
.in
.offered
= offered
;
5238 torture_comment(tctx
, "Testing SetPrinterData(%s)\n",
5241 torture_assert_ntstatus_ok(tctx
,
5242 dcerpc_spoolss_SetPrinterData_r(b
, tctx
, &r
),
5243 "SetPrinterData failed");
5244 torture_assert_werr_ok(tctx
, r
.out
.result
,
5245 "SetPrinterData failed");
5250 static bool test_SetPrinterData_matrix(struct torture_context
*tctx
,
5251 struct dcerpc_binding_handle
*b
,
5252 struct policy_handle
*handle
,
5253 const char *printer_name
,
5254 struct dcerpc_binding_handle
*winreg_handle
,
5255 struct policy_handle
*hive_handle
)
5257 const char *values
[] = {
5261 /* FIXME: not working with s3 atm. */
5267 /* FIXME: not working with s3 atm. */
5274 for (i
=0; i
< ARRAY_SIZE(values
); i
++) {
5276 enum winreg_Type type
, expected_type
= REG_SZ
;
5281 torture_assert(tctx
, push_reg_sz(tctx
, &blob
, "dog"), "");
5284 torture_assert(tctx
,
5285 test_SetPrinterData(tctx
, b
, handle
, values
[i
], REG_SZ
, blob
.data
, blob
.length
),
5286 "SetPrinterData failed");
5288 torture_assert(tctx
,
5289 test_GetPrinterData_checktype(tctx
, b
, handle
, values
[i
], &expected_type
, &type
, &data
, &needed
),
5290 "GetPrinterData failed");
5292 torture_assert_int_equal(tctx
, type
, REG_SZ
, "type mismatch");
5293 torture_assert_int_equal(tctx
, needed
, blob
.length
, "size mismatch");
5294 torture_assert_mem_equal(tctx
, data
, blob
.data
, blob
.length
, "buffer mismatch");
5296 if (winreg_handle
&& hive_handle
) {
5298 enum winreg_Type w_type
;
5303 torture_assert(tctx
,
5304 test_winreg_query_printerdata(tctx
, winreg_handle
, hive_handle
,
5305 printer_name
, "PrinterDriverData", values
[i
],
5306 &w_type
, &w_size
, &w_length
, &w_data
), "");
5308 torture_assert_int_equal(tctx
, w_type
, REG_SZ
, "winreg type mismatch");
5309 torture_assert_int_equal(tctx
, w_size
, blob
.length
, "winreg size mismatch");
5310 torture_assert_int_equal(tctx
, w_length
, blob
.length
, "winreg length mismatch");
5311 torture_assert_mem_equal(tctx
, w_data
, blob
.data
, blob
.length
, "winreg buffer mismatch");
5314 torture_assert(tctx
,
5315 test_DeletePrinterData(tctx
, b
, handle
, values
[i
]),
5316 "DeletePrinterData failed");
5323 static bool test_EnumPrinterKey(struct torture_context
*tctx
,
5324 struct dcerpc_binding_handle
*b
,
5325 struct policy_handle
*handle
,
5326 const char *key_name
,
5327 const char ***array
);
5329 static bool test_SetPrinterDataEx(struct torture_context
*tctx
,
5330 struct dcerpc_binding_handle
*b
,
5331 struct policy_handle
*handle
,
5332 const char *key_name
,
5333 const char *value_name
,
5334 enum winreg_Type type
,
5339 struct spoolss_SetPrinterDataEx r
;
5341 r
.in
.handle
= handle
;
5342 r
.in
.key_name
= key_name
;
5343 r
.in
.value_name
= value_name
;
5346 r
.in
.offered
= offered
;
5348 torture_comment(tctx
, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
5349 r
.in
.key_name
, r
.in
.value_name
, str_regtype(r
.in
.type
), r
.in
.offered
);
5351 status
= dcerpc_spoolss_SetPrinterDataEx_r(b
, tctx
, &r
);
5353 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinterDataEx failed");
5354 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinterDataEx failed");
5359 static bool test_SetPrinterDataEx_keys(struct torture_context
*tctx
,
5360 struct dcerpc_pipe
*p
,
5361 struct policy_handle
*handle
)
5363 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5364 const char *value_name
= "dog";
5365 const char *keys
[] = {
5368 "torturedataex_with_subkey\\subkey",
5369 "torturedataex_with_subkey\\subkey:0",
5370 "torturedataex_with_subkey\\subkey:1",
5371 "torturedataex_with_subkey\\subkey\\subsubkey",
5372 "torturedataex_with_subkey\\subkey\\subsubkey:0",
5373 "torturedataex_with_subkey\\subkey\\subsubkey:1",
5380 "torture/data ex/sub",
5383 "torture//data ex/sub",
5384 "torture//data ex//sub",
5388 for (i
=0; i
< ARRAY_SIZE(keys
); i
++) {
5392 enum winreg_Type type
;
5393 DATA_BLOB blob_in
, blob_out
;
5394 const char **subkeys
;
5396 struct spoolss_PrinterEnumValues
*einfo
;
5399 blob_in
= data_blob_talloc(tctx
, NULL
, 42);
5401 generate_random_buffer(blob_in
.data
, blob_in
.length
);
5403 torture_assert(tctx
,
5404 test_SetPrinterDataEx(tctx
, b
, handle
, keys
[i
], value_name
, REG_BINARY
, blob_in
.data
, blob_in
.length
),
5405 "failed to call SetPrinterDataEx");
5407 torture_assert(tctx
,
5408 test_GetPrinterDataEx(tctx
, p
, handle
, keys
[i
], value_name
, &type
, &blob_out
.data
, &needed
),
5409 "failed to call GetPrinterDataEx");
5411 blob_out
.length
= needed
;
5412 torture_assert(tctx
,
5413 test_EnumPrinterDataEx(tctx
, b
, handle
, keys
[i
], &ecount
, &einfo
),
5414 "failed to call EnumPrinterDataEx");
5416 torture_assert_int_equal(tctx
, type
, REG_BINARY
, "type mismatch");
5417 torture_assert_int_equal(tctx
, blob_out
.length
, blob_in
.length
, "size mismatch");
5418 torture_assert_mem_equal(tctx
, blob_out
.data
, blob_in
.data
, blob_in
.length
, "buffer mismatch");
5420 torture_assert_int_equal(tctx
, ecount
, 1, "unexpected enum count");
5421 torture_assert_str_equal(tctx
, einfo
[0].value_name
, value_name
, "value_name mismatch");
5422 torture_assert_int_equal(tctx
, einfo
[0].value_name_len
, strlen_m_term(value_name
)*2, "unexpected value_name_len");
5423 torture_assert_int_equal(tctx
, einfo
[0].type
, REG_BINARY
, "type mismatch");
5424 torture_assert_int_equal(tctx
, einfo
[0].data_length
, blob_in
.length
, "size mismatch");
5425 if (einfo
[0].data_length
> 0) {
5426 torture_assert_mem_equal(tctx
, einfo
[0].data
->data
, blob_in
.data
, blob_in
.length
, "buffer mismatch");
5429 key
= talloc_strdup(tctx
, keys
[i
]);
5431 if (!test_DeletePrinterDataEx(tctx
, b
, handle
, keys
[i
], value_name
)) {
5435 c
= strchr(key
, '\\');
5439 /* we have subkeys */
5443 if (!test_EnumPrinterKey(tctx
, b
, handle
, key
, &subkeys
)) {
5447 for (k
=0; subkeys
&& subkeys
[k
]; k
++) {
5449 const char *current_key
= talloc_asprintf(tctx
, "%s\\%s", key
, subkeys
[k
]);
5451 if (!test_DeletePrinterKey(tctx
, b
, handle
, current_key
)) {
5456 if (!test_DeletePrinterKey(tctx
, b
, handle
, key
)) {
5461 if (!test_DeletePrinterKey(tctx
, b
, handle
, key
)) {
5470 static bool test_SetPrinterDataEx_values(struct torture_context
*tctx
,
5471 struct dcerpc_pipe
*p
,
5472 struct policy_handle
*handle
)
5474 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5475 const char *key
= "torturedataex";
5476 const char *values
[] = {
5486 for (i
=0; i
< ARRAY_SIZE(values
); i
++) {
5488 enum winreg_Type type
;
5489 DATA_BLOB blob_in
, blob_out
;
5491 struct spoolss_PrinterEnumValues
*einfo
;
5494 if (torture_setting_bool(tctx
, "samba3", false)) {
5496 q
= strrchr(values
[i
], ',');
5498 torture_comment(tctx
, "skipping valuename '%s' including ',' character against Samba3\n",
5504 blob_in
= data_blob_talloc(tctx
, NULL
, 42);
5506 generate_random_buffer(blob_in
.data
, blob_in
.length
);
5508 torture_assert(tctx
,
5509 test_SetPrinterDataEx(tctx
, b
, handle
, key
, values
[i
], REG_BINARY
, blob_in
.data
, blob_in
.length
),
5510 "failed to call SetPrinterDataEx");
5512 torture_assert(tctx
,
5513 test_GetPrinterDataEx(tctx
, p
, handle
, key
, values
[i
], &type
, &blob_out
.data
, &needed
),
5514 "failed to call GetPrinterDataEx");
5516 blob_out
.length
= needed
;
5517 torture_assert(tctx
,
5518 test_EnumPrinterDataEx(tctx
, b
, handle
, key
, &ecount
, &einfo
),
5519 "failed to call EnumPrinterDataEx");
5521 torture_assert_int_equal(tctx
, type
, REG_BINARY
, "type mismatch");
5522 torture_assert_int_equal(tctx
, blob_out
.length
, blob_in
.length
, "size mismatch");
5523 torture_assert_mem_equal(tctx
, blob_out
.data
, blob_in
.data
, blob_in
.length
, "buffer mismatch");
5525 torture_assert_int_equal(tctx
, ecount
, 1, "unexpected enum count");
5526 torture_assert_str_equal(tctx
, einfo
[0].value_name
, values
[i
], "value_name mismatch");
5527 torture_assert_int_equal(tctx
, einfo
[0].value_name_len
, strlen_m_term(values
[i
])*2, "unexpected value_name_len");
5528 torture_assert_int_equal(tctx
, einfo
[0].type
, REG_BINARY
, "type mismatch");
5529 torture_assert_int_equal(tctx
, einfo
[0].data_length
, blob_in
.length
, "size mismatch");
5530 if (einfo
[0].data_length
> 0) {
5531 torture_assert_mem_equal(tctx
, einfo
[0].data
->data
, blob_in
.data
, blob_in
.length
, "buffer mismatch");
5534 torture_assert(tctx
,
5535 test_DeletePrinterDataEx(tctx
, b
, handle
, key
, values
[i
]),
5536 "failed to call DeletePrinterDataEx");
5543 static bool test_SetPrinterDataEx_matrix(struct torture_context
*tctx
,
5544 struct dcerpc_pipe
*p
,
5545 struct policy_handle
*handle
,
5546 const char *printername
,
5547 struct dcerpc_binding_handle
*winreg_handle
,
5548 struct policy_handle
*hive_handle
)
5550 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5551 const char *value_name
= "dog";
5552 const char *key_name
= "torturedataex";
5553 enum winreg_Type types
[] = {
5559 const char *str
= "abcdefghi";
5562 for (t
=0; t
< ARRAY_SIZE(types
); t
++) {
5563 for (s
=0; s
< strlen(str
); s
++) {
5565 enum winreg_Type type
;
5566 const char *string
= talloc_strndup(tctx
, str
, s
);
5567 const char *array
[2];
5568 DATA_BLOB blob
= data_blob_string_const(string
);
5571 uint32_t needed
, offered
= 0;
5573 struct spoolss_PrinterEnumValues
*einfo
;
5575 array
[0] = talloc_strdup(tctx
, string
);
5578 if (types
[t
] == REG_DWORD
) {
5585 offered
= blob
.length
;
5588 data
= data_blob_talloc(tctx
, NULL
, 4);
5589 SIVAL(data
.data
, 0, 0x12345678);
5593 torture_assert(tctx
, push_reg_sz(tctx
, &data
, string
), "");
5595 offered
= data
.length
;
5596 /*strlen_m_term(data.string)*2;*/
5599 torture_assert(tctx
, push_reg_multi_sz(tctx
, &data
, array
), "");
5600 type
= REG_MULTI_SZ
;
5601 offered
= data
.length
;
5604 torture_fail(tctx
, talloc_asprintf(tctx
, "type %d untested\n", types
[t
]));
5607 torture_assert(tctx
,
5608 test_SetPrinterDataEx(tctx
, b
, handle
, key_name
, value_name
, types
[t
], data
.data
, offered
),
5609 "failed to call SetPrinterDataEx");
5611 torture_assert(tctx
,
5612 test_GetPrinterDataEx_checktype(tctx
, p
, handle
, key_name
, value_name
, &types
[t
], &type
, &data_out
, &needed
),
5613 "failed to call GetPrinterDataEx");
5615 torture_assert(tctx
,
5616 test_EnumPrinterDataEx(tctx
, b
, handle
, key_name
, &ecount
, &einfo
),
5617 "failed to call EnumPrinterDataEx");
5619 torture_assert_int_equal(tctx
, types
[t
], type
, "type mismatch");
5620 torture_assert_int_equal(tctx
, needed
, offered
, "size mismatch");
5621 torture_assert_mem_equal(tctx
, data_out
, data
.data
, offered
, "buffer mismatch");
5623 torture_assert_int_equal(tctx
, ecount
, 1, "unexpected enum count");
5624 torture_assert_str_equal(tctx
, einfo
[0].value_name
, value_name
, "value_name mismatch");
5625 torture_assert_int_equal(tctx
, einfo
[0].value_name_len
, strlen_m_term(value_name
)*2, "unexpected value_name_len");
5626 torture_assert_int_equal(tctx
, einfo
[0].type
, types
[t
], "type mismatch");
5627 torture_assert_int_equal(tctx
, einfo
[0].data_length
, offered
, "size mismatch");
5628 if (einfo
[0].data_length
> 0) {
5629 torture_assert_mem_equal(tctx
, einfo
[0].data
->data
, data
.data
, offered
, "buffer mismatch");
5632 if (winreg_handle
&& hive_handle
) {
5633 enum winreg_Type w_type
;
5638 torture_assert(tctx
,
5639 test_winreg_query_printerdata(tctx
, winreg_handle
, hive_handle
,
5640 printername
, key_name
, value_name
,
5641 &w_type
, &w_size
, &w_length
, &w_data
), "");
5643 torture_assert_int_equal(tctx
, w_type
, types
[t
], "winreg type mismatch");
5644 torture_assert_int_equal(tctx
, w_size
, offered
, "winreg size mismatch");
5645 torture_assert_int_equal(tctx
, w_length
, offered
, "winreg length mismatch");
5646 torture_assert_mem_equal(tctx
, w_data
, data
.data
, offered
, "winreg buffer mismatch");
5649 torture_assert(tctx
,
5650 test_DeletePrinterDataEx(tctx
, b
, handle
, key_name
, value_name
),
5651 "failed to call DeletePrinterDataEx");
5658 static bool test_PrinterData_winreg(struct torture_context
*tctx
,
5659 struct dcerpc_pipe
*p
,
5660 struct policy_handle
*handle
,
5661 const char *printer_name
)
5663 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5664 struct dcerpc_pipe
*p2
;
5666 struct policy_handle hive_handle
;
5667 struct dcerpc_binding_handle
*b2
;
5669 torture_assert_ntstatus_ok(tctx
,
5670 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
5671 "could not open winreg pipe");
5672 b2
= p2
->binding_handle
;
5674 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
5676 ret
&= test_SetPrinterData_matrix(tctx
, b
, handle
, printer_name
, b2
, &hive_handle
);
5677 ret
&= test_SetPrinterDataEx_matrix(tctx
, p
, handle
, printer_name
, b2
, &hive_handle
);
5679 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
5686 static bool test_Forms_winreg(struct torture_context
*tctx
,
5687 struct dcerpc_binding_handle
*b
,
5688 struct policy_handle
*handle
,
5690 const char *printer_name
)
5692 struct dcerpc_pipe
*p2
;
5694 struct policy_handle hive_handle
;
5695 struct dcerpc_binding_handle
*b2
;
5697 torture_assert_ntstatus_ok(tctx
,
5698 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
5699 "could not open winreg pipe");
5700 b2
= p2
->binding_handle
;
5702 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
5704 ret
= test_Forms(tctx
, b
, handle
, print_server
, printer_name
, b2
, &hive_handle
);
5706 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
5713 static bool test_PrinterInfo_winreg(struct torture_context
*tctx
,
5714 struct dcerpc_pipe
*p
,
5715 struct policy_handle
*handle
,
5716 const char *printer_name
)
5718 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5719 struct dcerpc_pipe
*p2
;
5721 struct policy_handle hive_handle
;
5722 struct dcerpc_binding_handle
*b2
;
5724 torture_assert_ntstatus_ok(tctx
,
5725 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
5726 "could not open winreg pipe");
5727 b2
= p2
->binding_handle
;
5729 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
5731 ret
= test_GetPrinterInfo_winreg(tctx
, b
, handle
, printer_name
, b2
, &hive_handle
);
5733 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
5740 static bool test_DriverInfo_winreg(struct torture_context
*tctx
,
5741 struct dcerpc_pipe
*p
,
5742 struct policy_handle
*handle
,
5743 const char *printer_name
,
5744 const char *driver_name
,
5745 const char *environment
,
5746 enum spoolss_DriverOSVersion version
)
5748 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5749 struct dcerpc_pipe
*p2
;
5751 struct policy_handle hive_handle
;
5752 struct dcerpc_binding_handle
*b2
;
5754 torture_assert_ntstatus_ok(tctx
,
5755 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
5756 "could not open winreg pipe");
5757 b2
= p2
->binding_handle
;
5759 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
5761 ret
= test_GetDriverInfo_winreg(tctx
, b
, handle
, printer_name
, driver_name
, environment
, version
, b2
, &hive_handle
, NULL
);
5763 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
5770 static bool test_PrintProcessors_winreg(struct torture_context
*tctx
,
5771 struct dcerpc_binding_handle
*b
,
5772 const char *environment
)
5774 struct dcerpc_pipe
*p2
;
5776 struct policy_handle hive_handle
;
5777 struct dcerpc_binding_handle
*b2
;
5779 torture_assert_ntstatus_ok(tctx
,
5780 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
5781 "could not open winreg pipe");
5782 b2
= p2
->binding_handle
;
5784 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
5786 ret
= test_PrintProcessors(tctx
, b
, environment
, b2
, &hive_handle
);
5788 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
5795 static bool test_PrinterData_DsSpooler(struct torture_context
*tctx
,
5796 struct dcerpc_pipe
*p
,
5797 struct policy_handle
*handle
,
5798 const char *printer_name
)
5800 struct spoolss_SetPrinterInfoCtr info_ctr
;
5801 struct spoolss_DevmodeContainer devmode_ctr
;
5802 struct sec_desc_buf secdesc_ctr
;
5803 union spoolss_SetPrinterInfo sinfo
;
5804 union spoolss_PrinterInfo info
;
5805 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5808 ZERO_STRUCT(info_ctr
);
5809 ZERO_STRUCT(devmode_ctr
);
5810 ZERO_STRUCT(secdesc_ctr
);
5812 torture_comment(tctx
, "Testing DsSpooler <-> SetPrinter relations\n");
5814 torture_assert(tctx
,
5815 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
5816 "failed to query Printer level 2");
5818 torture_assert(tctx
,
5819 PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
),
5820 "failed to convert");
5823 info_ctr
.info
= sinfo
;
5825 #define TEST_SZ(wname, iname) \
5827 enum winreg_Type type;\
5832 torture_assert(tctx,\
5833 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5834 "failed to query");\
5835 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5836 blob = data_blob_const(data, needed);\
5837 torture_assert(tctx,\
5838 pull_reg_sz(tctx, &blob, &str),\
5839 "failed to pull REG_SZ");\
5840 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5844 #define TEST_SET_SZ(wname, iname, val) \
5846 enum winreg_Type type;\
5851 sinfo.info2->iname = val;\
5852 torture_assert(tctx,\
5853 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5854 "failed to call SetPrinter");\
5855 torture_assert(tctx,\
5856 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5857 "failed to query");\
5858 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5859 blob = data_blob_const(data, needed);\
5860 torture_assert(tctx,\
5861 pull_reg_sz(tctx, &blob, &str),\
5862 "failed to pull REG_SZ");\
5863 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5866 #define TEST_SET_DWORD(wname, iname, val) \
5868 enum winreg_Type type;\
5872 sinfo.info2->iname = val;\
5873 torture_assert(tctx,\
5874 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5875 "failed to call SetPrinter");\
5876 torture_assert(tctx,\
5877 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5878 "failed to query");\
5879 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5880 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5881 value = IVAL(data, 0); \
5882 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5885 TEST_SET_SZ("description", comment
, "newval");
5886 TEST_SET_SZ("location", location
, "newval");
5887 TEST_SET_SZ("driverName", drivername
, "newval");
5888 /* TEST_SET_DWORD("priority", priority, 25); */
5890 torture_assert(tctx
,
5891 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
5892 "failed to query Printer level 2");
5894 TEST_SZ("description", info
.info2
.comment
);
5895 TEST_SZ("driverName", info
.info2
.drivername
);
5896 TEST_SZ("location", info
.info2
.location
);
5898 pname
= strrchr(info
.info2
.printername
, '\\');
5899 if (pname
== NULL
) {
5900 pname
= info
.info2
.printername
;
5904 TEST_SZ("printerName", pname
);
5905 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5906 /* TEST_SZ("printShareName", info.info2.sharename); */
5908 /* FIXME gd: complete the list */
5914 torture_comment(tctx
, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5919 static bool test_print_processors_winreg(struct torture_context
*tctx
,
5922 struct test_spoolss_context
*ctx
=
5923 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
5924 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
5925 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5927 return test_PrintProcessors_winreg(tctx
, b
, ctx
->environment
);
5930 static bool test_AddPrintProcessor(struct torture_context
*tctx
,
5931 struct dcerpc_binding_handle
*b
,
5932 const char *environment
,
5933 const char *path_name
,
5934 const char *print_processor_name
,
5935 WERROR expected_error
)
5937 struct spoolss_AddPrintProcessor r
;
5940 r
.in
.architecture
= environment
;
5941 r
.in
.path_name
= path_name
;
5942 r
.in
.print_processor_name
= print_processor_name
;
5944 torture_comment(tctx
, "Testing AddPrintProcessor(%s)\n",
5945 print_processor_name
);
5947 torture_assert_ntstatus_ok(tctx
,
5948 dcerpc_spoolss_AddPrintProcessor_r(b
, tctx
, &r
),
5949 "spoolss_AddPrintProcessor failed");
5950 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_error
,
5951 "spoolss_AddPrintProcessor failed");
5956 static bool test_DeletePrintProcessor(struct torture_context
*tctx
,
5957 struct dcerpc_binding_handle
*b
,
5958 const char *environment
,
5959 const char *print_processor_name
,
5960 WERROR expected_error
)
5962 struct spoolss_DeletePrintProcessor r
;
5965 r
.in
.architecture
= environment
;
5966 r
.in
.print_processor_name
= print_processor_name
;
5968 torture_comment(tctx
, "Testing DeletePrintProcessor(%s)\n",
5969 print_processor_name
);
5971 torture_assert_ntstatus_ok(tctx
,
5972 dcerpc_spoolss_DeletePrintProcessor_r(b
, tctx
, &r
),
5973 "spoolss_DeletePrintProcessor failed");
5974 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_error
,
5975 "spoolss_DeletePrintProcessor failed");
5980 static bool test_add_print_processor(struct torture_context
*tctx
,
5983 struct test_spoolss_context
*ctx
=
5984 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
5985 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
5986 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5990 const char *environment
;
5991 const char *path_name
;
5992 const char *print_processor_name
;
5993 WERROR expected_add_result
;
5994 WERROR expected_del_result
;
5997 .environment
= ctx
->environment
,
5999 .print_processor_name
= "winprint",
6000 .expected_add_result
= WERR_PRINT_PROCESSOR_ALREADY_INSTALLED
,
6001 .expected_del_result
= WERR_CAN_NOT_COMPLETE
6003 .environment
= ctx
->environment
,
6005 .print_processor_name
= "unknown",
6006 .expected_add_result
= WERR_MOD_NOT_FOUND
,
6007 .expected_del_result
= WERR_UNKNOWN_PRINTPROCESSOR
6011 for (i
=0; i
< ARRAY_SIZE(tests
); i
++) {
6012 torture_assert(tctx
,
6013 test_AddPrintProcessor(tctx
, b
,
6014 tests
[i
].environment
,
6016 tests
[i
].print_processor_name
,
6017 tests
[i
].expected_add_result
),
6018 "add print processor failed");
6019 torture_assert(tctx
,
6020 test_DeletePrintProcessor(tctx
, b
,
6021 tests
[i
].environment
,
6022 tests
[i
].print_processor_name
,
6023 tests
[i
].expected_del_result
),
6024 "delete print processor failed");
6030 static bool test_GetChangeID_PrinterData(struct torture_context
*tctx
,
6031 struct dcerpc_binding_handle
*b
,
6032 struct policy_handle
*handle
,
6033 uint32_t *change_id
)
6035 enum winreg_Type type
;
6039 torture_assert(tctx
,
6040 test_GetPrinterData(tctx
, b
, handle
, "ChangeID", &type
, &data
, &needed
),
6041 "failed to call GetPrinterData");
6043 torture_assert(tctx
, type
== REG_DWORD
, "unexpected type");
6044 torture_assert_int_equal(tctx
, needed
, 4, "unexpected size");
6046 *change_id
= IVAL(data
, 0);
6051 static bool test_GetChangeID_PrinterDataEx(struct torture_context
*tctx
,
6052 struct dcerpc_pipe
*p
,
6053 struct policy_handle
*handle
,
6054 uint32_t *change_id
)
6056 enum winreg_Type type
;
6060 torture_assert(tctx
,
6061 test_GetPrinterDataEx(tctx
, p
, handle
, "PrinterDriverData", "ChangeID", &type
, &data
, &needed
),
6062 "failed to call GetPrinterData");
6064 torture_assert(tctx
, type
== REG_DWORD
, "unexpected type");
6065 torture_assert_int_equal(tctx
, needed
, 4, "unexpected size");
6067 *change_id
= IVAL(data
, 0);
6072 static bool test_GetChangeID_PrinterInfo(struct torture_context
*tctx
,
6073 struct dcerpc_binding_handle
*b
,
6074 struct policy_handle
*handle
,
6075 uint32_t *change_id
)
6077 union spoolss_PrinterInfo info
;
6079 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 0, &info
),
6080 "failed to query Printer level 0");
6082 *change_id
= info
.info0
.change_id
;
6087 static bool test_ChangeID(struct torture_context
*tctx
,
6088 struct dcerpc_pipe
*p
,
6089 struct policy_handle
*handle
)
6091 uint32_t change_id
, change_id_ex
, change_id_info
;
6092 uint32_t change_id2
, change_id_ex2
, change_id_info2
;
6093 union spoolss_PrinterInfo info
;
6094 const char *comment
;
6095 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6097 torture_comment(tctx
, "Testing ChangeID: id change test #1\n");
6099 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id
),
6100 "failed to query for ChangeID");
6101 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex
),
6102 "failed to query for ChangeID");
6103 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info
),
6104 "failed to query for ChangeID");
6106 torture_assert_int_equal(tctx
, change_id
, change_id_ex
,
6107 "change_ids should all be equal");
6108 torture_assert_int_equal(tctx
, change_id_ex
, change_id_info
,
6109 "change_ids should all be equal");
6112 torture_comment(tctx
, "Testing ChangeID: id change test #2\n");
6114 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id
),
6115 "failed to query for ChangeID");
6116 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
6117 "failed to query Printer level 2");
6118 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex
),
6119 "failed to query for ChangeID");
6120 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info
),
6121 "failed to query for ChangeID");
6122 torture_assert_int_equal(tctx
, change_id
, change_id_ex
,
6123 "change_id should not have changed");
6124 torture_assert_int_equal(tctx
, change_id_ex
, change_id_info
,
6125 "change_id should not have changed");
6128 torture_comment(tctx
, "Testing ChangeID: id change test #3\n");
6130 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id
),
6131 "failed to query for ChangeID");
6132 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex
),
6133 "failed to query for ChangeID");
6134 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info
),
6135 "failed to query for ChangeID");
6136 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
6137 "failed to query Printer level 2");
6138 comment
= talloc_strdup(tctx
, info
.info2
.comment
);
6141 struct spoolss_SetPrinterInfoCtr info_ctr
;
6142 struct spoolss_DevmodeContainer devmode_ctr
;
6143 struct sec_desc_buf secdesc_ctr
;
6144 union spoolss_SetPrinterInfo sinfo
;
6146 ZERO_STRUCT(info_ctr
);
6147 ZERO_STRUCT(devmode_ctr
);
6148 ZERO_STRUCT(secdesc_ctr
);
6151 torture_assert(tctx
, PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
6152 sinfo
.info2
->comment
= "torture_comment";
6155 info_ctr
.info
= sinfo
;
6157 torture_assert(tctx
, test_SetPrinter(tctx
, b
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0),
6158 "failed to call SetPrinter");
6160 sinfo
.info2
->comment
= comment
;
6162 torture_assert(tctx
, test_SetPrinter(tctx
, b
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0),
6163 "failed to call SetPrinter");
6167 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id2
),
6168 "failed to query for ChangeID");
6169 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex2
),
6170 "failed to query for ChangeID");
6171 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info2
),
6172 "failed to query for ChangeID");
6174 torture_assert_int_equal(tctx
, change_id2
, change_id_ex2
,
6175 "change_ids should all be equal");
6176 torture_assert_int_equal(tctx
, change_id_ex2
, change_id_info2
,
6177 "change_ids should all be equal");
6179 torture_assert(tctx
, (change_id
< change_id2
),
6180 talloc_asprintf(tctx
, "change_id %d needs to be larger than change_id %d",
6181 change_id2
, change_id
));
6182 torture_assert(tctx
, (change_id_ex
< change_id_ex2
),
6183 talloc_asprintf(tctx
, "change_id %d needs to be larger than change_id %d",
6184 change_id_ex2
, change_id_ex
));
6185 torture_assert(tctx
, (change_id_info
< change_id_info2
),
6186 talloc_asprintf(tctx
, "change_id %d needs to be larger than change_id %d",
6187 change_id_info2
, change_id_info
));
6189 torture_comment(tctx
, "ChangeID tests succeeded\n\n");
6194 static bool test_SecondaryClosePrinter(struct torture_context
*tctx
,
6195 struct dcerpc_pipe
*p
,
6196 struct policy_handle
*handle
)
6199 const struct dcerpc_binding
*binding2
;
6200 struct dcerpc_pipe
*p2
;
6201 struct spoolss_ClosePrinter cp
;
6203 /* only makes sense on SMB */
6204 if (p
->conn
->transport
.transport
!= NCACN_NP
) {
6208 torture_comment(tctx
, "Testing close on secondary pipe\n");
6210 binding2
= p
->binding
;
6211 status
= dcerpc_secondary_connection(p
, &p2
, binding2
);
6212 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create secondary connection");
6214 status
= dcerpc_bind_auth_none(p2
, &ndr_table_spoolss
);
6215 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create bind on secondary connection");
6217 cp
.in
.handle
= handle
;
6218 cp
.out
.handle
= handle
;
6220 status
= dcerpc_spoolss_ClosePrinter_r(p2
->binding_handle
, tctx
, &cp
);
6221 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_RPC_SS_CONTEXT_MISMATCH
,
6222 "ERROR: Allowed close on secondary connection");
6229 static bool test_OpenPrinter_badname(struct torture_context
*tctx
,
6230 struct dcerpc_binding_handle
*b
, const char *name
)
6233 struct spoolss_OpenPrinter op
;
6234 struct spoolss_OpenPrinterEx opEx
;
6235 struct policy_handle handle
;
6238 op
.in
.printername
= name
;
6239 op
.in
.datatype
= NULL
;
6240 op
.in
.devmode_ctr
.devmode
= NULL
;
6241 op
.in
.access_mask
= 0;
6242 op
.out
.handle
= &handle
;
6244 torture_comment(tctx
, "Testing OpenPrinter(%s) with bad name\n", op
.in
.printername
);
6246 status
= dcerpc_spoolss_OpenPrinter_r(b
, tctx
, &op
);
6247 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
6248 torture_assert_werr_equal(tctx
, op
.out
.result
, WERR_INVALID_PRINTER_NAME
,
6249 "unexpected result");
6251 if (W_ERROR_IS_OK(op
.out
.result
)) {
6252 ret
&=test_ClosePrinter(tctx
, b
, &handle
);
6255 opEx
.in
.printername
= name
;
6256 opEx
.in
.datatype
= NULL
;
6257 opEx
.in
.devmode_ctr
.devmode
= NULL
;
6258 opEx
.in
.access_mask
= 0;
6259 opEx
.in
.userlevel_ctr
.level
= 1;
6260 opEx
.in
.userlevel_ctr
.user_info
.level1
= NULL
;
6261 opEx
.out
.handle
= &handle
;
6263 torture_comment(tctx
, "Testing OpenPrinterEx(%s) with bad name\n", opEx
.in
.printername
);
6265 status
= dcerpc_spoolss_OpenPrinterEx_r(b
, tctx
, &opEx
);
6266 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinterEx failed");
6267 torture_assert_werr_equal(tctx
, opEx
.out
.result
, WERR_INVALID_PARAM
,
6268 "unexpected result");
6270 if (W_ERROR_IS_OK(opEx
.out
.result
)) {
6271 ret
&=test_ClosePrinter(tctx
, b
, &handle
);
6277 static bool test_OpenPrinter_badname_list(struct torture_context
*tctx
,
6280 struct test_spoolss_context
*ctx
=
6281 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
6283 const char *badnames
[] = {
6284 "__INVALID_PRINTER__",
6285 "\\\\__INVALID_HOST__",
6288 "\\\\\\__INVALID_PRINTER__"
6290 const char *badname
;
6291 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
6292 const char *server_name
= dcerpc_server_name(p
);
6293 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6296 for (i
=0; i
< ARRAY_SIZE(badnames
); i
++) {
6297 torture_assert(tctx
,
6298 test_OpenPrinter_badname(tctx
, b
, badnames
[i
]),
6302 badname
= talloc_asprintf(tctx
, "\\\\%s\\", server_name
);
6303 torture_assert(tctx
,
6304 test_OpenPrinter_badname(tctx
, b
, badname
),
6307 badname
= talloc_asprintf(tctx
, "\\\\%s\\__INVALID_PRINTER__", server_name
);
6308 torture_assert(tctx
,
6309 test_OpenPrinter_badname(tctx
, b
, badname
),
6315 static bool test_OpenPrinter(struct torture_context
*tctx
,
6316 struct dcerpc_pipe
*p
,
6318 const char *environment
,
6322 struct spoolss_OpenPrinter r
;
6323 struct policy_handle handle
;
6325 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6327 r
.in
.printername
= name
;
6328 r
.in
.datatype
= NULL
;
6329 r
.in
.devmode_ctr
.devmode
= NULL
;
6330 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
6331 r
.out
.handle
= &handle
;
6333 torture_comment(tctx
, "Testing OpenPrinter(%s)\n", r
.in
.printername
);
6335 status
= dcerpc_spoolss_OpenPrinter_r(b
, tctx
, &r
);
6337 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
6339 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenPrinter failed");
6345 if (!test_GetPrinter(tctx
, b
, &handle
, environment
)) {
6349 if (!torture_setting_bool(tctx
, "samba3", false)) {
6350 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
6356 if (!test_ClosePrinter(tctx
, b
, &handle
)) {
6363 static bool test_OpenPrinterEx(struct torture_context
*tctx
,
6364 struct dcerpc_binding_handle
*b
,
6365 const char *printername
,
6366 const char *datatype
,
6367 struct spoolss_DeviceMode
*devmode
,
6368 uint32_t access_mask
,
6369 struct spoolss_UserLevelCtr
*userlevel_ctr
,
6370 struct policy_handle
*handle
,
6371 WERROR expected_result
)
6373 struct spoolss_OpenPrinterEx r
;
6375 r
.in
.printername
= printername
;
6376 r
.in
.datatype
= datatype
;
6377 r
.in
.devmode_ctr
.devmode
= devmode
;
6378 r
.in
.access_mask
= access_mask
;
6379 r
.in
.userlevel_ctr
= *userlevel_ctr
;
6380 r
.out
.handle
= handle
;
6382 torture_comment(tctx
, "Testing OpenPrinterEx(%s)\n", r
.in
.printername
);
6384 torture_assert_ntstatus_ok(tctx
,
6385 dcerpc_spoolss_OpenPrinterEx_r(b
, tctx
, &r
),
6386 "OpenPrinterEx failed");
6388 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
6389 "OpenPrinterEx failed");
6394 static bool call_OpenPrinterEx(struct torture_context
*tctx
,
6395 struct dcerpc_pipe
*p
,
6397 struct spoolss_DeviceMode
*devmode
,
6398 struct policy_handle
*handle
)
6400 struct spoolss_UserLevelCtr userlevel_ctr
;
6401 struct spoolss_UserLevel1 userlevel1
;
6402 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6404 userlevel1
.size
= 1234;
6405 userlevel1
.client
= "hello";
6406 userlevel1
.user
= "spottyfoot!";
6407 userlevel1
.build
= 1;
6408 userlevel1
.major
= 2;
6409 userlevel1
.minor
= 3;
6410 userlevel1
.processor
= 4;
6412 userlevel_ctr
.level
= 1;
6413 userlevel_ctr
.user_info
.level1
= &userlevel1
;
6415 return test_OpenPrinterEx(tctx
, b
, name
, NULL
, devmode
,
6416 SEC_FLAG_MAXIMUM_ALLOWED
,
6422 static bool test_printer_rename(struct torture_context
*tctx
,
6425 struct torture_printer_context
*t
=
6426 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
6427 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
6430 union spoolss_PrinterInfo info
;
6431 union spoolss_SetPrinterInfo sinfo
;
6432 struct spoolss_SetPrinterInfoCtr info_ctr
;
6433 struct spoolss_DevmodeContainer devmode_ctr
;
6434 struct sec_desc_buf secdesc_ctr
;
6435 const char *printer_name
;
6436 const char *printer_name_orig
;
6437 const char *printer_name_new
= "SAMBA smbtorture Test Printer (Copy 2)";
6438 struct policy_handle new_handle
;
6440 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6442 ZERO_STRUCT(devmode_ctr
);
6443 ZERO_STRUCT(secdesc_ctr
);
6445 torture_comment(tctx
, "Testing Printer rename operations\n");
6447 torture_assert(tctx
,
6448 test_GetPrinter_level(tctx
, b
, &t
->handle
, 2, &info
),
6449 "failed to call GetPrinter level 2");
6451 printer_name_orig
= talloc_strdup(tctx
, info
.info2
.printername
);
6453 q
= strrchr(info
.info2
.printername
, '\\');
6455 torture_warning(tctx
,
6456 "server returns printername %s incl. servername although we did not set servername", info
.info2
.printername
);
6459 torture_assert(tctx
,
6460 PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
6462 sinfo
.info2
->printername
= printer_name_new
;
6465 info_ctr
.info
= sinfo
;
6467 torture_assert(tctx
,
6468 test_SetPrinter(tctx
, b
, &t
->handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0),
6469 "failed to call SetPrinter level 2");
6471 torture_assert(tctx
,
6472 test_GetPrinter_level(tctx
, b
, &t
->handle
, 2, &info
),
6473 "failed to call GetPrinter level 2");
6475 printer_name
= talloc_strdup(tctx
, info
.info2
.printername
);
6477 q
= strrchr(info
.info2
.printername
, '\\');
6479 torture_warning(tctx
,
6480 "server returns printername %s incl. servername although we did not set servername", info
.info2
.printername
);
6485 torture_assert_str_equal(tctx
, printer_name
, printer_name_new
,
6486 "new printer name was not set");
6488 /* samba currently cannot fully rename printers */
6489 if (!torture_setting_bool(tctx
, "samba3", false)) {
6490 torture_assert(tctx
,
6491 test_OpenPrinter_badname(tctx
, b
, printer_name_orig
),
6492 "still can open printer with oldname after rename");
6494 torture_warning(tctx
, "*not* checking for open with oldname after rename for samba3");
6497 torture_assert(tctx
,
6498 call_OpenPrinterEx(tctx
, p
, printer_name_new
, NULL
, &new_handle
),
6499 "failed to open printer with new name");
6501 torture_assert(tctx
,
6502 test_GetPrinter_level(tctx
, b
, &new_handle
, 2, &info
),
6503 "failed to call GetPrinter level 2");
6505 torture_assert_str_equal(tctx
, info
.info2
.printername
, printer_name_new
,
6506 "new printer name was not set");
6508 torture_assert(tctx
,
6509 test_ClosePrinter(tctx
, b
, &new_handle
),
6510 "failed to close printer");
6512 torture_comment(tctx
, "Printer rename operations test succeeded\n\n");
6517 static bool test_openprinter(struct torture_context
*tctx
,
6518 struct dcerpc_binding_handle
*b
,
6519 const char *real_printername
)
6521 struct spoolss_UserLevelCtr userlevel_ctr
;
6522 struct policy_handle handle
;
6523 struct spoolss_UserLevel1 userlevel1
;
6524 const char *printername
= NULL
;
6529 WERROR expected_result
;
6532 .suffix
= "rubbish",
6533 .expected_result
= WERR_INVALID_PRINTER_NAME
6535 .suffix
= ", LocalOnl",
6536 .expected_result
= WERR_INVALID_PRINTER_NAME
6538 .suffix
= ", localOnly",
6539 .expected_result
= WERR_INVALID_PRINTER_NAME
6541 .suffix
= ", localonl",
6542 .expected_result
= WERR_INVALID_PRINTER_NAME
6544 .suffix
= ",LocalOnl",
6545 .expected_result
= WERR_INVALID_PRINTER_NAME
6547 .suffix
= ",localOnl2",
6548 .expected_result
= WERR_INVALID_PRINTER_NAME
6550 .suffix
= ", DrvConver2t",
6551 .expected_result
= WERR_INVALID_PRINTER_NAME
6553 .suffix
= ", drvconvert",
6554 .expected_result
= WERR_INVALID_PRINTER_NAME
6556 .suffix
= ",drvconvert",
6557 .expected_result
= WERR_INVALID_PRINTER_NAME
6559 .suffix
= ", DrvConvert",
6560 .expected_result
= WERR_OK
6562 .suffix
= " , DrvConvert",
6563 .expected_result
= WERR_INVALID_PRINTER_NAME
6565 .suffix
= ",DrvConvert",
6566 .expected_result
= WERR_OK
6568 .suffix
= ", DrvConvertsadfasdf",
6569 .expected_result
= WERR_OK
6571 .suffix
= ",DrvConvertasdfasd",
6572 .expected_result
= WERR_OK
6574 .suffix
= ", LocalOnly",
6575 .expected_result
= WERR_OK
6577 .suffix
= " , LocalOnly",
6578 .expected_result
= WERR_INVALID_PRINTER_NAME
6580 .suffix
= ",LocalOnly",
6581 .expected_result
= WERR_OK
6583 .suffix
= ", LocalOnlysagi4gjfkd",
6584 .expected_result
= WERR_OK
6586 .suffix
= ",LocalOnlysagi4gjfkd",
6587 .expected_result
= WERR_OK
6591 userlevel1
.size
= 1234;
6592 userlevel1
.client
= "hello";
6593 userlevel1
.user
= "spottyfoot!";
6594 userlevel1
.build
= 1;
6595 userlevel1
.major
= 2;
6596 userlevel1
.minor
= 3;
6597 userlevel1
.processor
= 4;
6599 userlevel_ctr
.level
= 1;
6600 userlevel_ctr
.user_info
.level1
= &userlevel1
;
6602 torture_comment(tctx
, "Testing openprinterex printername pattern\n");
6604 torture_assert(tctx
,
6605 test_OpenPrinterEx(tctx
, b
, real_printername
, NULL
, NULL
, 0,
6606 &userlevel_ctr
, &handle
,
6608 "OpenPrinterEx failed");
6609 test_ClosePrinter(tctx
, b
, &handle
);
6611 for (i
=0; i
< ARRAY_SIZE(tests
); i
++) {
6613 printername
= talloc_asprintf(tctx
, "%s%s",
6617 torture_assert(tctx
,
6618 test_OpenPrinterEx(tctx
, b
, printername
, NULL
, NULL
, 0,
6619 &userlevel_ctr
, &handle
,
6620 tests
[i
].expected_result
),
6621 "OpenPrinterEx failed");
6622 if (W_ERROR_IS_OK(tests
[i
].expected_result
)) {
6623 test_ClosePrinter(tctx
, b
, &handle
);
6631 static bool test_existing_printer_openprinterex(struct torture_context
*tctx
,
6632 struct dcerpc_pipe
*p
,
6634 const char *environment
)
6636 struct policy_handle handle
;
6638 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6640 if (!test_openprinter(tctx
, b
, name
)) {
6644 if (!call_OpenPrinterEx(tctx
, p
, name
, NULL
, &handle
)) {
6648 if (!test_PrinterInfo_SD(tctx
, b
, &handle
)) {
6652 if (!test_GetPrinter(tctx
, b
, &handle
, environment
)) {
6656 if (!test_EnumForms_all(tctx
, b
, &handle
, false)) {
6660 if (!test_Forms(tctx
, b
, &handle
, false, name
, NULL
, NULL
)) {
6664 if (!test_Forms_winreg(tctx
, b
, &handle
, false, name
)) {
6668 if (!test_EnumPrinterData_all(tctx
, p
, &handle
)) {
6672 if (!test_EnumPrinterDataEx(tctx
, b
, &handle
, "PrinterDriverData", NULL
, NULL
)) {
6676 if (!test_EnumPrinterData_consistency(tctx
, p
, &handle
)) {
6680 if (!test_printer_all_keys(tctx
, b
, &handle
)) {
6684 if (!test_PausePrinter(tctx
, b
, &handle
)) {
6688 if (!test_DoPrintTest(tctx
, b
, &handle
)) {
6692 if (!test_ResumePrinter(tctx
, b
, &handle
)) {
6696 if (!test_SetPrinterData_matrix(tctx
, b
, &handle
, name
, NULL
, NULL
)) {
6700 if (!test_SetPrinterDataEx_matrix(tctx
, p
, &handle
, name
, NULL
, NULL
)) {
6704 if (!torture_setting_bool(tctx
, "samba3", false)) {
6705 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
6710 if (!test_ClosePrinter(tctx
, b
, &handle
)) {
6717 static bool test_EnumPrinters_old(struct torture_context
*tctx
,
6720 struct test_spoolss_context
*ctx
=
6721 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
6722 struct spoolss_EnumPrinters r
;
6724 uint16_t levels
[] = {1, 2, 4, 5};
6727 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
6728 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6730 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
6731 union spoolss_PrinterInfo
*info
;
6736 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
6738 r
.in
.level
= levels
[i
];
6741 r
.out
.needed
= &needed
;
6742 r
.out
.count
= &count
;
6745 torture_comment(tctx
, "Testing EnumPrinters level %u\n", r
.in
.level
);
6747 status
= dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &r
);
6748 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
6750 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
6751 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
6752 r
.in
.buffer
= &blob
;
6753 r
.in
.offered
= needed
;
6754 status
= dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &r
);
6757 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
6759 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
6761 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters
, info
, r
.in
.level
, count
, needed
, 4);
6764 torture_comment(tctx
, "No printers returned\n");
6768 for (j
=0;j
<count
;j
++) {
6769 if (r
.in
.level
== 1) {
6770 char *unc
= talloc_strdup(tctx
, info
[j
].info1
.name
);
6771 char *slash
, *name
, *full_name
;
6773 if (unc
[0] == '\\' && unc
[1] == '\\') {
6776 slash
= strchr(unc
, '\\');
6781 full_name
= talloc_asprintf(tctx
, "\\\\%s\\%s",
6782 dcerpc_server_name(p
), name
);
6783 if (!test_OpenPrinter(tctx
, p
, name
, ctx
->environment
, true)) {
6786 if (!test_OpenPrinter(tctx
, p
, full_name
, ctx
->environment
, true)) {
6789 if (!test_OpenPrinter(tctx
, p
, name
, ctx
->environment
, false)) {
6792 if (!test_existing_printer_openprinterex(tctx
, p
, name
, ctx
->environment
)) {
6802 static bool test_EnumPrinters_level(struct torture_context
*tctx
,
6803 struct dcerpc_binding_handle
*b
,
6805 const char *servername
,
6808 union spoolss_PrinterInfo
**info_p
)
6810 struct spoolss_EnumPrinters r
;
6811 union spoolss_PrinterInfo
*info
;
6816 r
.in
.server
= servername
;
6820 r
.out
.needed
= &needed
;
6821 r
.out
.count
= &count
;
6824 torture_comment(tctx
, "Testing EnumPrinters(%s) level %u\n",
6825 r
.in
.server
, r
.in
.level
);
6827 torture_assert_ntstatus_ok(tctx
,
6828 dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &r
),
6829 "EnumPrinters failed");
6830 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
6831 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
6832 r
.in
.buffer
= &blob
;
6833 r
.in
.offered
= needed
;
6834 torture_assert_ntstatus_ok(tctx
,
6835 dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &r
),
6836 "EnumPrinters failed");
6839 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
6841 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters
, info
, r
.in
.level
, count
, needed
, 4);
6853 static const char *get_short_printername(struct torture_context
*tctx
,
6856 const char *short_name
;
6858 if (name
[0] == '\\' && name
[1] == '\\') {
6860 short_name
= strchr(name
, '\\');
6862 return talloc_strdup(tctx
, short_name
+1);
6869 static const char *get_full_printername(struct torture_context
*tctx
,
6872 const char *full_name
= talloc_strdup(tctx
, name
);
6875 if (name
&& name
[0] == '\\' && name
[1] == '\\') {
6877 p
= strchr(name
, '\\');
6886 static bool test_OnePrinter_servername(struct torture_context
*tctx
,
6887 struct dcerpc_pipe
*p
,
6888 struct dcerpc_binding_handle
*b
,
6889 const char *servername
,
6890 const char *printername
)
6892 union spoolss_PrinterInfo info
;
6893 const char *short_name
= get_short_printername(tctx
, printername
);
6894 const char *full_name
= get_full_printername(tctx
, printername
);
6897 struct policy_handle handle
;
6898 torture_assert(tctx
,
6899 call_OpenPrinterEx(tctx
, p
, short_name
, NULL
, &handle
),
6900 "failed to open printer");
6902 torture_assert(tctx
,
6903 test_GetPrinter_level(tctx
, b
, &handle
, 2, &info
),
6904 "failed to get printer info");
6906 torture_assert_casestr_equal(tctx
, info
.info2
.servername
, NULL
,
6907 "unexpected servername");
6908 torture_assert_casestr_equal(tctx
, info
.info2
.printername
, short_name
,
6909 "unexpected printername");
6911 if (info
.info2
.devmode
) {
6912 const char *expected_devicename
;
6913 expected_devicename
= talloc_strndup(tctx
, short_name
, MIN(strlen(short_name
), 31));
6914 torture_assert_casestr_equal(tctx
, info
.info2
.devmode
->devicename
, expected_devicename
,
6915 "unexpected devicemode devicename");
6918 torture_assert(tctx
,
6919 test_ClosePrinter(tctx
, b
, &handle
),
6920 "failed to close printer");
6924 struct policy_handle handle
;
6926 torture_assert(tctx
,
6927 call_OpenPrinterEx(tctx
, p
, full_name
, NULL
, &handle
),
6928 "failed to open printer");
6930 torture_assert(tctx
,
6931 test_GetPrinter_level(tctx
, b
, &handle
, 2, &info
),
6932 "failed to get printer info");
6934 torture_assert_casestr_equal(tctx
, info
.info2
.servername
, servername
,
6935 "unexpected servername");
6936 torture_assert_casestr_equal(tctx
, info
.info2
.printername
, full_name
,
6937 "unexpected printername");
6939 if (info
.info2
.devmode
) {
6940 const char *expected_devicename
;
6941 expected_devicename
= talloc_strndup(tctx
, full_name
, MIN(strlen(full_name
), 31));
6942 torture_assert_casestr_equal(tctx
, info
.info2
.devmode
->devicename
, expected_devicename
,
6943 "unexpected devicemode devicename");
6946 torture_assert(tctx
,
6947 test_ClosePrinter(tctx
, b
, &handle
),
6948 "failed to close printer");
6954 static bool test_EnumPrinters_servername(struct torture_context
*tctx
,
6957 struct test_spoolss_context
*ctx
=
6958 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
6960 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
6961 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6963 union spoolss_PrinterInfo
*info
;
6964 const char *servername
;
6965 uint32_t flags
= PRINTER_ENUM_NAME
|PRINTER_ENUM_LOCAL
;
6967 torture_comment(tctx
, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6969 servername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
6971 torture_assert(tctx
,
6972 test_EnumPrinters_level(tctx
, b
, flags
, servername
, 2, &count
, &info
),
6973 "failed to enumerate printers");
6975 for (i
=0; i
< count
; i
++) {
6977 torture_assert_casestr_equal(tctx
, info
[i
].info2
.servername
, servername
,
6978 "unexpected servername");
6980 torture_assert(tctx
,
6981 test_OnePrinter_servername(tctx
, p
, b
, servername
, info
[i
].info2
.printername
),
6982 "failed to check printer");
6987 torture_assert(tctx
,
6988 test_EnumPrinters_level(tctx
, b
, flags
, servername
, 2, &count
, &info
),
6989 "failed to enumerate printers");
6991 for (i
=0; i
< count
; i
++) {
6993 torture_assert_casestr_equal(tctx
, info
[i
].info2
.servername
, NULL
,
6994 "unexpected servername");
6996 torture_assert(tctx
,
6997 test_OnePrinter_servername(tctx
, p
, b
, servername
, info
[i
].info2
.printername
),
6998 "failed to check printer");
7006 static bool test_GetPrinterDriver(struct torture_context
*tctx
,
7007 struct dcerpc_binding_handle
*b
,
7008 struct policy_handle
*handle
,
7009 const char *driver_name
)
7011 struct spoolss_GetPrinterDriver r
;
7014 r
.in
.handle
= handle
;
7015 r
.in
.architecture
= "W32X86";
7019 r
.out
.needed
= &needed
;
7021 torture_comment(tctx
, "Testing GetPrinterDriver level %d\n", r
.in
.level
);
7023 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver_r(b
, tctx
, &r
),
7024 "failed to call GetPrinterDriver");
7025 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
7026 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
7027 r
.in
.buffer
= &blob
;
7028 r
.in
.offered
= needed
;
7029 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver_r(b
, tctx
, &r
),
7030 "failed to call GetPrinterDriver");
7033 torture_assert_werr_ok(tctx
, r
.out
.result
,
7034 "failed to call GetPrinterDriver");
7036 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo
, r
.out
.info
, r
.in
.level
, needed
, 4);
7042 static bool test_GetPrinterDriver2_level(struct torture_context
*tctx
,
7043 struct dcerpc_binding_handle
*b
,
7044 struct policy_handle
*handle
,
7045 const char *driver_name
,
7046 const char *architecture
,
7048 uint32_t client_major_version
,
7049 uint32_t client_minor_version
,
7050 union spoolss_DriverInfo
*info_p
,
7054 struct spoolss_GetPrinterDriver2 r
;
7056 uint32_t server_major_version
;
7057 uint32_t server_minor_version
;
7059 r
.in
.handle
= handle
;
7060 r
.in
.architecture
= architecture
;
7061 r
.in
.client_major_version
= client_major_version
;
7062 r
.in
.client_minor_version
= client_minor_version
;
7066 r
.out
.needed
= &needed
;
7067 r
.out
.server_major_version
= &server_major_version
;
7068 r
.out
.server_minor_version
= &server_minor_version
;
7070 torture_comment(tctx
, "Testing GetPrinterDriver2(%s) level %d\n",
7071 driver_name
, r
.in
.level
);
7073 torture_assert_ntstatus_ok(tctx
,
7074 dcerpc_spoolss_GetPrinterDriver2_r(b
, tctx
, &r
),
7075 "failed to call GetPrinterDriver2");
7076 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
7077 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
7078 r
.in
.buffer
= &blob
;
7079 r
.in
.offered
= needed
;
7080 torture_assert_ntstatus_ok(tctx
,
7081 dcerpc_spoolss_GetPrinterDriver2_r(b
, tctx
, &r
),
7082 "failed to call GetPrinterDriver2");
7086 *result_p
= r
.out
.result
;
7089 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INVALID_LEVEL
)) {
7090 switch (r
.in
.level
) {
7093 torture_comment(tctx
,
7094 "level %d not implemented, not considering as an error\n",
7102 torture_assert_werr_ok(tctx
, r
.out
.result
,
7103 "failed to call GetPrinterDriver2");
7105 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo
, r
.out
.info
, r
.in
.level
, needed
, 4);
7108 *info_p
= *r
.out
.info
;
7114 static bool test_GetPrinterDriver2(struct torture_context
*tctx
,
7115 struct dcerpc_binding_handle
*b
,
7116 struct policy_handle
*handle
,
7117 const char *driver_name
,
7118 const char *architecture
)
7120 uint16_t levels
[] = {1, 2, 3, 4, 5, 6, 8, 101 };
7124 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
7126 torture_assert(tctx
,
7127 test_GetPrinterDriver2_level(tctx
, b
, handle
, driver_name
, architecture
, levels
[i
], 3, 0, NULL
, NULL
),
7134 static bool test_EnumPrinterDrivers_old(struct torture_context
*tctx
,
7137 struct test_spoolss_context
*ctx
=
7138 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
7139 uint16_t levels
[] = {1, 2, 3, 4, 5, 6};
7141 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
7142 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7143 const char *server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
7145 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
7148 union spoolss_DriverInfo
*info
;
7150 torture_assert(tctx
,
7151 test_EnumPrinterDrivers_args(tctx
, b
, server_name
, ctx
->environment
, levels
[i
], &count
, &info
),
7152 "failed to enumerate drivers");
7155 torture_comment(tctx
, "No printer drivers returned\n");
7163 static bool test_DeletePrinter(struct torture_context
*tctx
,
7164 struct dcerpc_binding_handle
*b
,
7165 struct policy_handle
*handle
)
7167 struct spoolss_DeletePrinter r
;
7169 torture_comment(tctx
, "Testing DeletePrinter\n");
7171 r
.in
.handle
= handle
;
7173 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_DeletePrinter_r(b
, tctx
, &r
),
7174 "failed to delete printer");
7175 torture_assert_werr_ok(tctx
, r
.out
.result
,
7176 "failed to delete printer");
7181 static bool test_EnumPrinters_findname(struct torture_context
*tctx
,
7182 struct dcerpc_binding_handle
*b
,
7188 struct spoolss_EnumPrinters e
;
7190 union spoolss_PrinterInfo
*info
;
7201 e
.out
.count
= &count
;
7203 e
.out
.needed
= &needed
;
7205 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &e
),
7206 "failed to enum printers");
7208 if (W_ERROR_EQUAL(e
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
7209 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
7210 e
.in
.buffer
= &blob
;
7211 e
.in
.offered
= needed
;
7213 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &e
),
7214 "failed to enum printers");
7217 torture_assert_werr_ok(tctx
, e
.out
.result
,
7218 "failed to enum printers");
7220 for (i
=0; i
< count
; i
++) {
7222 const char *current
= NULL
;
7227 current
= info
[i
].info1
.name
;
7231 if (strequal(current
, name
)) {
7236 q
= strrchr(current
, '\\');
7239 torture_warning(tctx
,
7240 "server returns printername %s incl. servername although we did not set servername", current
);
7243 if (strequal(q
, name
)) {
7253 static bool test_AddPrinter_wellknown(struct torture_context
*tctx
,
7254 struct dcerpc_pipe
*p
,
7255 const char *printername
,
7259 struct spoolss_AddPrinter r
;
7260 struct spoolss_AddPrinterEx rex
;
7261 struct spoolss_SetPrinterInfoCtr info_ctr
;
7262 struct spoolss_SetPrinterInfo1 info1
;
7263 struct spoolss_DevmodeContainer devmode_ctr
;
7264 struct sec_desc_buf secdesc_ctr
;
7265 struct spoolss_UserLevelCtr userlevel_ctr
;
7266 struct policy_handle handle
;
7268 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7270 ZERO_STRUCT(devmode_ctr
);
7271 ZERO_STRUCT(secdesc_ctr
);
7272 ZERO_STRUCT(userlevel_ctr
);
7275 torture_comment(tctx
, "Testing AddPrinter%s(%s) level 1\n",
7276 ex
? "Ex":"", printername
);
7278 /* try to add printer to wellknown printer list (level 1) */
7280 userlevel_ctr
.level
= 1;
7282 info_ctr
.info
.info1
= &info1
;
7285 rex
.in
.server
= NULL
;
7286 rex
.in
.info_ctr
= &info_ctr
;
7287 rex
.in
.devmode_ctr
= &devmode_ctr
;
7288 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
7289 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
7290 rex
.out
.handle
= &handle
;
7293 r
.in
.info_ctr
= &info_ctr
;
7294 r
.in
.devmode_ctr
= &devmode_ctr
;
7295 r
.in
.secdesc_ctr
= &secdesc_ctr
;
7296 r
.out
.handle
= &handle
;
7298 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7299 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7300 "failed to add printer");
7301 result
= ex
? rex
.out
.result
: r
.out
.result
;
7302 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
7303 "unexpected result code");
7305 info1
.name
= printername
;
7306 info1
.flags
= PRINTER_ATTRIBUTE_SHARED
;
7308 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7309 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7310 "failed to add printer");
7311 result
= ex
? rex
.out
.result
: r
.out
.result
;
7312 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
7313 "unexpected result code");
7315 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7316 better do a real check to see the printer is really there */
7318 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, b
,
7319 PRINTER_ENUM_NETWORK
, 1,
7322 "failed to enum printers");
7324 torture_assert(tctx
, found
, "failed to find newly added printer");
7328 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7329 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7330 "failed to add printer");
7331 result
= ex
? rex
.out
.result
: r
.out
.result
;
7332 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
7333 "unexpected result code");
7335 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7336 better do a real check to see the printer has really been removed
7337 from the well known printer list */
7341 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, b
,
7342 PRINTER_ENUM_NETWORK
, 1,
7345 "failed to enum printers");
7347 torture_assert(tctx
, !found
, "printer still in well known printer list");
7352 static bool test_AddPrinter_normal(struct torture_context
*tctx
,
7353 struct dcerpc_pipe
*p
,
7354 struct policy_handle
*handle_p
,
7355 const char *printername
,
7356 const char *drivername
,
7357 const char *portname
,
7358 struct spoolss_DeviceMode
*devmode
,
7362 struct spoolss_AddPrinter r
;
7363 struct spoolss_AddPrinterEx rex
;
7364 struct spoolss_SetPrinterInfoCtr info_ctr
;
7365 struct spoolss_SetPrinterInfo2 info2
;
7366 struct spoolss_DevmodeContainer devmode_ctr
;
7367 struct sec_desc_buf secdesc_ctr
;
7368 struct spoolss_UserLevelCtr userlevel_ctr
;
7369 struct policy_handle handle
;
7371 bool existing_printer_deleted
= false;
7372 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7374 ZERO_STRUCT(devmode_ctr
);
7375 ZERO_STRUCT(secdesc_ctr
);
7376 ZERO_STRUCT(userlevel_ctr
);
7378 torture_comment(tctx
, "Testing AddPrinter%s(%s) level 2\n",
7379 ex
? "Ex":"", printername
);
7381 devmode_ctr
.devmode
= devmode
;
7383 userlevel_ctr
.level
= 1;
7385 rex
.in
.server
= NULL
;
7386 rex
.in
.info_ctr
= &info_ctr
;
7387 rex
.in
.devmode_ctr
= &devmode_ctr
;
7388 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
7389 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
7390 rex
.out
.handle
= &handle
;
7393 r
.in
.info_ctr
= &info_ctr
;
7394 r
.in
.devmode_ctr
= &devmode_ctr
;
7395 r
.in
.secdesc_ctr
= &secdesc_ctr
;
7396 r
.out
.handle
= &handle
;
7400 /* try to add printer to printer list (level 2) */
7404 info_ctr
.info
.info2
= &info2
;
7407 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7408 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7409 "failed to add printer");
7410 result
= ex
? rex
.out
.result
: r
.out
.result
;
7411 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
7412 "unexpected result code");
7414 info2
.printername
= printername
;
7416 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7417 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7418 "failed to add printer");
7419 result
= ex
? rex
.out
.result
: r
.out
.result
;
7421 if (W_ERROR_EQUAL(result
, WERR_PRINTER_ALREADY_EXISTS
)) {
7422 struct policy_handle printer_handle
;
7424 if (existing_printer_deleted
) {
7425 torture_fail(tctx
, "already deleted printer still existing?");
7428 torture_assert(tctx
, call_OpenPrinterEx(tctx
, p
, printername
, NULL
, &printer_handle
),
7429 "failed to open printer handle");
7431 torture_assert(tctx
, test_DeletePrinter(tctx
, b
, &printer_handle
),
7432 "failed to delete printer");
7434 torture_assert(tctx
, test_ClosePrinter(tctx
, b
, &printer_handle
),
7435 "failed to close server handle");
7437 existing_printer_deleted
= true;
7442 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PORT
,
7443 "unexpected result code");
7445 info2
.portname
= portname
;
7447 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7448 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7449 "failed to add printer");
7450 result
= ex
? rex
.out
.result
: r
.out
.result
;
7451 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTER_DRIVER
,
7452 "unexpected result code");
7454 info2
.drivername
= drivername
;
7456 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7457 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7458 "failed to add printer");
7459 result
= ex
? rex
.out
.result
: r
.out
.result
;
7461 /* w2k8r2 allows to add printer w/o defining printprocessor */
7463 if (!W_ERROR_IS_OK(result
)) {
7464 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTPROCESSOR
,
7465 "unexpected result code");
7467 info2
.printprocessor
= "winprint";
7469 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7470 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7471 "failed to add printer");
7472 result
= ex
? rex
.out
.result
: r
.out
.result
;
7473 torture_assert_werr_ok(tctx
, result
,
7474 "failed to add printer");
7479 /* we are paranoid, really check if the printer is there now */
7481 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, b
,
7482 PRINTER_ENUM_LOCAL
, 1,
7485 "failed to enum printers");
7486 torture_assert(tctx
, found
, "failed to find newly added printer");
7488 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7489 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7490 "failed to add printer");
7491 result
= ex
? rex
.out
.result
: r
.out
.result
;
7492 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
7493 "unexpected result code");
7498 static bool test_printer_info(struct torture_context
*tctx
,
7501 struct torture_printer_context
*t
=
7502 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
7503 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
7504 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7508 if (torture_setting_bool(tctx
, "samba3", false)) {
7509 torture_skip(tctx
, "skipping printer info cross tests against samba 3");
7512 if (!test_PrinterInfo(tctx
, b
, &t
->handle
)) {
7516 if (!test_SetPrinter_errors(tctx
, b
, &t
->handle
)) {
7523 static bool test_EnumPrinterKey(struct torture_context
*tctx
,
7524 struct dcerpc_binding_handle
*b
,
7525 struct policy_handle
*handle
,
7526 const char *key_name
,
7527 const char ***array
)
7529 struct spoolss_EnumPrinterKey r
;
7530 uint32_t needed
= 0;
7531 union spoolss_KeyNames key_buffer
;
7532 int32_t offered
[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7536 r
.in
.handle
= handle
;
7537 r
.in
.key_name
= key_name
;
7538 r
.out
.key_buffer
= &key_buffer
;
7539 r
.out
.needed
= &needed
;
7540 r
.out
._ndr_size
= &_ndr_size
;
7542 for (i
=0; i
< ARRAY_SIZE(offered
); i
++) {
7544 if (offered
[i
] < 0 && needed
) {
7548 r
.in
.offered
= needed
+ offered
[i
];
7550 r
.in
.offered
= offered
[i
];
7553 ZERO_STRUCT(key_buffer
);
7555 torture_comment(tctx
, "Testing EnumPrinterKey(%s) with %d offered\n", r
.in
.key_name
, r
.in
.offered
);
7557 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterKey_r(b
, tctx
, &r
),
7558 "failed to call EnumPrinterKey");
7559 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
7561 torture_assert(tctx
, (_ndr_size
== r
.in
.offered
/2),
7562 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7563 _ndr_size
, r
.in
.offered
/2));
7565 r
.in
.offered
= needed
;
7566 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterKey_r(b
, tctx
, &r
),
7567 "failed to call EnumPrinterKey");
7570 if (offered
[i
] > 0) {
7571 torture_assert_werr_ok(tctx
, r
.out
.result
,
7572 "failed to call EnumPrinterKey");
7575 torture_assert(tctx
, (_ndr_size
== r
.in
.offered
/2),
7576 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7577 _ndr_size
, r
.in
.offered
/2));
7579 torture_assert(tctx
, (*r
.out
.needed
<= r
.in
.offered
),
7580 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r
.out
.needed
, r
.in
.offered
));
7582 torture_assert(tctx
, (*r
.out
.needed
<= _ndr_size
* 2),
7583 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r
.out
.needed
, _ndr_size
));
7585 if (key_buffer
.string_array
) {
7586 uint32_t calc_needed
= 0;
7588 for (s
=0; key_buffer
.string_array
[s
]; s
++) {
7589 calc_needed
+= strlen_m_term(key_buffer
.string_array
[s
])*2;
7591 if (!key_buffer
.string_array
[0]) {
7596 torture_assert_int_equal(tctx
, *r
.out
.needed
, calc_needed
,
7597 "EnumPrinterKey unexpected size");
7602 *array
= key_buffer
.string_array
;
7608 bool test_printer_all_keys(struct torture_context
*tctx
,
7609 struct dcerpc_binding_handle
*b
,
7610 struct policy_handle
*handle
)
7612 const char **key_array
= NULL
;
7615 torture_comment(tctx
, "Testing Printer Keys\n");
7617 torture_assert(tctx
, test_EnumPrinterKey(tctx
, b
, handle
, "", &key_array
),
7618 "failed to call test_EnumPrinterKey");
7620 for (i
=0; key_array
&& key_array
[i
]; i
++) {
7621 torture_assert(tctx
, test_EnumPrinterKey(tctx
, b
, handle
, key_array
[i
], NULL
),
7622 "failed to call test_EnumPrinterKey");
7624 for (i
=0; key_array
&& key_array
[i
]; i
++) {
7625 torture_assert(tctx
, test_EnumPrinterDataEx(tctx
, b
, handle
, key_array
[i
], NULL
, NULL
),
7626 "failed to call test_EnumPrinterDataEx");
7629 torture_comment(tctx
, "Printer Keys test succeeded\n\n");
7634 static bool test_openprinter_wrap(struct torture_context
*tctx
,
7637 struct torture_printer_context
*t
=
7638 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
7639 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
7640 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7641 const char *printername
= t
->info2
.printername
;
7643 return test_openprinter(tctx
, b
, printername
);
7646 static bool test_csetprinter(struct torture_context
*tctx
,
7649 struct torture_printer_context
*t
=
7650 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
7651 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
7653 const char *printername
= talloc_asprintf(tctx
, "%s2", t
->info2
.printername
);
7654 const char *drivername
= t
->added_driver
? t
->driver
.info8
.driver_name
: t
->info2
.drivername
;
7655 const char *portname
= t
->info2
.portname
;
7657 union spoolss_PrinterInfo info
;
7658 struct policy_handle new_handle
, new_handle2
;
7659 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7661 torture_comment(tctx
, "Testing c_setprinter\n");
7663 torture_assert(tctx
,
7664 test_GetPrinter_level(tctx
, b
, &t
->handle
, 0, &info
),
7665 "failed to get level 0 printer info");
7666 torture_comment(tctx
, "csetprinter on initial printer handle: %d\n",
7667 info
.info0
.c_setprinter
);
7669 /* check if c_setprinter on 1st handle increases after a printer has
7672 torture_assert(tctx
,
7673 test_AddPrinter_normal(tctx
, p
, &new_handle
, printername
, drivername
, portname
, NULL
, false),
7674 "failed to add new printer");
7675 torture_assert(tctx
,
7676 test_GetPrinter_level(tctx
, b
, &t
->handle
, 0, &info
),
7677 "failed to get level 0 printer info");
7678 torture_comment(tctx
, "csetprinter on initial printer handle (after add): %d\n",
7679 info
.info0
.c_setprinter
);
7681 /* check if c_setprinter on new handle increases after a printer has
7684 torture_assert(tctx
,
7685 test_GetPrinter_level(tctx
, b
, &new_handle
, 0, &info
),
7686 "failed to get level 0 printer info");
7687 torture_comment(tctx
, "csetprinter on created handle: %d\n",
7688 info
.info0
.c_setprinter
);
7690 /* open the new printer and check if c_setprinter increases */
7692 torture_assert(tctx
,
7693 call_OpenPrinterEx(tctx
, p
, printername
, NULL
, &new_handle2
),
7694 "failed to open created printer");
7695 torture_assert(tctx
,
7696 test_GetPrinter_level(tctx
, b
, &new_handle2
, 0, &info
),
7697 "failed to get level 0 printer info");
7698 torture_comment(tctx
, "csetprinter on new handle (after openprinter): %d\n",
7699 info
.info0
.c_setprinter
);
7703 torture_assert(tctx
,
7704 test_ClosePrinter(tctx
, b
, &new_handle2
),
7705 "failed to close printer");
7706 torture_assert(tctx
,
7707 test_DeletePrinter(tctx
, b
, &new_handle
),
7708 "failed to delete new printer");
7713 static bool compose_local_driver_directory(struct torture_context
*tctx
,
7714 const char *environment
,
7715 const char *local_dir
,
7720 p
= strrchr(local_dir
, '/');
7726 if (strequal(environment
, "Windows x64")) {
7727 if (!strequal(p
, "x64")) {
7728 *path
= talloc_asprintf(tctx
, "%s/x64", local_dir
);
7730 } else if (strequal(environment
, "Windows NT x86")) {
7731 if (!strequal(p
, "i386")) {
7732 *path
= talloc_asprintf(tctx
, "%s/i386", local_dir
);
7735 torture_assert(tctx
, "unknown environment: '%s'\n", environment
);
7742 static struct spoolss_DeviceMode
*torture_devicemode(TALLOC_CTX
*mem_ctx
,
7743 const char *devicename
)
7745 struct spoolss_DeviceMode
*r
;
7747 r
= talloc_zero(mem_ctx
, struct spoolss_DeviceMode
);
7752 r
->devicename
= talloc_strdup(r
, devicename
);
7753 r
->specversion
= DMSPEC_NT4_AND_ABOVE
;
7754 r
->driverversion
= 0x0600;
7756 r
->__driverextra_length
= 0;
7757 r
->fields
= DEVMODE_FORMNAME
|
7759 DEVMODE_PRINTQUALITY
|
7760 DEVMODE_DEFAULTSOURCE
|
7764 DEVMODE_ORIENTATION
;
7765 r
->orientation
= DMORIENT_PORTRAIT
;
7766 r
->papersize
= DMPAPER_LETTER
;
7771 r
->defaultsource
= DMBIN_FORMSOURCE
;
7772 r
->printquality
= DMRES_HIGH
;
7773 r
->color
= DMRES_MONOCHROME
;
7774 r
->duplex
= DMDUP_SIMPLEX
;
7776 r
->ttoption
= DMTT_SUBDEV
;
7777 r
->collate
= DMCOLLATE_FALSE
;
7778 r
->formname
= talloc_strdup(r
, "Letter");
7784 static bool test_architecture_buffer(struct torture_context
*tctx
,
7787 struct test_spoolss_context
*ctx
=
7788 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
7790 struct spoolss_OpenPrinterEx r
;
7791 struct spoolss_UserLevel1 u1
;
7792 struct policy_handle handle
;
7793 uint32_t architectures
[] = {
7794 PROCESSOR_ARCHITECTURE_INTEL
,
7795 PROCESSOR_ARCHITECTURE_IA64
,
7796 PROCESSOR_ARCHITECTURE_AMD64
7800 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
7801 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7803 for (i
=0; i
< ARRAY_SIZE(architectures
); i
++) {
7805 torture_comment(tctx
, "Testing OpenPrinterEx with architecture %d\n", architectures
[i
]);
7813 u1
.processor
= architectures
[i
];
7815 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
7816 r
.in
.datatype
= NULL
;
7817 r
.in
.devmode_ctr
.devmode
= NULL
;
7818 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
7819 r
.in
.userlevel_ctr
.level
= 1;
7820 r
.in
.userlevel_ctr
.user_info
.level1
= &u1
;
7821 r
.out
.handle
= &handle
;
7823 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_OpenPrinterEx_r(b
, tctx
, &r
), "");
7824 torture_assert_werr_ok(tctx
, r
.out
.result
, "");
7827 struct spoolss_EnumPrinters e
;
7829 union spoolss_PrinterInfo
*info
;
7831 e
.in
.flags
= PRINTER_ENUM_LOCAL
;
7836 e
.out
.count
= &count
;
7838 e
.out
.needed
= &needed
[i
];
7840 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &e
), "");
7842 torture_comment(tctx
, "needed was %d\n", needed
[i
]);
7846 torture_assert(tctx
, test_ClosePrinter(tctx
, b
, &handle
), "");
7849 for (i
=1; i
< ARRAY_SIZE(architectures
); i
++) {
7850 if (needed
[i
-1] != needed
[i
]) {
7852 talloc_asprintf(tctx
, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7853 needed
[i
-1], architectures
[i
-1], needed
[i
], architectures
[i
]));
7860 static bool test_PrintServer_Forms_Winreg(struct torture_context
*tctx
,
7863 struct test_spoolss_context
*ctx
=
7864 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
7865 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
7866 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7868 return test_Forms_winreg(tctx
, b
, &ctx
->server_handle
, true, NULL
);
7871 static bool test_PrintServer_Forms(struct torture_context
*tctx
,
7874 struct test_spoolss_context
*ctx
=
7875 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
7876 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
7877 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7879 return test_Forms(tctx
, b
, &ctx
->server_handle
, true, NULL
, NULL
, NULL
);
7882 static bool test_PrintServer_EnumForms(struct torture_context
*tctx
,
7885 struct test_spoolss_context
*ctx
=
7886 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
7887 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
7888 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7890 return test_EnumForms_all(tctx
, b
, &ctx
->server_handle
, true);
7893 static bool torture_rpc_spoolss_setup_common(struct torture_context
*tctx
, struct test_spoolss_context
*t
)
7897 status
= torture_rpc_connection(tctx
, &t
->spoolss_pipe
, &ndr_table_spoolss
);
7899 torture_assert_ntstatus_ok(tctx
, status
, "Error connecting to server");
7901 torture_assert(tctx
,
7902 test_OpenPrinter_server(tctx
, t
->spoolss_pipe
, &t
->server_handle
),
7903 "failed to open printserver");
7904 torture_assert(tctx
,
7905 test_get_environment(tctx
, t
->spoolss_pipe
->binding_handle
, &t
->server_handle
, &t
->environment
),
7906 "failed to get environment");
7911 static bool torture_rpc_spoolss_setup(struct torture_context
*tctx
, void **data
)
7913 struct test_spoolss_context
*t
;
7915 *data
= t
= talloc_zero(tctx
, struct test_spoolss_context
);
7917 return torture_rpc_spoolss_setup_common(tctx
, t
);
7920 static bool torture_rpc_spoolss_teardown_common(struct torture_context
*tctx
, struct test_spoolss_context
*t
)
7922 test_ClosePrinter(tctx
, t
->spoolss_pipe
->binding_handle
, &t
->server_handle
);
7927 static bool torture_rpc_spoolss_teardown(struct torture_context
*tctx
, void *data
)
7929 struct test_spoolss_context
*t
= talloc_get_type(data
, struct test_spoolss_context
);
7932 ret
= torture_rpc_spoolss_teardown_common(tctx
, t
);
7938 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context
*tctx
, struct torture_printer_context
*t
)
7940 struct dcerpc_pipe
*p
;
7941 struct dcerpc_binding_handle
*b
;
7942 const char *server_name_slash
;
7943 const char *driver_name
;
7944 const char *printer_name
;
7945 const char *port_name
;
7947 torture_assert_ntstatus_ok(tctx
,
7948 torture_rpc_connection(tctx
, &t
->spoolss_pipe
, &ndr_table_spoolss
),
7949 "Error connecting to server");
7951 p
= t
->spoolss_pipe
;
7952 b
= p
->binding_handle
;
7953 server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
7955 t
->driver
.info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
7956 t
->driver
.info8
.driver_name
= TORTURE_DRIVER
;
7957 t
->driver
.info8
.driver_path
= "pscript5.dll";
7958 t
->driver
.info8
.data_file
= "cups6.ppd";
7959 t
->driver
.info8
.config_file
= "ps5ui.dll";
7960 t
->driver
.info8
.help_file
= "pscript.hlp";
7961 t
->driver
.info8
.default_datatype
= "RAW";
7962 t
->driver
.info8
.dependent_files
= talloc_zero(t
, struct spoolss_StringArray
);
7963 t
->driver
.info8
.dependent_files
->string
= talloc_zero_array(t
, const char *, 8 + 1);
7964 t
->driver
.info8
.dependent_files
->string
[0] = "pscript5.dll";
7965 t
->driver
.info8
.dependent_files
->string
[1] = "cups6.ppd";
7966 t
->driver
.info8
.dependent_files
->string
[2] = "ps5ui.dll";
7967 t
->driver
.info8
.dependent_files
->string
[3] = "pscript.hlp";
7968 t
->driver
.info8
.dependent_files
->string
[4] = "pscript.ntf";
7969 t
->driver
.info8
.dependent_files
->string
[5] = "cups6.ini";
7970 t
->driver
.info8
.dependent_files
->string
[6] = "cupsps6.dll";
7971 t
->driver
.info8
.dependent_files
->string
[7] = "cupsui6.dll";
7973 t
->driver
.local
.driver_directory
= "/usr/share/cups/drivers";
7975 t
->info2
.portname
= "LPT1:";
7977 printer_name
= t
->info2
.printername
;
7978 port_name
= t
->info2
.portname
;
7980 torture_assert(tctx
,
7981 fillup_printserver_info(tctx
, p
, &t
->driver
),
7982 "failed to fillup printserver info");
7984 t
->driver
.info8
.architecture
= talloc_strdup(t
, t
->driver
.remote
.environment
);
7986 torture_assert(tctx
,
7987 compose_local_driver_directory(tctx
, t
->driver
.remote
.environment
,
7988 t
->driver
.local
.driver_directory
,
7989 &t
->driver
.local
.driver_directory
),
7990 "failed to compose local driver directory");
7992 t
->info2
.drivername
= "Microsoft XPS Document Writer";
7994 if (test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, t
->driver
.remote
.environment
, 3, t
->info2
.drivername
, NULL
)) {
7995 torture_comment(tctx
, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7996 t
->info2
.drivername
, t
->driver
.remote
.environment
);
7997 t
->have_driver
= true;
8001 torture_comment(tctx
, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
8002 t
->info2
.drivername
, t
->driver
.remote
.environment
);
8004 t
->info2
.drivername
= "Microsoft XPS Document Writer v4";
8006 if (test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, t
->driver
.remote
.environment
, 3, t
->info2
.drivername
, NULL
)) {
8007 torture_comment(tctx
, "driver '%s' (architecture: %s, version: 4) is present on server\n",
8008 t
->info2
.drivername
, t
->driver
.remote
.environment
);
8009 t
->have_driver
= true;
8013 torture_comment(tctx
, "trying to upload own driver\n");
8015 if (!directory_exist(t
->driver
.local
.driver_directory
)) {
8016 torture_warning(tctx
, "no local driver is available!");
8017 t
->have_driver
= false;
8021 torture_assert(tctx
,
8022 upload_printer_driver(tctx
, dcerpc_server_name(p
), &t
->driver
),
8023 "failed to upload printer driver");
8025 torture_assert(tctx
,
8026 test_AddPrinterDriver_args_level_3(tctx
, b
, server_name_slash
, &t
->driver
.info8
, 0, false, NULL
),
8027 "failed to add driver");
8029 t
->added_driver
= true;
8030 t
->have_driver
= true;
8033 driver_name
= t
->added_driver
? t
->driver
.info8
.driver_name
: t
->info2
.drivername
;
8036 torture_assert(tctx
,
8037 test_AddPrinter_wellknown(tctx
, p
, printer_name
, t
->ex
),
8038 "failed to add wellknown printer");
8040 torture_assert(tctx
,
8041 test_AddPrinter_normal(tctx
, p
, &t
->handle
, printer_name
, driver_name
, port_name
, t
->devmode
, t
->ex
),
8042 "failed to add printer");
8048 static bool torture_rpc_spoolss_printer_setup(struct torture_context
*tctx
, void **data
)
8050 struct torture_printer_context
*t
;
8052 *data
= t
= talloc_zero(tctx
, struct torture_printer_context
);
8055 t
->wellknown
= false;
8056 t
->info2
.printername
= TORTURE_PRINTER
;
8059 return torture_rpc_spoolss_printer_setup_common(tctx
, t
);
8062 static bool torture_rpc_spoolss_printerex_setup(struct torture_context
*tctx
, void **data
)
8064 struct torture_printer_context
*t
;
8066 *data
= t
= talloc_zero(tctx
, struct torture_printer_context
);
8069 t
->wellknown
= false;
8070 t
->info2
.printername
= TORTURE_PRINTER_EX
;
8073 return torture_rpc_spoolss_printer_setup_common(tctx
, t
);
8076 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context
*tctx
, void **data
)
8078 struct torture_printer_context
*t
;
8080 *data
= t
= talloc_zero(tctx
, struct torture_printer_context
);
8083 t
->wellknown
= true;
8084 t
->info2
.printername
= TORTURE_WELLKNOWN_PRINTER
;
8089 torture_skip(tctx
, "skipping AddPrinter level 1");
8092 return torture_rpc_spoolss_printer_setup_common(tctx
, t
);
8095 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context
*tctx
, void **data
)
8097 struct torture_printer_context
*t
;
8099 *data
= t
= talloc_zero(tctx
, struct torture_printer_context
);
8102 t
->wellknown
= true;
8103 t
->info2
.printername
= TORTURE_WELLKNOWN_PRINTER_EX
;
8108 torture_skip(tctx
, "skipping AddPrinterEx level 1");
8111 return torture_rpc_spoolss_printer_setup_common(tctx
, t
);
8115 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context
*tctx
, void **data
)
8117 struct torture_printer_context
*t
;
8119 *data
= t
= talloc_zero(tctx
, struct torture_printer_context
);
8122 t
->wellknown
= false;
8123 t
->info2
.printername
= TORTURE_PRINTER_EX
;
8124 t
->devmode
= torture_devicemode(t
, TORTURE_PRINTER_EX
);
8126 return torture_rpc_spoolss_printer_setup_common(tctx
, t
);
8130 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context
*tctx
, struct torture_printer_context
*t
)
8133 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8134 struct dcerpc_binding_handle
*b
;
8135 const char *printer_name
= t
->info2
.printername
;
8137 if (t
->added_driver
) {
8138 torture_assert(tctx
,
8139 remove_printer_driver(tctx
, dcerpc_server_name(t
->spoolss_pipe
), &t
->driver
),
8140 "failed to remove printer driver");
8143 if (p
&& !t
->wellknown
) {
8144 b
= p
->binding_handle
;
8146 torture_assert(tctx
,
8147 test_DeletePrinter(tctx
, b
, &t
->handle
),
8148 "failed to delete printer");
8150 torture_assert(tctx
,
8151 test_EnumPrinters_findname(tctx
, b
, PRINTER_ENUM_LOCAL
, 1,
8152 printer_name
, &found
),
8153 "failed to enumerate printers");
8155 torture_assert(tctx
, !found
, "deleted printer still there");
8161 static bool torture_rpc_spoolss_printer_teardown(struct torture_context
*tctx
, void *data
)
8163 struct torture_printer_context
*t
= talloc_get_type(data
, struct torture_printer_context
);
8166 ret
= torture_rpc_spoolss_printer_teardown_common(tctx
, t
);
8172 static bool test_print_test(struct torture_context
*tctx
,
8175 struct torture_printer_context
*t
=
8176 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8177 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8178 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8180 torture_assert(tctx
,
8181 test_PausePrinter(tctx
, b
, &t
->handle
),
8182 "failed to pause printer");
8184 torture_assert(tctx
,
8185 test_DoPrintTest(tctx
, b
, &t
->handle
),
8186 "failed to do print test");
8188 torture_assert(tctx
,
8189 test_ResumePrinter(tctx
, b
, &t
->handle
),
8190 "failed to resume printer");
8195 static bool test_print_test_extended(struct torture_context
*tctx
,
8198 struct torture_printer_context
*t
=
8199 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8200 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8201 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8204 torture_assert(tctx
,
8205 test_PausePrinter(tctx
, b
, &t
->handle
),
8206 "failed to pause printer");
8208 ret
= test_DoPrintTest_extended(tctx
, b
, &t
->handle
);
8210 torture_comment(tctx
, "WARNING! failed to do extended print test\n");
8211 if (torture_setting_bool(tctx
, "samba3", false)) {
8212 torture_comment(tctx
, "non-critical for samba3\n");
8214 tctx
->last_result
= TORTURE_SKIP
;
8218 torture_assert(tctx
,
8219 test_ResumePrinter(tctx
, b
, &t
->handle
),
8220 "failed to resume printer");
8225 static bool test_print_test_properties(struct torture_context
*tctx
,
8228 struct torture_printer_context
*t
=
8229 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8230 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8231 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8233 if (torture_setting_bool(tctx
, "samba3", false)) {
8234 torture_skip(tctx
, "skip printer job property tests against samba");
8237 torture_assert(tctx
,
8238 test_PausePrinter(tctx
, b
, &t
->handle
),
8239 "failed to pause printer");
8241 torture_assert(tctx
,
8242 test_DoPrintTest_properties(tctx
, b
, &t
->handle
),
8243 "failed to test print job properties");
8245 torture_assert(tctx
,
8246 test_ResumePrinter(tctx
, b
, &t
->handle
),
8247 "failed to resume printer");
8252 /* use smbd file IO to spool a print job */
8253 static bool test_print_test_smbd(struct torture_context
*tctx
,
8256 struct torture_printer_context
*t
=
8257 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8258 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8259 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8262 union spoolss_JobInfo
*info
= NULL
;
8265 struct smb2_tree
*tree
;
8266 struct smb2_handle job_h
;
8267 struct cli_credentials
*credentials
= cmdline_credentials
;
8268 struct smbcli_options options
;
8269 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
8271 * Do not test against the dynamically added printers, printing via
8272 * smbd means that a different spoolss process may handle the
8273 * OpenPrinter request to the one that handled the AddPrinter request.
8274 * This currently leads to an ugly race condition where one process
8275 * sees the new printer and one doesn't.
8277 const char *share
= TORTURE_PRINTER_STATIC1
;
8279 torture_comment(tctx
, "Testing smbd job spooling\n");
8280 lpcfg_smbcli_options(tctx
->lp_ctx
, &options
);
8282 status
= smb2_connect(mem_ctx
,
8283 torture_setting_string(tctx
, "host", NULL
),
8284 lpcfg_smb_ports(tctx
->lp_ctx
),
8286 lpcfg_resolve_context(tctx
->lp_ctx
),
8291 lpcfg_socket_options(tctx
->lp_ctx
),
8292 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
));
8293 if (!NT_STATUS_IS_OK(status
)) {
8294 printf("Failed to connect to SMB2 printer %s - %s\n",
8295 share
, nt_errstr(status
));
8299 status
= torture_smb2_testfile(tree
, "smbd_spooler_job", &job_h
);
8300 torture_assert_ntstatus_ok(tctx
, status
, "smbd spool job create");
8302 status
= smb2_util_write(tree
, job_h
, "exciting print job data", 0,
8303 sizeof("exciting print job data"));
8304 torture_assert_ntstatus_ok(tctx
, status
, "smbd spool job write");
8306 /* check back end spoolss job was created */
8307 torture_assert(tctx
,
8308 test_EnumJobs_args(tctx
, b
, &t
->handle
, 1, &count
, &info
),
8309 "EnumJobs level 1 failed");
8311 for (i
= 0; i
< count
; i
++) {
8312 if (!strcmp(info
[i
].info1
.document_name
, "smbd_spooler_job")) {
8316 torture_assert(tctx
, (i
!= count
), "smbd_spooler_job not found");
8318 status
= smb2_util_close(tree
, job_h
);
8319 torture_assert_ntstatus_ok(tctx
, status
, "smbd spool job close");
8321 /* disconnect from printer share */
8322 talloc_free(mem_ctx
);
8327 static bool test_print_test_purge(struct torture_context
*tctx
,
8330 struct torture_printer_context
*t
=
8331 (struct torture_printer_context
*)talloc_get_type_abort(private_data
,
8332 struct torture_printer_context
);
8333 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8334 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8335 uint32_t num_jobs
= 8;
8340 union spoolss_JobInfo
*info
;
8342 torture_assert(tctx
,
8343 test_PausePrinter(tctx
, b
, &t
->handle
),
8344 "failed to pause printer");
8346 job_ids
= talloc_zero_array(tctx
, uint32_t, num_jobs
);
8347 for (i
=0; i
< num_jobs
; i
++) {
8348 ret
= test_DoPrintTest_add_one_job(tctx
, b
, &t
->handle
,
8351 torture_assert(tctx
, ret
, "failed to add print job");
8354 torture_assert(tctx
,
8355 test_EnumJobs_args(tctx
, b
, &t
->handle
, 1, &count
, &info
),
8356 "EnumJobs level 1 failed");
8358 torture_assert_int_equal(tctx
, count
, num_jobs
,
8359 "unexpected number of jobs in queue");
8361 torture_assert(tctx
,
8362 test_printer_purge(tctx
, b
, &t
->handle
),
8363 "failed to purge printer");
8365 torture_assert(tctx
,
8366 test_EnumJobs_args(tctx
, b
, &t
->handle
, 1, &count
, &info
),
8367 "EnumJobs level 1 failed");
8369 torture_assert_int_equal(tctx
, count
, 0,
8370 "unexpected number of jobs in queue");
8372 torture_assert(tctx
,
8373 test_ResumePrinter(tctx
, b
, &t
->handle
),
8374 "failed to resume printer");
8379 static bool test_printer_sd(struct torture_context
*tctx
,
8382 struct torture_printer_context
*t
=
8383 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8384 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8385 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8387 torture_assert(tctx
,
8388 test_PrinterInfo_SD(tctx
, b
, &t
->handle
),
8389 "failed to test security descriptors");
8394 static bool test_printer_dm(struct torture_context
*tctx
,
8397 struct torture_printer_context
*t
=
8398 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8399 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8401 torture_assert(tctx
,
8402 test_PrinterInfo_DevMode(tctx
, p
, &t
->handle
, t
->info2
.printername
, t
->devmode
),
8403 "failed to test devicemodes");
8408 static bool test_printer_info_winreg(struct torture_context
*tctx
,
8411 struct torture_printer_context
*t
=
8412 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8413 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8415 torture_assert(tctx
,
8416 test_PrinterInfo_winreg(tctx
, p
, &t
->handle
, t
->info2
.printername
),
8417 "failed to test printer info winreg");
8422 static bool test_printer_change_id(struct torture_context
*tctx
,
8425 struct torture_printer_context
*t
=
8426 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8427 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8429 torture_assert(tctx
,
8430 test_ChangeID(tctx
, p
, &t
->handle
),
8431 "failed to test change id");
8436 static bool test_printer_keys(struct torture_context
*tctx
,
8439 struct torture_printer_context
*t
=
8440 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8441 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8442 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8444 torture_assert(tctx
,
8445 test_printer_all_keys(tctx
, b
, &t
->handle
),
8446 "failed to test printer keys");
8451 static bool test_printer_data_consistency(struct torture_context
*tctx
,
8454 struct torture_printer_context
*t
=
8455 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8456 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8458 torture_assert(tctx
,
8459 test_EnumPrinterData_consistency(tctx
, p
, &t
->handle
),
8460 "failed to test printer data consistency");
8465 static bool test_printer_data_keys(struct torture_context
*tctx
,
8468 struct torture_printer_context
*t
=
8469 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8470 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8472 torture_assert(tctx
,
8473 test_SetPrinterDataEx_keys(tctx
, p
, &t
->handle
),
8474 "failed to test printer data keys");
8479 static bool test_printer_data_values(struct torture_context
*tctx
,
8482 struct torture_printer_context
*t
=
8483 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8484 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8486 torture_assert(tctx
,
8487 test_SetPrinterDataEx_values(tctx
, p
, &t
->handle
),
8488 "failed to test printer data values");
8493 static bool test_printer_data_set(struct torture_context
*tctx
,
8496 struct torture_printer_context
*t
=
8497 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8498 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8500 torture_assert(tctx
,
8501 test_SetPrinterDataEx_matrix(tctx
, p
, &t
->handle
, t
->info2
.printername
, NULL
, NULL
),
8502 "failed to test printer data set");
8507 static bool test_printer_data_winreg(struct torture_context
*tctx
,
8510 struct torture_printer_context
*t
=
8511 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8512 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8514 torture_assert(tctx
,
8515 test_PrinterData_winreg(tctx
, p
, &t
->handle
, t
->info2
.printername
),
8516 "failed to test printer data winreg");
8521 static bool test_printer_data_dsspooler(struct torture_context
*tctx
,
8524 struct torture_printer_context
*t
=
8525 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8526 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8528 torture_assert(tctx
,
8529 test_PrinterData_DsSpooler(tctx
, p
, &t
->handle
, t
->info2
.printername
),
8530 "failed to test printer data winreg dsspooler");
8535 static bool test_printer_ic(struct torture_context
*tctx
,
8538 struct torture_printer_context
*t
=
8539 talloc_get_type_abort(private_data
,
8540 struct torture_printer_context
);
8541 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8542 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8543 struct policy_handle gdi_handle
;
8545 if (torture_setting_bool(tctx
, "samba3", false)) {
8546 torture_skip(tctx
, "skip printer information context tests against samba");
8550 struct spoolss_CreatePrinterIC r
;
8551 struct spoolss_DevmodeContainer devmode_ctr
;
8553 ZERO_STRUCT(devmode_ctr
);
8555 r
.in
.handle
= &t
->handle
;
8556 r
.in
.devmode_ctr
= &devmode_ctr
;
8557 r
.out
.gdi_handle
= &gdi_handle
;
8559 torture_assert_ntstatus_ok(tctx
,
8560 dcerpc_spoolss_CreatePrinterIC_r(b
, tctx
, &r
),
8561 "CreatePrinterIC failed");
8562 torture_assert_werr_ok(tctx
, r
.out
.result
,
8563 "CreatePrinterIC failed");
8567 struct spoolss_PlayGDIScriptOnPrinterIC r
;
8570 uint32_t num_fonts
= 0;
8572 in
= data_blob_string_const("");
8574 r
.in
.gdi_handle
= &gdi_handle
;
8576 r
.in
.cIn
= in
.length
;
8579 for (i
= 0; i
< 4; i
++) {
8581 out
= data_blob_talloc_zero(tctx
, i
);
8583 r
.in
.cOut
= out
.length
;
8584 r
.out
.pOut
= out
.data
;
8586 torture_assert_ntstatus_ok(tctx
,
8587 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b
, tctx
, &r
),
8588 "PlayGDIScriptOnPrinterIC failed");
8589 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_NOMEM
,
8590 "PlayGDIScriptOnPrinterIC failed");
8593 out
= data_blob_talloc_zero(tctx
, 4);
8595 r
.in
.cOut
= out
.length
;
8596 r
.out
.pOut
= out
.data
;
8598 torture_assert_ntstatus_ok(tctx
,
8599 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b
, tctx
, &r
),
8600 "PlayGDIScriptOnPrinterIC failed");
8601 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_OK
,
8602 "PlayGDIScriptOnPrinterIC failed");
8604 /* now we should have the required length, so retry with a
8605 * buffer which is large enough to carry all font ids */
8607 num_fonts
= IVAL(r
.out
.pOut
, 0);
8609 torture_comment(tctx
, "PlayGDIScriptOnPrinterIC gave font count of %d\n", num_fonts
);
8611 out
= data_blob_talloc_zero(tctx
,
8612 num_fonts
* sizeof(struct UNIVERSAL_FONT_ID
) + 4);
8614 r
.in
.cOut
= out
.length
;
8615 r
.out
.pOut
= out
.data
;
8617 torture_assert_ntstatus_ok(tctx
,
8618 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b
, tctx
, &r
),
8619 "PlayGDIScriptOnPrinterIC failed");
8620 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_OK
,
8621 "PlayGDIScriptOnPrinterIC failed");
8626 struct spoolss_DeletePrinterIC r
;
8628 r
.in
.gdi_handle
= &gdi_handle
;
8629 r
.out
.gdi_handle
= &gdi_handle
;
8631 torture_assert_ntstatus_ok(tctx
,
8632 dcerpc_spoolss_DeletePrinterIC_r(b
, tctx
, &r
),
8633 "DeletePrinterIC failed");
8634 torture_assert_werr_ok(tctx
, r
.out
.result
,
8635 "DeletePrinterIC failed");
8642 static bool test_printer_bidi(struct torture_context
*tctx
,
8645 struct torture_printer_context
*t
=
8646 talloc_get_type_abort(private_data
,
8647 struct torture_printer_context
);
8648 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8649 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8650 struct spoolss_RpcSendRecvBidiData r
;
8651 struct RPC_BIDI_REQUEST_CONTAINER bidi_req
;
8652 struct RPC_BIDI_RESPONSE_CONTAINER
*bidi_rep
= NULL
;
8654 if (torture_setting_bool(tctx
, "samba3", false)) {
8655 torture_skip(tctx
, "skip printer bidirectional tests against samba");
8658 ZERO_STRUCT(bidi_req
);
8660 r
.in
.hPrinter
= t
->handle
;
8661 r
.in
.pAction
= "foobar";
8662 r
.in
.pReqData
= &bidi_req
;
8663 r
.out
.ppRespData
= &bidi_rep
;
8665 torture_assert_ntstatus_ok(tctx
,
8666 dcerpc_spoolss_RpcSendRecvBidiData_r(b
, tctx
, &r
),
8667 "RpcSendRecvBidiData failed");
8668 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_NOT_SUPPORTED
,
8669 "RpcSendRecvBidiData failed");
8671 if (!(t
->info2
.attributes
& PRINTER_ATTRIBUTE_ENABLE_BIDI
)) {
8672 torture_skip(tctx
, "skipping further tests as printer is not BIDI enabled");
8675 r
.in
.pAction
= BIDI_ACTION_ENUM_SCHEMA
;
8677 torture_assert_ntstatus_ok(tctx
,
8678 dcerpc_spoolss_RpcSendRecvBidiData_r(b
, tctx
, &r
),
8679 "RpcSendRecvBidiData failed");
8680 torture_assert_werr_ok(tctx
, r
.out
.result
,
8681 "RpcSendRecvBidiData failed");
8686 static bool test_printer_set_publish(struct torture_context
*tctx
,
8687 struct dcerpc_binding_handle
*b
,
8688 struct policy_handle
*handle
)
8690 union spoolss_PrinterInfo info
;
8691 struct spoolss_SetPrinterInfo7 info7
;
8692 struct spoolss_SetPrinterInfoCtr info_ctr
;
8693 struct spoolss_DevmodeContainer devmode_ctr
;
8694 struct sec_desc_buf secdesc_ctr
;
8697 info7
.action
= DSPRINT_PUBLISH
;
8699 ZERO_STRUCT(info_ctr
);
8700 ZERO_STRUCT(devmode_ctr
);
8701 ZERO_STRUCT(secdesc_ctr
);
8703 info_ctr
.info
.info7
= &info7
;
8705 torture_assert(tctx
,
8706 test_SetPrinter(tctx
, b
, handle
, &info_ctr
,
8707 &devmode_ctr
, &secdesc_ctr
, 0), "");
8709 torture_assert(tctx
,
8710 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
8712 torture_assert(tctx
,
8713 (info
.info2
.attributes
& PRINTER_ATTRIBUTE_PUBLISHED
),
8714 "info2 publish flag not set");
8715 torture_assert(tctx
,
8716 test_GetPrinter_level(tctx
, b
, handle
, 7, &info
),
8718 if (info
.info7
.action
& DSPRINT_PENDING
) {
8719 torture_comment(tctx
, "publish is pending\n");
8720 torture_assert_int_equal(tctx
,
8722 (DSPRINT_PENDING
| DSPRINT_PUBLISH
),
8723 "info7 publish flag not set");
8726 torture_assert_int_equal(tctx
,
8729 "info7 publish flag not set");
8730 torture_assert_ntstatus_ok(tctx
,
8731 GUID_from_string(info
.info7
.guid
,
8733 "invalid published printer GUID");
8739 static bool test_printer_set_unpublish(struct torture_context
*tctx
,
8740 struct dcerpc_binding_handle
*b
,
8741 struct policy_handle
*handle
)
8743 union spoolss_PrinterInfo info
;
8744 struct spoolss_SetPrinterInfo7 info7
;
8745 struct spoolss_SetPrinterInfoCtr info_ctr
;
8746 struct spoolss_DevmodeContainer devmode_ctr
;
8747 struct sec_desc_buf secdesc_ctr
;
8749 info7
.action
= DSPRINT_UNPUBLISH
;
8752 ZERO_STRUCT(info_ctr
);
8753 ZERO_STRUCT(devmode_ctr
);
8754 ZERO_STRUCT(secdesc_ctr
);
8756 info_ctr
.info
.info7
= &info7
;
8758 torture_assert(tctx
,
8759 test_SetPrinter(tctx
, b
, handle
, &info_ctr
,
8760 &devmode_ctr
, &secdesc_ctr
, 0), "");
8762 torture_assert(tctx
,
8763 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
8765 torture_assert(tctx
,
8766 !(info
.info2
.attributes
& PRINTER_ATTRIBUTE_PUBLISHED
),
8767 "info2 publish flag still set");
8768 torture_assert(tctx
,
8769 test_GetPrinter_level(tctx
, b
, handle
, 7, &info
),
8772 if (info
.info7
.action
& DSPRINT_PENDING
) {
8774 torture_comment(tctx
, "unpublish is pending\n");
8775 torture_assert_int_equal(tctx
,
8777 (DSPRINT_PENDING
| DSPRINT_UNPUBLISH
),
8778 "info7 unpublish flag not set");
8779 torture_assert_ntstatus_ok(tctx
,
8780 GUID_from_string(info
.info7
.guid
,
8782 "invalid printer GUID");
8784 torture_assert_int_equal(tctx
,
8785 info
.info7
.action
, DSPRINT_UNPUBLISH
,
8786 "info7 unpublish flag not set");
8792 static bool test_printer_publish_toggle(struct torture_context
*tctx
,
8795 struct torture_printer_context
*t
=
8796 talloc_get_type_abort(private_data
,
8797 struct torture_printer_context
);
8798 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8799 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8800 struct policy_handle
*handle
= &t
->handle
;
8801 union spoolss_PrinterInfo info7
;
8802 union spoolss_PrinterInfo info2
;
8804 /* check publish status via level 7 and level 2 */
8805 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 7, &info7
),
8807 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info2
),
8810 if (info2
.info2
.attributes
& PRINTER_ATTRIBUTE_PUBLISHED
) {
8811 torture_assert_int_equal(tctx
,
8812 info7
.info7
.action
, DSPRINT_PUBLISH
,
8813 "info7 publish flag not set");
8814 torture_assert(tctx
, test_printer_set_unpublish(tctx
, b
, handle
), "");
8815 torture_assert(tctx
, test_printer_set_publish(tctx
, b
, handle
), "");
8817 torture_assert_int_equal(tctx
,
8818 info7
.info7
.action
, DSPRINT_UNPUBLISH
,
8819 "info7 unpublish flag not set");
8820 torture_assert(tctx
, test_printer_set_publish(tctx
, b
, handle
), "");
8821 torture_assert(tctx
, test_printer_set_unpublish(tctx
, b
, handle
), "");
8827 static bool test_driver_info_winreg(struct torture_context
*tctx
,
8830 struct torture_printer_context
*t
=
8831 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8832 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8833 const char *driver_name
= t
->added_driver
? t
->driver
.info8
.driver_name
: t
->info2
.drivername
;
8835 if (!t
->have_driver
) {
8836 torture_skip(tctx
, "skipping driver info winreg test as we don't have a driver");
8839 torture_assert(tctx
,
8840 test_DriverInfo_winreg(tctx
, p
, &t
->handle
, t
->info2
.printername
, driver_name
, t
->driver
.remote
.environment
, 3),
8841 "failed to test driver info winreg");
8846 void torture_tcase_printer(struct torture_tcase
*tcase
)
8848 torture_tcase_add_simple_test(tcase
, "openprinter", test_openprinter_wrap
);
8849 torture_tcase_add_simple_test(tcase
, "csetprinter", test_csetprinter
);
8850 torture_tcase_add_simple_test(tcase
, "print_test", test_print_test
);
8851 torture_tcase_add_simple_test(tcase
, "print_test_extended", test_print_test_extended
);
8852 torture_tcase_add_simple_test(tcase
, "print_test_smbd", test_print_test_smbd
);
8853 torture_tcase_add_simple_test(tcase
, "print_test_properties", test_print_test_properties
);
8854 torture_tcase_add_simple_test(tcase
, "print_test_purge", test_print_test_purge
);
8855 torture_tcase_add_simple_test(tcase
, "printer_info", test_printer_info
);
8856 torture_tcase_add_simple_test(tcase
, "sd", test_printer_sd
);
8857 torture_tcase_add_simple_test(tcase
, "dm", test_printer_dm
);
8858 torture_tcase_add_simple_test(tcase
, "printer_info_winreg", test_printer_info_winreg
);
8859 torture_tcase_add_simple_test(tcase
, "change_id", test_printer_change_id
);
8860 torture_tcase_add_simple_test(tcase
, "keys", test_printer_keys
);
8861 torture_tcase_add_simple_test(tcase
, "printerdata_consistency", test_printer_data_consistency
);
8862 torture_tcase_add_simple_test(tcase
, "printerdata_keys", test_printer_data_keys
);
8863 torture_tcase_add_simple_test(tcase
, "printerdata_values", test_printer_data_values
);
8864 torture_tcase_add_simple_test(tcase
, "printerdata_set", test_printer_data_set
);
8865 torture_tcase_add_simple_test(tcase
, "printerdata_winreg", test_printer_data_winreg
);
8866 torture_tcase_add_simple_test(tcase
, "printerdata_dsspooler", test_printer_data_dsspooler
);
8867 torture_tcase_add_simple_test(tcase
, "driver_info_winreg", test_driver_info_winreg
);
8868 torture_tcase_add_simple_test(tcase
, "printer_rename", test_printer_rename
);
8869 torture_tcase_add_simple_test(tcase
, "printer_ic", test_printer_ic
);
8870 torture_tcase_add_simple_test(tcase
, "bidi", test_printer_bidi
);
8871 torture_tcase_add_simple_test(tcase
, "publish_toggle",
8872 test_printer_publish_toggle
);
8875 struct torture_suite
*torture_rpc_spoolss_printer(TALLOC_CTX
*mem_ctx
)
8877 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "printer");
8878 struct torture_tcase
*tcase
;
8880 tcase
= torture_suite_add_tcase(suite
, "addprinter");
8882 torture_tcase_set_fixture(tcase
,
8883 torture_rpc_spoolss_printer_setup
,
8884 torture_rpc_spoolss_printer_teardown
);
8886 torture_tcase_printer(tcase
);
8888 tcase
= torture_suite_add_tcase(suite
, "addprinterex");
8890 torture_tcase_set_fixture(tcase
,
8891 torture_rpc_spoolss_printerex_setup
,
8892 torture_rpc_spoolss_printer_teardown
);
8894 torture_tcase_printer(tcase
);
8896 tcase
= torture_suite_add_tcase(suite
, "addprinterwkn");
8898 torture_tcase_set_fixture(tcase
,
8899 torture_rpc_spoolss_printerwkn_setup
,
8900 torture_rpc_spoolss_printer_teardown
);
8902 tcase
= torture_suite_add_tcase(suite
, "addprinterexwkn");
8904 torture_tcase_set_fixture(tcase
,
8905 torture_rpc_spoolss_printerexwkn_setup
,
8906 torture_rpc_spoolss_printer_teardown
);
8909 /* test is not correct */
8910 tcase
= torture_suite_add_tcase(suite
, "addprinterdm");
8912 torture_tcase_set_fixture(tcase
,
8913 torture_rpc_spoolss_printerdm_setup
,
8914 torture_rpc_spoolss_printer_teardown
);
8916 torture_tcase_printer(tcase
);
8921 struct torture_suite
*torture_rpc_spoolss(TALLOC_CTX
*mem_ctx
)
8923 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "spoolss");
8924 struct torture_tcase
*tcase
= torture_suite_add_tcase(suite
, "printserver");
8926 torture_tcase_set_fixture(tcase
,
8927 torture_rpc_spoolss_setup
,
8928 torture_rpc_spoolss_teardown
);
8930 torture_tcase_add_simple_test(tcase
, "openprinter_badnamelist", test_OpenPrinter_badname_list
);
8931 torture_tcase_add_simple_test(tcase
, "printer_data_list", test_GetPrinterData_list
);
8932 torture_tcase_add_simple_test(tcase
, "enum_forms", test_PrintServer_EnumForms
);
8933 torture_tcase_add_simple_test(tcase
, "forms", test_PrintServer_Forms
);
8934 torture_tcase_add_simple_test(tcase
, "forms_winreg", test_PrintServer_Forms_Winreg
);
8935 torture_tcase_add_simple_test(tcase
, "enum_ports", test_EnumPorts
);
8936 torture_tcase_add_simple_test(tcase
, "add_port", test_AddPort
);
8937 torture_tcase_add_simple_test(tcase
, "get_printer_driver_directory", test_GetPrinterDriverDirectory
);
8938 torture_tcase_add_simple_test(tcase
, "get_print_processor_directory", test_GetPrintProcessorDirectory
);
8939 torture_tcase_add_simple_test(tcase
, "enum_printer_drivers", test_EnumPrinterDrivers
);
8940 torture_tcase_add_simple_test(tcase
, "enum_monitors", test_EnumMonitors
);
8941 torture_tcase_add_simple_test(tcase
, "enum_print_processors", test_EnumPrintProcessors
);
8942 torture_tcase_add_simple_test(tcase
, "print_processors_winreg", test_print_processors_winreg
);
8943 torture_tcase_add_simple_test(tcase
, "add_processor", test_add_print_processor
);
8944 torture_tcase_add_simple_test(tcase
, "enum_printprocdata", test_EnumPrintProcDataTypes
);
8945 torture_tcase_add_simple_test(tcase
, "enum_printers", test_EnumPrinters
);
8946 torture_tcase_add_simple_test(tcase
, "enum_ports_old", test_EnumPorts_old
);
8947 torture_tcase_add_simple_test(tcase
, "enum_printers_old", test_EnumPrinters_old
);
8948 torture_tcase_add_simple_test(tcase
, "enum_printers_servername", test_EnumPrinters_servername
);
8949 torture_tcase_add_simple_test(tcase
, "enum_printer_drivers_old", test_EnumPrinterDrivers_old
);
8950 torture_tcase_add_simple_test(tcase
, "architecture_buffer", test_architecture_buffer
);
8952 torture_suite_add_suite(suite
, torture_rpc_spoolss_printer(suite
));
8957 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context
*tctx
,
8958 struct dcerpc_binding_handle
*b
,
8960 const char *environment
,
8963 struct spoolss_GetPrinterDriverDirectory r
;
8966 r
.in
.server
= server
;
8967 r
.in
.environment
= environment
;
8971 r
.out
.needed
= &needed
;
8973 torture_assert_ntstatus_ok(tctx
,
8974 dcerpc_spoolss_GetPrinterDriverDirectory_r(b
, tctx
, &r
),
8975 "failed to query driver directory");
8977 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
8978 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
8979 r
.in
.buffer
= &blob
;
8980 r
.in
.offered
= needed
;
8982 torture_assert_ntstatus_ok(tctx
,
8983 dcerpc_spoolss_GetPrinterDriverDirectory_r(b
, tctx
, &r
),
8984 "failed to query driver directory");
8987 torture_assert_werr_ok(tctx
, r
.out
.result
,
8988 "failed to query driver directory");
8991 *dir_p
= r
.out
.info
->info1
.directory_name
;
8997 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr
*info_ctr
)
8999 if (info_ctr
== NULL
) {
9003 switch (info_ctr
->level
) {
9005 return info_ctr
->info
.info1
->driver_name
;
9007 return info_ctr
->info
.info2
->driver_name
;
9009 return info_ctr
->info
.info3
->driver_name
;
9011 return info_ctr
->info
.info4
->driver_name
;
9013 return info_ctr
->info
.info6
->driver_name
;
9015 return info_ctr
->info
.info8
->driver_name
;
9021 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr
*info_ctr
)
9023 if (info_ctr
== NULL
) {
9027 switch (info_ctr
->level
) {
9029 return info_ctr
->info
.info2
->architecture
;
9031 return info_ctr
->info
.info3
->architecture
;
9033 return info_ctr
->info
.info4
->architecture
;
9035 return info_ctr
->info
.info6
->architecture
;
9037 return info_ctr
->info
.info8
->architecture
;
9044 static bool test_AddPrinterDriver_exp(struct torture_context
*tctx
,
9045 struct dcerpc_binding_handle
*b
,
9046 const char *servername
,
9047 struct spoolss_AddDriverInfoCtr
*info_ctr
,
9048 WERROR expected_result
)
9050 struct spoolss_AddPrinterDriver r
;
9051 const char *drivername
= get_driver_from_info(info_ctr
);
9052 const char *environment
= get_environment_from_info(info_ctr
);
9054 r
.in
.servername
= servername
;
9055 r
.in
.info_ctr
= info_ctr
;
9057 torture_comment(tctx
, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
9058 drivername
, info_ctr
->level
, environment
);
9060 torture_assert_ntstatus_ok(tctx
,
9061 dcerpc_spoolss_AddPrinterDriver_r(b
, tctx
, &r
),
9062 "spoolss_AddPrinterDriver failed");
9063 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
9064 "spoolss_AddPrinterDriver failed with unexpected result");
9070 static bool test_AddPrinterDriverEx_exp(struct torture_context
*tctx
,
9071 struct dcerpc_binding_handle
*b
,
9072 const char *servername
,
9073 struct spoolss_AddDriverInfoCtr
*info_ctr
,
9075 WERROR expected_result
)
9077 struct spoolss_AddPrinterDriverEx r
;
9078 const char *drivername
= get_driver_from_info(info_ctr
);
9079 const char *environment
= get_environment_from_info(info_ctr
);
9081 r
.in
.servername
= servername
;
9082 r
.in
.info_ctr
= info_ctr
;
9085 torture_comment(tctx
, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
9086 drivername
, info_ctr
->level
, environment
);
9088 torture_assert_ntstatus_ok(tctx
,
9089 dcerpc_spoolss_AddPrinterDriverEx_r(b
, tctx
, &r
),
9090 "AddPrinterDriverEx failed");
9091 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
9092 "AddPrinterDriverEx failed with unexpected result");
9097 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
9098 if (path && strlen(path)) {\
9099 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
9102 static bool test_AddPrinterDriver_args_level_1(struct torture_context
*tctx
,
9103 struct dcerpc_binding_handle
*b
,
9104 const char *server_name
,
9105 struct spoolss_AddDriverInfo8
*r
,
9108 const char *remote_driver_dir
)
9110 struct spoolss_AddDriverInfoCtr info_ctr
;
9111 struct spoolss_AddDriverInfo1 info1
;
9116 info_ctr
.info
.info1
= &info1
;
9119 torture_assert(tctx
,
9120 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_UNKNOWN_LEVEL
),
9121 "failed to test AddPrinterDriverEx level 1");
9123 torture_assert(tctx
,
9124 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_UNKNOWN_LEVEL
),
9125 "failed to test AddPrinterDriver level 1");
9128 info1
.driver_name
= r
->driver_name
;
9131 torture_assert(tctx
,
9132 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_UNKNOWN_LEVEL
),
9133 "failed to test AddPrinterDriverEx level 1");
9135 torture_assert(tctx
,
9136 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_UNKNOWN_LEVEL
),
9137 "failed to test AddPrinterDriver level 1");
9143 static bool test_AddPrinterDriver_args_level_2(struct torture_context
*tctx
,
9144 struct dcerpc_binding_handle
*b
,
9145 const char *server_name
,
9146 struct spoolss_AddDriverInfo8
*r
,
9149 const char *remote_driver_dir
)
9151 struct spoolss_AddDriverInfoCtr info_ctr
;
9152 struct spoolss_AddDriverInfo2 info2
;
9153 union spoolss_DriverInfo info
;
9158 info_ctr
.info
.info2
= &info2
;
9161 torture_assert(tctx
,
9162 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAM
),
9163 "failed to test AddPrinterDriverEx level 2");
9165 torture_assert(tctx
,
9166 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAM
),
9167 "failed to test AddPrinterDriver level 2");
9170 info2
.driver_name
= r
->driver_name
;
9173 torture_assert(tctx
,
9174 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAM
),
9175 "failed to test AddPrinterDriverEx level 2");
9177 torture_assert(tctx
,
9178 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAM
),
9179 "failed to test AddPrinterDriver level 2");
9182 info2
.version
= r
->version
;
9185 torture_assert(tctx
,
9186 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAM
),
9187 "failed to test AddPrinterDriverEx level 2");
9189 torture_assert(tctx
,
9190 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAM
),
9191 "failed to test AddPrinterDriver level 2");
9194 info2
.architecture
= r
->architecture
;
9197 torture_assert(tctx
,
9198 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAM
),
9199 "failed to test AddPrinterDriverEx level 2");
9201 torture_assert(tctx
,
9202 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAM
),
9203 "failed to test AddPrinterDriver level 2");
9206 info2
.driver_path
= r
->driver_path
;
9209 torture_assert(tctx
,
9210 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAM
),
9211 "failed to test AddPrinterDriverEx level 2");
9213 torture_assert(tctx
,
9214 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAM
),
9215 "failed to test AddPrinterDriver level 2");
9218 info2
.data_file
= r
->data_file
;
9221 torture_assert(tctx
,
9222 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAM
),
9223 "failed to test AddPrinterDriverEx level 2");
9225 torture_assert(tctx
,
9226 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAM
),
9227 "failed to test AddPrinterDriver level 2");
9230 info2
.config_file
= r
->config_file
;
9233 torture_assert(tctx
,
9234 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, 0, WERR_INVALID_PARAM
),
9235 "failed to test AddPrinterDriverEx");
9239 torture_assert(tctx
,
9240 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_OK
),
9241 "failed to test AddPrinterDriverEx level 2");
9243 torture_assert(tctx
,
9244 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_OK
),
9245 "failed to test AddPrinterDriver level 2");
9248 torture_assert(tctx
,
9249 test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, r
->architecture
, 2, r
->driver_name
, &info
),
9250 "failed to find added printer driver");
9252 if (remote_driver_dir
) {
9253 ASSERT_DRIVER_PATH(tctx
, info
.info2
.driver_path
, remote_driver_dir
, "unexpected path");
9254 ASSERT_DRIVER_PATH(tctx
, info
.info2
.data_file
, remote_driver_dir
, "unexpected path");
9255 ASSERT_DRIVER_PATH(tctx
, info
.info2
.config_file
, remote_driver_dir
, "unexpected path");
9261 static bool test_AddPrinterDriver_args_level_3(struct torture_context
*tctx
,
9262 struct dcerpc_binding_handle
*b
,
9263 const char *server_name
,
9264 struct spoolss_AddDriverInfo8
*r
,
9267 const char *remote_driver_dir
)
9269 struct spoolss_AddDriverInfoCtr info_ctr
;
9270 struct spoolss_AddDriverInfo3 info3
;
9271 union spoolss_DriverInfo info
;
9273 info3
.driver_name
= r
->driver_name
;
9274 info3
.version
= r
->version
;
9275 info3
.architecture
= r
->architecture
;
9276 info3
.driver_path
= r
->driver_path
;
9277 info3
.data_file
= r
->data_file
;
9278 info3
.config_file
= r
->config_file
;
9279 info3
.help_file
= r
->help_file
;
9280 info3
.monitor_name
= r
->monitor_name
;
9281 info3
.default_datatype
= r
->default_datatype
;
9282 info3
._ndr_size_dependent_files
= r
->_ndr_size_dependent_files
;
9283 info3
.dependent_files
= r
->dependent_files
;
9286 info_ctr
.info
.info3
= &info3
;
9289 torture_assert(tctx
,
9290 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_OK
),
9291 "failed to test AddPrinterDriverEx level 3");
9293 torture_assert(tctx
,
9294 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_OK
),
9295 "failed to test AddPrinterDriver level 3");
9298 torture_assert(tctx
,
9299 test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, r
->architecture
, 3, r
->driver_name
, &info
),
9300 "failed to find added printer driver");
9302 if (remote_driver_dir
) {
9304 ASSERT_DRIVER_PATH(tctx
, info
.info3
.driver_path
, remote_driver_dir
, "unexpected path");
9305 ASSERT_DRIVER_PATH(tctx
, info
.info3
.data_file
, remote_driver_dir
, "unexpected path");
9306 ASSERT_DRIVER_PATH(tctx
, info
.info3
.config_file
, remote_driver_dir
, "unexpected path");
9307 ASSERT_DRIVER_PATH(tctx
, info
.info3
.help_file
, remote_driver_dir
, "unexpected path");
9308 for (i
=0; info
.info3
.dependent_files
&& info
.info3
.dependent_files
[i
] != NULL
; i
++) {
9309 ASSERT_DRIVER_PATH(tctx
, info
.info3
.dependent_files
[i
], remote_driver_dir
, "unexpected path");
9316 static bool test_AddPrinterDriver_args_level_4(struct torture_context
*tctx
,
9317 struct dcerpc_binding_handle
*b
,
9318 const char *server_name
,
9319 struct spoolss_AddDriverInfo8
*r
,
9322 const char *remote_driver_dir
)
9324 struct spoolss_AddDriverInfoCtr info_ctr
;
9325 struct spoolss_AddDriverInfo4 info4
;
9326 union spoolss_DriverInfo info
;
9328 info4
.version
= r
->version
;
9329 info4
.driver_name
= r
->driver_name
;
9330 info4
.architecture
= r
->architecture
;
9331 info4
.driver_path
= r
->driver_path
;
9332 info4
.data_file
= r
->data_file
;
9333 info4
.config_file
= r
->config_file
;
9334 info4
.help_file
= r
->help_file
;
9335 info4
.monitor_name
= r
->monitor_name
;
9336 info4
.default_datatype
= r
->default_datatype
;
9337 info4
._ndr_size_dependent_files
= r
->_ndr_size_dependent_files
;
9338 info4
.dependent_files
= r
->dependent_files
;
9339 info4
._ndr_size_previous_names
= r
->_ndr_size_previous_names
;
9340 info4
.previous_names
= r
->previous_names
;
9343 info_ctr
.info
.info4
= &info4
;
9346 torture_assert(tctx
,
9347 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_OK
),
9348 "failed to test AddPrinterDriverEx level 4");
9350 torture_assert(tctx
,
9351 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_OK
),
9352 "failed to test AddPrinterDriver level 4");
9355 torture_assert(tctx
,
9356 test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, r
->architecture
, 4, r
->driver_name
, &info
),
9357 "failed to find added printer driver");
9359 if (remote_driver_dir
) {
9361 ASSERT_DRIVER_PATH(tctx
, info
.info4
.driver_path
, remote_driver_dir
, "unexpected path");
9362 ASSERT_DRIVER_PATH(tctx
, info
.info4
.data_file
, remote_driver_dir
, "unexpected path");
9363 ASSERT_DRIVER_PATH(tctx
, info
.info4
.config_file
, remote_driver_dir
, "unexpected path");
9364 ASSERT_DRIVER_PATH(tctx
, info
.info4
.help_file
, remote_driver_dir
, "unexpected path");
9365 for (i
=0; info
.info4
.dependent_files
&& info
.info4
.dependent_files
[i
] != NULL
; i
++) {
9366 ASSERT_DRIVER_PATH(tctx
, info
.info4
.dependent_files
[i
], remote_driver_dir
, "unexpected path");
9373 static bool test_AddPrinterDriver_args_level_6(struct torture_context
*tctx
,
9374 struct dcerpc_binding_handle
*b
,
9375 const char *server_name
,
9376 struct spoolss_AddDriverInfo8
*r
,
9379 const char *remote_driver_dir
)
9381 struct spoolss_AddDriverInfoCtr info_ctr
;
9382 struct spoolss_AddDriverInfo6 info6
;
9383 union spoolss_DriverInfo info
;
9385 info6
.version
= r
->version
;
9386 info6
.driver_name
= r
->driver_name
;
9387 info6
.architecture
= r
->architecture
;
9388 info6
.driver_path
= r
->driver_path
;
9389 info6
.data_file
= r
->data_file
;
9390 info6
.config_file
= r
->config_file
;
9391 info6
.help_file
= r
->help_file
;
9392 info6
.monitor_name
= r
->monitor_name
;
9393 info6
.default_datatype
= r
->default_datatype
;
9394 info6
._ndr_size_dependent_files
= r
->_ndr_size_dependent_files
;
9395 info6
.dependent_files
= r
->dependent_files
;
9396 info6
._ndr_size_previous_names
= r
->_ndr_size_previous_names
;
9397 info6
.previous_names
= r
->previous_names
;
9398 info6
.driver_date
= r
->driver_date
;
9399 info6
.driver_version
= r
->driver_version
;
9400 info6
.manufacturer_name
= r
->manufacturer_name
;
9401 info6
.manufacturer_url
= r
->manufacturer_url
;
9402 info6
.hardware_id
= r
->hardware_id
;
9403 info6
.provider
= r
->provider
;
9406 info_ctr
.info
.info6
= &info6
;
9409 torture_assert(tctx
,
9410 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_OK
),
9411 "failed to test AddPrinterDriverEx level 6");
9413 torture_assert(tctx
,
9414 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_UNKNOWN_LEVEL
),
9415 "failed to test AddPrinterDriver level 6");
9418 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9424 torture_assert(tctx
,
9425 test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, r
->architecture
, 6, r
->driver_name
, &info
),
9426 "failed to find added printer driver");
9428 if (remote_driver_dir
) {
9430 ASSERT_DRIVER_PATH(tctx
, info
.info6
.driver_path
, remote_driver_dir
, "unexpected path");
9431 ASSERT_DRIVER_PATH(tctx
, info
.info6
.data_file
, remote_driver_dir
, "unexpected path");
9432 ASSERT_DRIVER_PATH(tctx
, info
.info6
.config_file
, remote_driver_dir
, "unexpected path");
9433 ASSERT_DRIVER_PATH(tctx
, info
.info6
.help_file
, remote_driver_dir
, "unexpected path");
9434 for (i
=0; info
.info6
.dependent_files
&& info
.info6
.dependent_files
[i
] != NULL
; i
++) {
9435 ASSERT_DRIVER_PATH(tctx
, info
.info6
.dependent_files
[i
], remote_driver_dir
, "unexpected path");
9439 torture_assert_nttime_equal(tctx
, info
.info6
.driver_date
, info6
.driver_date
, "driverdate mismatch");
9440 torture_assert_u64_equal(tctx
, info
.info6
.driver_version
, info6
.driver_version
, "driverversion mismatch");
9445 static bool test_AddPrinterDriver_args_level_8(struct torture_context
*tctx
,
9446 struct dcerpc_binding_handle
*b
,
9447 const char *server_name
,
9448 struct spoolss_AddDriverInfo8
*r
,
9451 const char *remote_driver_dir
)
9453 struct spoolss_AddDriverInfoCtr info_ctr
;
9454 union spoolss_DriverInfo info
;
9457 info_ctr
.info
.info8
= r
;
9460 torture_assert(tctx
,
9461 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_OK
),
9462 "failed to test AddPrinterDriverEx level 8");
9464 torture_assert(tctx
,
9465 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_UNKNOWN_LEVEL
),
9466 "failed to test AddPrinterDriver level 8");
9469 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9475 torture_assert(tctx
,
9476 test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, r
->architecture
, 8, r
->driver_name
, &info
),
9477 "failed to find added printer driver");
9479 if (remote_driver_dir
) {
9481 ASSERT_DRIVER_PATH(tctx
, info
.info8
.driver_path
, remote_driver_dir
, "unexpected path");
9482 ASSERT_DRIVER_PATH(tctx
, info
.info8
.data_file
, remote_driver_dir
, "unexpected path");
9483 ASSERT_DRIVER_PATH(tctx
, info
.info8
.config_file
, remote_driver_dir
, "unexpected path");
9484 ASSERT_DRIVER_PATH(tctx
, info
.info8
.help_file
, remote_driver_dir
, "unexpected path");
9485 for (i
=0; info
.info8
.dependent_files
&& info
.info8
.dependent_files
[i
] != NULL
; i
++) {
9486 ASSERT_DRIVER_PATH(tctx
, info
.info8
.dependent_files
[i
], remote_driver_dir
, "unexpected path");
9490 torture_assert_nttime_equal(tctx
, info
.info8
.driver_date
, r
->driver_date
, "driverdate mismatch");
9491 torture_assert_u64_equal(tctx
, info
.info8
.driver_version
, r
->driver_version
, "driverversion mismatch");
9496 #undef ASSERT_DRIVER_PATH
9498 static bool test_DeletePrinterDriver_exp(struct torture_context
*tctx
,
9499 struct dcerpc_binding_handle
*b
,
9502 const char *environment
,
9503 WERROR expected_result
)
9505 struct spoolss_DeletePrinterDriver r
;
9507 r
.in
.server
= server
;
9508 r
.in
.architecture
= environment
;
9509 r
.in
.driver
= driver
;
9511 torture_comment(tctx
, "Testing DeletePrinterDriver(%s)\n", driver
);
9513 torture_assert_ntstatus_ok(tctx
,
9514 dcerpc_spoolss_DeletePrinterDriver_r(b
, tctx
, &r
),
9515 "DeletePrinterDriver failed");
9516 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
9517 "DeletePrinterDriver failed with unexpected result");
9522 static bool test_DeletePrinterDriverEx_exp(struct torture_context
*tctx
,
9523 struct dcerpc_binding_handle
*b
,
9526 const char *environment
,
9527 uint32_t delete_flags
,
9529 WERROR expected_result
)
9531 struct spoolss_DeletePrinterDriverEx r
;
9533 r
.in
.server
= server
;
9534 r
.in
.architecture
= environment
;
9535 r
.in
.driver
= driver
;
9536 r
.in
.delete_flags
= delete_flags
;
9537 r
.in
.version
= version
;
9539 torture_comment(tctx
, "Testing DeletePrinterDriverEx(%s)\n", driver
);
9541 torture_assert_ntstatus_ok(tctx
,
9542 dcerpc_spoolss_DeletePrinterDriverEx_r(b
, tctx
, &r
),
9543 "DeletePrinterDriverEx failed");
9544 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
9545 "DeletePrinterDriverEx failed with unexpected result");
9550 static bool test_DeletePrinterDriver(struct torture_context
*tctx
,
9551 struct dcerpc_binding_handle
*b
,
9552 const char *server_name
,
9554 const char *environment
)
9556 torture_assert(tctx
,
9557 test_DeletePrinterDriver_exp(tctx
, b
, server_name
, driver
, "FOOBAR", WERR_INVALID_ENVIRONMENT
),
9558 "failed to delete driver");
9560 torture_assert(tctx
,
9561 test_DeletePrinterDriver_exp(tctx
, b
, server_name
, driver
, environment
, WERR_OK
),
9562 "failed to delete driver");
9564 if (test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, environment
, 1, driver
, NULL
)) {
9565 torture_fail(tctx
, "deleted driver still enumerated");
9568 torture_assert(tctx
,
9569 test_DeletePrinterDriver_exp(tctx
, b
, server_name
, driver
, environment
, WERR_UNKNOWN_PRINTER_DRIVER
),
9570 "2nd delete failed");
9575 static bool test_DeletePrinterDriverEx(struct torture_context
*tctx
,
9576 struct dcerpc_binding_handle
*b
,
9577 const char *server_name
,
9579 const char *environment
,
9580 uint32_t delete_flags
,
9583 torture_assert(tctx
,
9584 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name
, driver
, "FOOBAR", delete_flags
, version
, WERR_INVALID_ENVIRONMENT
),
9585 "failed to delete driver");
9587 torture_assert(tctx
,
9588 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name
, driver
, environment
, delete_flags
, version
, WERR_OK
),
9589 "failed to delete driver");
9591 if (test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, environment
, 1, driver
, NULL
)) {
9592 torture_fail(tctx
, "deleted driver still enumerated");
9595 torture_assert(tctx
,
9596 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name
, driver
, environment
, delete_flags
, version
, WERR_UNKNOWN_PRINTER_DRIVER
),
9597 "2nd delete failed");
9602 static bool test_PrinterDriver_args(struct torture_context
*tctx
,
9603 struct dcerpc_binding_handle
*b
,
9604 const char *server_name
,
9606 struct spoolss_AddDriverInfo8
*r
,
9608 uint32_t delete_flags
,
9609 uint32_t delete_version
,
9611 const char *remote_driver_dir
)
9617 ret
= test_AddPrinterDriver_args_level_1(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
9620 ret
= test_AddPrinterDriver_args_level_2(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
9623 ret
= test_AddPrinterDriver_args_level_3(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
9626 ret
= test_AddPrinterDriver_args_level_4(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
9629 ret
= test_AddPrinterDriver_args_level_6(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
9632 ret
= test_AddPrinterDriver_args_level_8(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
9646 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9648 if (!ex
&& (level
== 6 || level
== 8)) {
9653 struct dcerpc_pipe
*p2
;
9654 struct policy_handle hive_handle
;
9655 struct dcerpc_binding_handle
*b2
;
9657 torture_assert_ntstatus_ok(tctx
,
9658 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
9659 "could not open winreg pipe");
9660 b2
= p2
->binding_handle
;
9662 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
9664 ret
= test_GetDriverInfo_winreg(tctx
, b
, NULL
, NULL
, r
->driver_name
, r
->architecture
, r
->version
, b2
, &hive_handle
, server_name
);
9666 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
9672 return test_DeletePrinterDriverEx(tctx
, b
, server_name
, r
->driver_name
, r
->architecture
, delete_flags
, r
->version
);
9674 return test_DeletePrinterDriver(tctx
, b
, server_name
, r
->driver_name
, r
->architecture
);
9678 static bool fillup_printserver_info(struct torture_context
*tctx
,
9679 struct dcerpc_pipe
*p
,
9680 struct torture_driver_context
*d
)
9682 struct policy_handle server_handle
;
9683 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
9684 const char *server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
9686 torture_assert(tctx
,
9687 test_OpenPrinter_server(tctx
, p
, &server_handle
),
9688 "failed to open printserver");
9689 torture_assert(tctx
,
9690 test_get_environment(tctx
, b
, &server_handle
, &d
->remote
.environment
),
9691 "failed to get environment");
9692 torture_assert(tctx
,
9693 test_ClosePrinter(tctx
, b
, &server_handle
),
9694 "failed to close printserver");
9696 torture_assert(tctx
,
9697 test_GetPrinterDriverDirectory_getdir(tctx
, b
, server_name_slash
,
9698 d
->local
.environment
? d
->local
.environment
: d
->remote
.environment
,
9699 &d
->remote
.driver_directory
),
9700 "failed to get driver directory");
9705 static const char *driver_directory_dir(const char *driver_directory
)
9709 p
= strrchr(driver_directory
, '\\');
9717 static const char *driver_directory_share(struct torture_context
*tctx
,
9718 const char *driver_directory
)
9723 if (driver_directory
[0] == '\\' && driver_directory
[1] == '\\') {
9724 driver_directory
+= 2;
9727 p
= talloc_strdup(tctx
, driver_directory
);
9729 torture_assert(tctx
,
9730 next_token_talloc(tctx
, &p
, &tok
, "\\"),
9731 "cannot explode uri");
9732 torture_assert(tctx
,
9733 next_token_talloc(tctx
, &p
, &tok
, "\\"),
9734 "cannot explode uri");
9739 static bool upload_printer_driver_file(struct torture_context
*tctx
,
9740 struct smbcli_state
*cli
,
9741 struct torture_driver_context
*d
,
9742 const char *file_name
)
9747 int maxwrite
= 64512;
9750 const char *remote_dir
= driver_directory_dir(d
->remote
.driver_directory
);
9751 const char *local_name
= talloc_asprintf(tctx
, "%s/%s", d
->local
.driver_directory
, file_name
);
9752 const char *remote_name
= talloc_asprintf(tctx
, "%s\\%s", remote_dir
, file_name
);
9754 if (!file_name
|| strlen(file_name
) == 0) {
9758 torture_comment(tctx
, "Uploading %s to %s\n", local_name
, remote_name
);
9760 fnum
= smbcli_open(cli
->tree
, remote_name
, O_RDWR
|O_CREAT
|O_TRUNC
, DENY_NONE
);
9762 torture_fail(tctx
, talloc_asprintf(tctx
, "failed to open remote file: %s\n", remote_name
));
9765 f
= x_fopen(local_name
, O_RDONLY
, 0);
9767 torture_fail(tctx
, talloc_asprintf(tctx
, "failed to open local file: %s\n", local_name
));
9770 buf
= talloc_array(tctx
, uint8_t, maxwrite
);
9776 while (!x_feof(f
)) {
9780 if ((n
= x_fread(buf
, 1, n
, f
)) < 1) {
9781 if((n
== 0) && x_feof(f
))
9782 break; /* Empty local file. */
9784 torture_warning(tctx
,
9785 "failed to read file: %s\n", strerror(errno
));
9789 ret
= smbcli_write(cli
->tree
, fnum
, 0, buf
, nread
+ start
, n
);
9792 torture_warning(tctx
,
9793 "failed to write file: %s\n", smbcli_errstr(cli
->tree
));
9802 torture_assert_ntstatus_ok(tctx
,
9803 smbcli_close(cli
->tree
, fnum
),
9804 "failed to close file");
9809 static bool connect_printer_driver_share(struct torture_context
*tctx
,
9810 const char *server_name
,
9811 const char *share_name
,
9812 struct smbcli_state
**cli
)
9814 struct smbcli_options smb_options
;
9815 struct smbcli_session_options smb_session_options
;
9817 torture_comment(tctx
, "Connecting printer driver share '%s' on '%s'\n",
9818 share_name
, server_name
);
9820 lpcfg_smbcli_options(tctx
->lp_ctx
, &smb_options
);
9821 lpcfg_smbcli_session_options(tctx
->lp_ctx
, &smb_session_options
);
9823 torture_assert_ntstatus_ok(tctx
,
9824 smbcli_full_connection(tctx
, cli
, server_name
,
9825 lpcfg_smb_ports(tctx
->lp_ctx
),
9827 lpcfg_socket_options(tctx
->lp_ctx
),
9828 cmdline_credentials
,
9829 lpcfg_resolve_context(tctx
->lp_ctx
),
9832 &smb_session_options
,
9833 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
)),
9834 "failed to open driver share");
9839 static bool upload_printer_driver(struct torture_context
*tctx
,
9840 const char *server_name
,
9841 struct torture_driver_context
*d
)
9843 struct smbcli_state
*cli
;
9844 const char *share_name
= driver_directory_share(tctx
, d
->remote
.driver_directory
);
9847 torture_assert(tctx
,
9848 connect_printer_driver_share(tctx
, server_name
, share_name
, &cli
),
9849 "failed to connect to driver share");
9851 torture_comment(tctx
, "Uploading printer driver files to \\\\%s\\%s\n",
9852 server_name
, share_name
);
9854 torture_assert(tctx
,
9855 upload_printer_driver_file(tctx
, cli
, d
, d
->info8
.driver_path
),
9856 "failed to upload driver_path");
9857 torture_assert(tctx
,
9858 upload_printer_driver_file(tctx
, cli
, d
, d
->info8
.data_file
),
9859 "failed to upload data_file");
9860 torture_assert(tctx
,
9861 upload_printer_driver_file(tctx
, cli
, d
, d
->info8
.config_file
),
9862 "failed to upload config_file");
9863 torture_assert(tctx
,
9864 upload_printer_driver_file(tctx
, cli
, d
, d
->info8
.help_file
),
9865 "failed to upload help_file");
9866 if (d
->info8
.dependent_files
) {
9867 for (i
=0; d
->info8
.dependent_files
->string
&& d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
9868 torture_assert(tctx
,
9869 upload_printer_driver_file(tctx
, cli
, d
, d
->info8
.dependent_files
->string
[i
]),
9870 "failed to upload dependent_files");
9879 static bool check_printer_driver_file(struct torture_context
*tctx
,
9880 struct smbcli_state
*cli
,
9881 struct torture_driver_context
*d
,
9882 const char *file_name
)
9884 const char *remote_arch_dir
= driver_directory_dir(d
->remote
.driver_directory
);
9885 const char *remote_name
= talloc_asprintf(tctx
, "%s\\%d\\%s",
9891 torture_assert(tctx
, (file_name
&& strlen(file_name
) != 0), "invalid filename");
9893 torture_comment(tctx
, "checking for driver file at %s\n", remote_name
);
9895 fnum
= smbcli_open(cli
->tree
, remote_name
, O_RDONLY
, DENY_NONE
);
9900 torture_assert_ntstatus_ok(tctx
,
9901 smbcli_close(cli
->tree
, fnum
),
9902 "failed to close driver file");
9907 static bool check_printer_driver_files(struct torture_context
*tctx
,
9908 const char *server_name
,
9909 struct torture_driver_context
*d
,
9912 struct smbcli_state
*cli
;
9913 const char *share_name
= driver_directory_share(tctx
, d
->remote
.driver_directory
);
9916 torture_assert(tctx
,
9917 connect_printer_driver_share(tctx
, server_name
, share_name
, &cli
),
9918 "failed to connect to driver share");
9920 torture_comment(tctx
, "checking %sexistent driver files at \\\\%s\\%s\n",
9921 (expect_exist
? "": "non-"),
9922 server_name
, share_name
);
9924 if (d
->info8
.driver_path
&& d
->info8
.driver_path
[0]) {
9925 torture_assert(tctx
,
9926 check_printer_driver_file(tctx
, cli
, d
, d
->info8
.driver_path
) == expect_exist
,
9927 "failed driver_path check");
9929 if (d
->info8
.data_file
&& d
->info8
.data_file
[0]) {
9930 torture_assert(tctx
,
9931 check_printer_driver_file(tctx
, cli
, d
, d
->info8
.data_file
) == expect_exist
,
9932 "failed data_file check");
9934 if (d
->info8
.config_file
&& d
->info8
.config_file
[0]) {
9935 torture_assert(tctx
,
9936 check_printer_driver_file(tctx
, cli
, d
, d
->info8
.config_file
) == expect_exist
,
9937 "failed config_file check");
9939 if (d
->info8
.help_file
&& d
->info8
.help_file
[0]) {
9940 torture_assert(tctx
,
9941 check_printer_driver_file(tctx
, cli
, d
, d
->info8
.help_file
) == expect_exist
,
9942 "failed help_file check");
9944 if (d
->info8
.dependent_files
) {
9945 for (i
=0; d
->info8
.dependent_files
->string
&& d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
9946 torture_assert(tctx
,
9947 check_printer_driver_file(tctx
, cli
, d
, d
->info8
.dependent_files
->string
[i
]) == expect_exist
,
9948 "failed dependent_files check");
9957 static bool remove_printer_driver_file(struct torture_context
*tctx
,
9958 struct smbcli_state
*cli
,
9959 struct torture_driver_context
*d
,
9960 const char *file_name
)
9962 const char *remote_name
;
9963 const char *remote_dir
= driver_directory_dir(d
->remote
.driver_directory
);
9965 if (!file_name
|| strlen(file_name
) == 0) {
9969 remote_name
= talloc_asprintf(tctx
, "%s\\%s", remote_dir
, file_name
);
9971 torture_comment(tctx
, "Removing %s\n", remote_name
);
9973 torture_assert_ntstatus_ok(tctx
,
9974 smbcli_unlink(cli
->tree
, remote_name
),
9975 "failed to unlink");
9980 static bool remove_printer_driver(struct torture_context
*tctx
,
9981 const char *server_name
,
9982 struct torture_driver_context
*d
)
9984 struct smbcli_state
*cli
;
9985 const char *share_name
= driver_directory_share(tctx
, d
->remote
.driver_directory
);
9988 torture_assert(tctx
,
9989 connect_printer_driver_share(tctx
, server_name
, share_name
, &cli
),
9990 "failed to connect to driver share");
9992 torture_comment(tctx
, "Removing printer driver files from \\\\%s\\%s\n",
9993 server_name
, share_name
);
9995 torture_assert(tctx
,
9996 remove_printer_driver_file(tctx
, cli
, d
, d
->info8
.driver_path
),
9997 "failed to remove driver_path");
9998 torture_assert(tctx
,
9999 remove_printer_driver_file(tctx
, cli
, d
, d
->info8
.data_file
),
10000 "failed to remove data_file");
10001 if (!strequal(d
->info8
.config_file
, d
->info8
.driver_path
)) {
10002 torture_assert(tctx
,
10003 remove_printer_driver_file(tctx
, cli
, d
, d
->info8
.config_file
),
10004 "failed to remove config_file");
10006 torture_assert(tctx
,
10007 remove_printer_driver_file(tctx
, cli
, d
, d
->info8
.help_file
),
10008 "failed to remove help_file");
10009 if (d
->info8
.dependent_files
) {
10010 for (i
=0; d
->info8
.dependent_files
->string
&& d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
10011 if (strequal(d
->info8
.dependent_files
->string
[i
], d
->info8
.driver_path
) ||
10012 strequal(d
->info8
.dependent_files
->string
[i
], d
->info8
.data_file
) ||
10013 strequal(d
->info8
.dependent_files
->string
[i
], d
->info8
.config_file
) ||
10014 strequal(d
->info8
.dependent_files
->string
[i
], d
->info8
.help_file
)) {
10017 torture_assert(tctx
,
10018 remove_printer_driver_file(tctx
, cli
, d
, d
->info8
.dependent_files
->string
[i
]),
10019 "failed to remove dependent_files");
10029 static bool test_add_driver_arg(struct torture_context
*tctx
,
10030 struct dcerpc_pipe
*p
,
10031 struct torture_driver_context
*d
)
10034 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
10035 const char *server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
10036 uint32_t levels
[] = { 1, 2, 3, 4, 6, 8 };
10038 struct spoolss_AddDriverInfo8 info8
;
10039 uint32_t add_flags
= APD_COPY_NEW_FILES
;
10040 uint32_t delete_flags
= 0;
10042 ZERO_STRUCT(info8
);
10044 torture_comment(tctx
, "Testing PrinterDriver%s '%s' for environment '%s'\n",
10045 d
->ex
? "Ex" : "", d
->info8
.driver_name
, d
->local
.environment
);
10047 torture_assert(tctx
,
10048 fillup_printserver_info(tctx
, p
, d
),
10049 "failed to fillup printserver info");
10051 if (!directory_exist(d
->local
.driver_directory
)) {
10052 torture_skip(tctx
, "Skipping Printer Driver test as no local driver is available");
10055 torture_assert(tctx
,
10056 upload_printer_driver(tctx
, dcerpc_server_name(p
), d
),
10057 "failed to upload printer driver");
10060 if (d
->info8
.dependent_files
) {
10061 info8
.dependent_files
= talloc_zero(tctx
, struct spoolss_StringArray
);
10062 if (d
->info8
.dependent_files
->string
) {
10063 for (i
=0; d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
10065 info8
.dependent_files
->string
= talloc_zero_array(info8
.dependent_files
, const char *, i
+1);
10066 for (i
=0; d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
10067 info8
.dependent_files
->string
[i
] = talloc_strdup(info8
.dependent_files
->string
, d
->info8
.dependent_files
->string
[i
]);
10071 info8
.architecture
= d
->local
.environment
;
10073 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
10075 if (torture_setting_bool(tctx
, "samba3", false)) {
10076 switch (levels
[i
]) {
10080 torture_comment(tctx
, "skipping level %d against samba\n", levels
[i
]);
10086 if (torture_setting_bool(tctx
, "w2k3", false)) {
10087 switch (levels
[i
]) {
10089 torture_comment(tctx
, "skipping level %d against w2k3\n", levels
[i
]);
10096 torture_comment(tctx
,
10097 "Testing PrinterDriver%s '%s' add & delete level %d\n",
10098 d
->ex
? "Ex" : "", info8
.driver_name
, levels
[i
]);
10100 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
);
10103 info8
.driver_path
= talloc_asprintf(tctx
, "%s\\%s", d
->remote
.driver_directory
, d
->info8
.driver_path
);
10104 info8
.data_file
= talloc_asprintf(tctx
, "%s\\%s", d
->remote
.driver_directory
, d
->info8
.data_file
);
10105 if (d
->info8
.config_file
) {
10106 info8
.config_file
= talloc_asprintf(tctx
, "%s\\%s", d
->remote
.driver_directory
, d
->info8
.config_file
);
10108 if (d
->info8
.help_file
) {
10109 info8
.help_file
= talloc_asprintf(tctx
, "%s\\%s", d
->remote
.driver_directory
, d
->info8
.help_file
);
10111 if (d
->info8
.dependent_files
&& d
->info8
.dependent_files
->string
) {
10112 for (i
=0; d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
10113 info8
.dependent_files
->string
[i
] = talloc_asprintf(tctx
, "%s\\%s", d
->remote
.driver_directory
, d
->info8
.dependent_files
->string
[i
]);
10117 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
10119 if (torture_setting_bool(tctx
, "samba3", false)) {
10120 switch (levels
[i
]) {
10124 torture_comment(tctx
, "skipping level %d against samba\n", levels
[i
]);
10130 if (torture_setting_bool(tctx
, "w2k3", false)) {
10131 switch (levels
[i
]) {
10133 torture_comment(tctx
, "skipping level %d against w2k3\n", levels
[i
]);
10140 torture_comment(tctx
,
10141 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
10142 d
->ex
? "Ex" : "", info8
.driver_name
, levels
[i
]);
10144 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
);
10147 torture_assert(tctx
,
10148 remove_printer_driver(tctx
, dcerpc_server_name(p
), d
),
10149 "failed to remove printer driver");
10151 torture_comment(tctx
, "\n");
10156 static bool test_add_driver_ex_64(struct torture_context
*tctx
,
10157 struct dcerpc_pipe
*p
)
10159 struct torture_driver_context
*d
;
10161 d
= talloc_zero(tctx
, struct torture_driver_context
);
10163 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
10164 d
->info8
.driver_name
= TORTURE_DRIVER_EX
;
10165 d
->info8
.architecture
= NULL
;
10166 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
10167 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
10168 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
10169 d
->local
.environment
= talloc_strdup(d
, "Windows x64");
10170 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/x64");
10173 return test_add_driver_arg(tctx
, p
, d
);
10176 static bool test_add_driver_ex_32(struct torture_context
*tctx
,
10177 struct dcerpc_pipe
*p
)
10179 struct torture_driver_context
*d
;
10181 d
= talloc_zero(tctx
, struct torture_driver_context
);
10183 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
10184 d
->info8
.driver_name
= TORTURE_DRIVER_EX
;
10185 d
->info8
.architecture
= NULL
;
10186 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
10187 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
10188 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
10189 d
->local
.environment
= talloc_strdup(d
, "Windows NT x86");
10190 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/i386");
10193 return test_add_driver_arg(tctx
, p
, d
);
10196 static bool test_add_driver_64(struct torture_context
*tctx
,
10197 struct dcerpc_pipe
*p
)
10199 struct torture_driver_context
*d
;
10201 d
= talloc_zero(tctx
, struct torture_driver_context
);
10203 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
10204 d
->info8
.driver_name
= TORTURE_DRIVER
;
10205 d
->info8
.architecture
= NULL
;
10206 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
10207 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
10208 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
10209 d
->local
.environment
= talloc_strdup(d
, "Windows x64");
10210 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/x64");
10213 return test_add_driver_arg(tctx
, p
, d
);
10216 static bool test_add_driver_32(struct torture_context
*tctx
,
10217 struct dcerpc_pipe
*p
)
10219 struct torture_driver_context
*d
;
10221 d
= talloc_zero(tctx
, struct torture_driver_context
);
10223 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
10224 d
->info8
.driver_name
= TORTURE_DRIVER
;
10225 d
->info8
.architecture
= NULL
;
10226 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
10227 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
10228 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
10229 d
->local
.environment
= talloc_strdup(d
, "Windows NT x86");
10230 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/i386");
10233 return test_add_driver_arg(tctx
, p
, d
);
10236 static bool test_add_driver_adobe(struct torture_context
*tctx
,
10237 struct dcerpc_pipe
*p
)
10239 struct torture_driver_context
*d
;
10241 if (!torture_setting_bool(tctx
, "samba3", false)) {
10242 torture_skip(tctx
, "skipping adobe test which only works against samba3");
10245 d
= talloc_zero(tctx
, struct torture_driver_context
);
10247 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_9X
;
10248 d
->info8
.driver_name
= TORTURE_DRIVER_ADOBE
;
10249 d
->info8
.architecture
= NULL
;
10250 d
->info8
.driver_path
= talloc_strdup(d
, "ADOBEPS4.DRV");
10251 d
->info8
.data_file
= talloc_strdup(d
, "DEFPRTR2.PPD");
10252 d
->info8
.config_file
= talloc_strdup(d
, "ADOBEPS4.DRV");
10254 d
->info8
.help_file
= talloc_strdup(d
, "ADOBEPS4.HLP");
10255 d
->info8
.monitor_name
= talloc_strdup(d
, "PSMON.DLL");
10257 d
->local
.environment
= talloc_strdup(d
, "Windows 4.0");
10258 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/adobe/");
10261 return test_add_driver_arg(tctx
, p
, d
);
10264 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context
*tctx
,
10265 struct dcerpc_pipe
*p
)
10267 struct torture_driver_context
*d
;
10268 struct spoolss_StringArray
*a
;
10270 if (!torture_setting_bool(tctx
, "samba3", false)) {
10271 torture_skip(tctx
, "skipping cupsaddsmb test which only works against samba3");
10274 d
= talloc_zero(tctx
, struct torture_driver_context
);
10276 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_9X
;
10277 d
->info8
.driver_name
= TORTURE_DRIVER_ADOBE_CUPSADDSMB
;
10278 d
->info8
.architecture
= NULL
;
10279 d
->info8
.driver_path
= talloc_strdup(d
, "ADOBEPS4.DRV");
10280 d
->info8
.data_file
= talloc_strdup(d
, "DEFPRTR2.PPD");
10281 d
->info8
.config_file
= NULL
;
10282 d
->info8
.help_file
= talloc_strdup(d
, "ADOBEPS4.HLP");
10283 d
->info8
.monitor_name
= talloc_strdup(d
, "PSMON.DLL");
10284 d
->info8
.default_datatype
= talloc_strdup(d
, "RAW");
10286 a
= talloc_zero(d
, struct spoolss_StringArray
);
10287 a
->string
= talloc_zero_array(a
, const char *, 7);
10288 a
->string
[0] = talloc_strdup(a
->string
, "ADOBEPS4.DRV");
10289 a
->string
[1] = talloc_strdup(a
->string
, "DEFPRTR2.PPD");
10290 a
->string
[2] = talloc_strdup(a
->string
, "ADOBEPS4.HLP");
10291 a
->string
[3] = talloc_strdup(a
->string
, "PSMON.DLL");
10292 a
->string
[4] = talloc_strdup(a
->string
, "ADFONTS.MFM");
10293 a
->string
[5] = talloc_strdup(a
->string
, "ICONLIB.DLL");
10295 d
->info8
.dependent_files
= a
;
10296 d
->local
.environment
= talloc_strdup(d
, "Windows 4.0");
10297 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/adobe/");
10300 return test_add_driver_arg(tctx
, p
, d
);
10303 static bool test_add_driver_timestamps(struct torture_context
*tctx
,
10304 struct dcerpc_pipe
*p
)
10306 struct torture_driver_context
*d
;
10307 struct timeval t
= timeval_current();
10309 d
= talloc_zero(tctx
, struct torture_driver_context
);
10311 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
10312 d
->info8
.driver_name
= TORTURE_DRIVER_TIMESTAMPS
;
10313 d
->info8
.architecture
= NULL
;
10314 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
10315 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
10316 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
10317 d
->info8
.driver_date
= timeval_to_nttime(&t
);
10318 d
->local
.environment
= talloc_strdup(d
, "Windows NT x86");
10319 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/i386");
10322 torture_assert(tctx
,
10323 test_add_driver_arg(tctx
, p
, d
),
10326 unix_to_nt_time(&d
->info8
.driver_date
, 1);
10328 torture_assert(tctx
,
10329 test_add_driver_arg(tctx
, p
, d
),
10335 static bool test_multiple_drivers(struct torture_context
*tctx
,
10336 struct dcerpc_pipe
*p
)
10338 struct torture_driver_context
*d
;
10339 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
10340 const char *server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
10342 struct spoolss_AddDriverInfo8 info8
;
10343 uint32_t add_flags
= APD_COPY_NEW_FILES
;
10344 uint32_t delete_flags
= 0;
10346 d
= talloc_zero(tctx
, struct torture_driver_context
);
10348 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
10349 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
10350 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
10351 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
10352 d
->local
.environment
= talloc_strdup(d
, "Windows NT x86");
10353 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/i386");
10356 torture_assert(tctx
,
10357 fillup_printserver_info(tctx
, p
, d
),
10358 "failed to fillup printserver info");
10360 if (!directory_exist(d
->local
.driver_directory
)) {
10361 torture_skip(tctx
, "Skipping Printer Driver test as no local driver is available");
10364 torture_assert(tctx
,
10365 upload_printer_driver(tctx
, dcerpc_server_name(p
), d
),
10366 "failed to upload printer driver");
10369 info8
.architecture
= d
->local
.environment
;
10371 for (i
=0; i
< 3; i
++) {
10372 info8
.driver_name
= talloc_asprintf(d
, "torture_test_driver_%d", i
);
10374 torture_assert(tctx
,
10375 test_AddPrinterDriver_args_level_3(tctx
, b
, server_name_slash
, &info8
, add_flags
, true, NULL
),
10376 "failed to add driver");
10379 torture_assert(tctx
,
10380 test_DeletePrinterDriverEx(tctx
, b
, server_name_slash
, "torture_test_driver_0", info8
.architecture
, delete_flags
, info8
.version
),
10381 "failed to delete driver");
10383 torture_assert(tctx
,
10384 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, info8
.architecture
, 3, "torture_test_driver_1", NULL
),
10385 "torture_test_driver_1 no longer on the server");
10387 torture_assert(tctx
,
10388 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, info8
.architecture
, 3, "torture_test_driver_2", NULL
),
10389 "torture_test_driver_2 no longer on the server");
10391 torture_assert(tctx
,
10392 test_DeletePrinterDriverEx(tctx
, b
, server_name_slash
, "torture_test_driver_1", info8
.architecture
, delete_flags
, info8
.version
),
10393 "failed to delete driver");
10395 torture_assert(tctx
,
10396 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, info8
.architecture
, 3, "torture_test_driver_2", NULL
),
10397 "torture_test_driver_2 no longer on the server");
10399 torture_assert(tctx
,
10400 test_DeletePrinterDriverEx(tctx
, b
, server_name_slash
, "torture_test_driver_2", info8
.architecture
, delete_flags
, info8
.version
),
10401 "failed to delete driver");
10403 torture_assert(tctx
,
10404 remove_printer_driver(tctx
, dcerpc_server_name(p
), d
),
10405 "failed to remove printer driver");
10410 static bool test_del_driver_all_files(struct torture_context
*tctx
,
10411 struct dcerpc_pipe
*p
)
10413 struct torture_driver_context
*d
;
10414 struct spoolss_StringArray
*a
;
10415 uint32_t add_flags
= APD_COPY_NEW_FILES
;
10416 uint32_t delete_flags
= DPD_DELETE_ALL_FILES
;
10417 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
10418 const char *server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
10420 d
= talloc_zero(tctx
, struct torture_driver_context
);
10423 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
10424 d
->info8
.driver_name
= TORTURE_DRIVER_DELETER
;
10425 d
->info8
.architecture
= NULL
;
10426 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
10427 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
10428 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
10429 d
->info8
.help_file
= talloc_strdup(d
, "pscript.hlp");
10430 d
->local
.environment
= talloc_strdup(d
, SPOOLSS_ARCHITECTURE_x64
);
10431 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/x64");
10433 a
= talloc_zero(d
, struct spoolss_StringArray
);
10434 a
->string
= talloc_zero_array(a
, const char *, 3);
10435 a
->string
[0] = talloc_strdup(a
->string
, "cups6.inf");
10436 a
->string
[1] = talloc_strdup(a
->string
, "cups6.ini");
10438 d
->info8
.dependent_files
= a
;
10439 d
->info8
.architecture
= d
->local
.environment
;
10441 torture_assert(tctx
,
10442 fillup_printserver_info(tctx
, p
, d
),
10443 "failed to fillup printserver info");
10445 if (!directory_exist(d
->local
.driver_directory
)) {
10446 torture_skip(tctx
, "Skipping Printer Driver test as no local driver is available");
10449 torture_assert(tctx
,
10450 upload_printer_driver(tctx
, dcerpc_server_name(p
), d
),
10451 "failed to upload printer driver");
10453 torture_assert(tctx
,
10454 test_AddPrinterDriver_args_level_3(tctx
, b
, server_name_slash
, &d
->info8
, add_flags
, true, NULL
),
10455 "failed to add driver");
10457 torture_assert(tctx
,
10458 test_DeletePrinterDriverEx(tctx
, b
, server_name_slash
,
10459 d
->info8
.driver_name
,
10460 d
->local
.environment
,
10463 "failed to delete driver");
10465 torture_assert(tctx
,
10466 check_printer_driver_files(tctx
, dcerpc_server_name(p
), d
, false),
10467 "printer driver file check failed");
10473 static bool test_del_driver_unused_files(struct torture_context
*tctx
,
10474 struct dcerpc_pipe
*p
)
10476 struct torture_driver_context
*d1
;
10477 struct torture_driver_context
*d2
;
10478 uint32_t add_flags
= APD_COPY_NEW_FILES
;
10479 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
10480 const char *server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
10482 d1
= talloc_zero(tctx
, struct torture_driver_context
);
10484 d1
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
10485 d1
->info8
.driver_name
= TORTURE_DRIVER_DELETER
;
10486 d1
->info8
.architecture
= NULL
;
10487 d1
->info8
.driver_path
= talloc_strdup(d1
, "pscript5.dll");
10488 d1
->info8
.data_file
= talloc_strdup(d1
, "cups6.ppd");
10489 d1
->info8
.config_file
= talloc_strdup(d1
, "cupsui6.dll");
10490 d1
->info8
.help_file
= talloc_strdup(d1
, "pscript.hlp");
10491 d1
->local
.environment
= talloc_strdup(d1
, SPOOLSS_ARCHITECTURE_x64
);
10492 d1
->local
.driver_directory
= talloc_strdup(d1
, "/usr/share/cups/drivers/x64");
10493 d1
->info8
.architecture
= d1
->local
.environment
;
10495 d2
= talloc_zero(tctx
, struct torture_driver_context
);
10497 d2
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
10498 d2
->info8
.driver_name
= TORTURE_DRIVER_DELETERIN
;
10499 d2
->info8
.architecture
= NULL
;
10500 d2
->info8
.driver_path
= talloc_strdup(d2
, "pscript5.dll"); /* overlapping */
10501 d2
->info8
.data_file
= talloc_strdup(d2
, "cupsps6.dll");
10502 d2
->info8
.config_file
= talloc_strdup(d2
, "cups6.ini");
10503 d2
->info8
.help_file
= talloc_strdup(d2
, "pscript.hlp"); /* overlapping */
10504 d2
->local
.environment
= talloc_strdup(d2
, SPOOLSS_ARCHITECTURE_x64
);
10505 d2
->local
.driver_directory
= talloc_strdup(d2
, "/usr/share/cups/drivers/x64");
10506 d2
->info8
.architecture
= d2
->local
.environment
;
10508 torture_assert(tctx
,
10509 fillup_printserver_info(tctx
, p
, d1
),
10510 "failed to fillup printserver info");
10511 torture_assert(tctx
,
10512 fillup_printserver_info(tctx
, p
, d2
),
10513 "failed to fillup printserver info");
10515 if (!directory_exist(d1
->local
.driver_directory
)) {
10516 torture_skip(tctx
, "Skipping Printer Driver test as no local driver is available");
10519 torture_assert(tctx
,
10520 upload_printer_driver(tctx
, dcerpc_server_name(p
), d1
),
10521 "failed to upload printer driver");
10522 torture_assert(tctx
,
10523 test_AddPrinterDriver_args_level_3(tctx
, b
, server_name_slash
, &d1
->info8
, add_flags
, true, NULL
),
10524 "failed to add driver");
10526 torture_assert(tctx
,
10527 upload_printer_driver(tctx
, dcerpc_server_name(p
), d2
),
10528 "failed to upload printer driver");
10529 torture_assert(tctx
,
10530 test_AddPrinterDriver_args_level_3(tctx
, b
, server_name_slash
, &d2
->info8
, add_flags
, true, NULL
),
10531 "failed to add driver");
10533 /* some files are in use by a separate driver, should fail */
10534 torture_assert(tctx
,
10535 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name_slash
,
10536 d1
->info8
.driver_name
,
10537 d1
->local
.environment
,
10538 DPD_DELETE_ALL_FILES
,
10540 WERR_PRINTER_DRIVER_IN_USE
),
10541 "invalid delete driver response");
10543 /* should only delete files not in use by other driver */
10544 torture_assert(tctx
,
10545 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name_slash
,
10546 d1
->info8
.driver_name
,
10547 d1
->local
.environment
,
10548 DPD_DELETE_UNUSED_FILES
,
10551 "failed to delete driver (unused files)");
10553 /* check non-overlapping were deleted */
10554 d1
->info8
.driver_path
= NULL
;
10555 d1
->info8
.help_file
= NULL
;
10556 torture_assert(tctx
,
10557 check_printer_driver_files(tctx
, dcerpc_server_name(p
), d1
, false),
10558 "printer driver file check failed");
10559 /* d2 files should be uneffected */
10560 torture_assert(tctx
,
10561 check_printer_driver_files(tctx
, dcerpc_server_name(p
), d2
, true),
10562 "printer driver file check failed");
10564 torture_assert(tctx
,
10565 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name_slash
,
10566 d2
->info8
.driver_name
,
10567 d2
->local
.environment
,
10568 DPD_DELETE_ALL_FILES
,
10571 "failed to delete driver");
10573 torture_assert(tctx
,
10574 check_printer_driver_files(tctx
, dcerpc_server_name(p
), d2
, false),
10575 "printer driver file check failed");
10582 struct torture_suite
*torture_rpc_spoolss_driver(TALLOC_CTX
*mem_ctx
)
10584 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "spoolss.driver");
10586 struct torture_rpc_tcase
*tcase
= torture_suite_add_rpc_iface_tcase(suite
,
10587 "driver", &ndr_table_spoolss
);
10588 torture_rpc_tcase_add_test(tcase
, "add_driver_64", test_add_driver_64
);
10589 torture_rpc_tcase_add_test(tcase
, "add_driver_ex_64", test_add_driver_ex_64
);
10591 torture_rpc_tcase_add_test(tcase
, "add_driver_32", test_add_driver_32
);
10592 torture_rpc_tcase_add_test(tcase
, "add_driver_ex_32", test_add_driver_ex_32
);
10594 torture_rpc_tcase_add_test(tcase
, "add_driver_adobe", test_add_driver_adobe
);
10596 torture_rpc_tcase_add_test(tcase
, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb
);
10598 torture_rpc_tcase_add_test(tcase
, "add_driver_timestamps", test_add_driver_timestamps
);
10600 torture_rpc_tcase_add_test(tcase
, "multiple_drivers", test_multiple_drivers
);
10602 torture_rpc_tcase_add_test(tcase
, "del_driver_all_files", test_del_driver_all_files
);
10604 torture_rpc_tcase_add_test(tcase
, "del_driver_unused_files", test_del_driver_unused_files
);