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/cmdline.h"
41 #include "system/filesys.h"
42 #include "torture/ndr/ndr.h"
43 #include "torture/smb2/proto.h"
45 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
46 #define TORTURE_PRINTER "torture_printer"
47 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
48 #define TORTURE_PRINTER_EX "torture_printer_ex"
49 #define TORTURE_DRIVER "torture_driver"
50 #define TORTURE_DRIVER_ADD "torture_driver_add"
51 #define TORTURE_DRIVER_EX "torture_driver_ex"
52 #define TORTURE_DRIVER_ADOBE "torture_driver_adobe"
53 #define TORTURE_DRIVER_EX_ADOBE "torture_driver_ex_adobe"
54 #define TORTURE_DRIVER_ADOBE_CUPSADDSMB "torture_driver_adobe_cupsaddsmb"
55 #define TORTURE_DRIVER_TIMESTAMPS "torture_driver_timestamps"
56 #define TORTURE_DRIVER_DELETER "torture_driver_deleter"
57 #define TORTURE_DRIVER_COPY_DIR "torture_driver_copy_from_directory"
58 #define TORTURE_DRIVER_DELETERIN "torture_driver_deleterin"
59 #define TORTURE_PRINTER_STATIC1 "print1"
61 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
62 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
63 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
64 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
65 #define TOP_LEVEL_CONTROL_PRINTERS_KEY TOP_LEVEL_CONTROL_KEY "\\Printers"
66 #define TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY TOP_LEVEL_CONTROL_KEY "\\Environments"
68 struct test_spoolss_context
{
69 struct dcerpc_pipe
*spoolss_pipe
;
71 /* server environment */
72 const char *environment
;
74 /* print server handle */
75 struct policy_handle server_handle
;
78 uint32_t port_count
[3];
79 union spoolss_PortInfo
*ports
[3];
81 /* for EnumPrinterDrivers */
82 uint32_t driver_count
[9];
83 union spoolss_DriverInfo
*drivers
[9];
85 /* for EnumMonitors */
86 uint32_t monitor_count
[3];
87 union spoolss_MonitorInfo
*monitors
[3];
89 /* for EnumPrintProcessors */
90 uint32_t print_processor_count
[2];
91 union spoolss_PrintProcessorInfo
*print_processors
[2];
93 /* for EnumPrinters */
94 uint32_t printer_count
[6];
95 union spoolss_PrinterInfo
*printers
[6];
98 struct torture_driver_context
{
100 const char *driver_directory
;
101 const char *environment
;
104 const char *driver_directory
;
105 const char *driver_upload_directory
;
106 const char *environment
;
108 struct spoolss_AddDriverInfo8 info8
;
112 struct torture_printer_context
{
113 struct dcerpc_pipe
*spoolss_pipe
;
114 struct spoolss_SetPrinterInfo2 info2
;
115 struct torture_driver_context driver
;
120 struct spoolss_DeviceMode
*devmode
;
121 struct policy_handle handle
;
124 static bool upload_printer_driver(struct torture_context
*tctx
,
125 const char *server_name
,
126 struct torture_driver_context
*d
);
127 static bool remove_printer_driver(struct torture_context
*tctx
,
128 const char *server_name
,
129 struct torture_driver_context
*d
);
130 static bool fillup_printserver_info(struct torture_context
*tctx
,
131 struct dcerpc_pipe
*p
,
132 struct torture_driver_context
*d
);
133 static bool test_AddPrinterDriver_args_level_3(struct torture_context
*tctx
,
134 struct dcerpc_binding_handle
*b
,
135 const char *server_name
,
136 struct spoolss_AddDriverInfo8
*r
,
139 const char *remote_driver_dir
);
141 #define COMPARE_STRING(tctx, c,r,e) \
142 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
144 /* not every compiler supports __typeof__() */
146 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
147 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
148 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
150 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
151 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
155 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
158 #define COMPARE_UINT32(tctx, c, r, e) do {\
159 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
160 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
163 #define COMPARE_UINT64(tctx, c, r, e) do {\
164 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
165 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
169 #define COMPARE_NTTIME(tctx, c, r, e) do {\
170 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
171 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
174 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
176 if (!c.e && !r.e) { \
180 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
183 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
185 for (__i=0;c.e[__i] != NULL; __i++) { \
186 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
190 #define CHECK_ALIGN(size, n) do {\
192 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
193 size, n, size + n - (size % n));\
197 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
199 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, needed, align) do { \
200 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
201 uint32_t size = ndr_size_##fn##_info(tctx, level, count, info);\
202 uint32_t round_size = DO_ROUND(size, align);\
203 if (round_size != needed) {\
204 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
205 CHECK_ALIGN(size, align);\
210 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, needed, align) do { \
211 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
212 uint32_t size = ndr_size_##fn##_info(tctx, count, info);\
213 uint32_t round_size = DO_ROUND(size, align);\
214 if (round_size != needed) {\
215 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
216 CHECK_ALIGN(size, align);\
221 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, needed, align) do { \
222 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
223 uint32_t size = ndr_size_##fn(info, level, 0);\
224 uint32_t round_size = DO_ROUND(size, align);\
225 if (round_size != needed) {\
226 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
227 CHECK_ALIGN(size, align);\
232 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context
*tctx
,
233 const union spoolss_PrinterInfo
*i
,
235 union spoolss_SetPrinterInfo
*s
)
239 s
->info0
= talloc(tctx
, struct spoolss_SetPrinterInfo0
);
242 s
->info2
= talloc(tctx
, struct spoolss_SetPrinterInfo2
);
243 s
->info2
->servername
= i
->info2
.servername
;
244 s
->info2
->printername
= i
->info2
.printername
;
245 s
->info2
->sharename
= i
->info2
.sharename
;
246 s
->info2
->portname
= i
->info2
.portname
;
247 s
->info2
->drivername
= i
->info2
.drivername
;
248 s
->info2
->comment
= i
->info2
.comment
;
249 s
->info2
->location
= i
->info2
.location
;
250 s
->info2
->devmode_ptr
= 0;
251 s
->info2
->sepfile
= i
->info2
.sepfile
;
252 s
->info2
->printprocessor
= i
->info2
.printprocessor
;
253 s
->info2
->datatype
= i
->info2
.datatype
;
254 s
->info2
->parameters
= i
->info2
.parameters
;
255 s
->info2
->secdesc_ptr
= 0;
256 s
->info2
->attributes
= i
->info2
.attributes
;
257 s
->info2
->priority
= i
->info2
.priority
;
258 s
->info2
->defaultpriority
= i
->info2
.defaultpriority
;
259 s
->info2
->starttime
= i
->info2
.starttime
;
260 s
->info2
->untiltime
= i
->info2
.untiltime
;
261 s
->info2
->status
= i
->info2
.status
;
262 s
->info2
->cjobs
= i
->info2
.cjobs
;
263 s
->info2
->averageppm
= i
->info2
.averageppm
;
279 static bool test_OpenPrinter_server(struct torture_context
*tctx
,
280 struct dcerpc_pipe
*p
,
281 struct policy_handle
*server_handle
)
284 struct spoolss_OpenPrinter op
;
285 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
287 op
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
288 op
.in
.datatype
= NULL
;
289 op
.in
.devmode_ctr
.devmode
= NULL
;
290 op
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
291 op
.out
.handle
= server_handle
;
293 torture_comment(tctx
, "Testing OpenPrinter(%s)\n", op
.in
.printername
);
295 status
= dcerpc_spoolss_OpenPrinter_r(b
, tctx
, &op
);
296 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_OpenPrinter failed");
297 torture_assert_werr_ok(tctx
, op
.out
.result
, "dcerpc_spoolss_OpenPrinter failed");
302 static bool test_EnumPorts(struct torture_context
*tctx
,
305 struct test_spoolss_context
*ctx
=
306 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
307 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
308 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
310 struct spoolss_EnumPorts r
;
311 uint16_t levels
[] = { 1, 2 };
314 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
315 int level
= levels
[i
];
319 union spoolss_PortInfo
*info
;
321 r
.in
.servername
= "";
325 r
.out
.needed
= &needed
;
326 r
.out
.count
= &count
;
329 torture_comment(tctx
, "Testing EnumPorts level %u\n", r
.in
.level
);
331 status
= dcerpc_spoolss_EnumPorts_r(b
, ctx
, &r
);
332 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPorts failed");
333 if (W_ERROR_IS_OK(r
.out
.result
)) {
334 /* TODO: do some more checks here */
337 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
338 "EnumPorts unexpected return code");
340 blob
= data_blob_talloc_zero(ctx
, needed
);
342 r
.in
.offered
= needed
;
344 status
= dcerpc_spoolss_EnumPorts_r(b
, ctx
, &r
);
345 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPorts failed");
347 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
349 torture_assert(tctx
, info
, "EnumPorts returned no info");
351 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts
, info
, r
.in
.level
, count
, needed
, 4);
353 ctx
->port_count
[level
] = count
;
354 ctx
->ports
[level
] = info
;
357 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
358 int level
= levels
[i
];
359 int old_level
= levels
[i
-1];
360 torture_assert_int_equal(tctx
, ctx
->port_count
[level
], ctx
->port_count
[old_level
],
361 "EnumPorts invalid value");
363 /* if the array sizes are not the same we would maybe segfault in the following code */
365 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
366 int level
= levels
[i
];
367 for (j
=0;j
<ctx
->port_count
[level
];j
++) {
368 union spoolss_PortInfo
*cur
= &ctx
->ports
[level
][j
];
369 union spoolss_PortInfo
*ref
= &ctx
->ports
[2][j
];
372 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, port_name
);
375 /* level 2 is our reference, and it makes no sense to compare it to itself */
384 static bool test_GetPrintProcessorDirectory(struct torture_context
*tctx
,
387 struct test_spoolss_context
*ctx
=
388 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
391 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
392 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
393 struct spoolss_GetPrintProcessorDirectory r
;
408 .server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
))
411 .server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
))
417 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
418 int level
= levels
[i
].level
;
421 r
.in
.server
= levels
[i
].server
;
422 r
.in
.environment
= ctx
->environment
;
426 r
.out
.needed
= &needed
;
428 torture_comment(tctx
, "Testing GetPrintProcessorDirectory level %u\n", r
.in
.level
);
430 status
= dcerpc_spoolss_GetPrintProcessorDirectory_r(b
, tctx
, &r
);
431 torture_assert_ntstatus_ok(tctx
, status
,
432 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
433 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
434 "GetPrintProcessorDirectory unexpected return code");
436 blob
= data_blob_talloc_zero(tctx
, needed
);
438 r
.in
.offered
= needed
;
440 status
= dcerpc_spoolss_GetPrintProcessorDirectory_r(b
, tctx
, &r
);
441 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
443 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrintProcessorDirectory failed");
445 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo
, r
.out
.info
, r
.in
.level
, needed
, 2);
452 static bool test_GetPrinterDriverDirectory(struct torture_context
*tctx
,
455 struct test_spoolss_context
*ctx
=
456 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
459 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
460 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
461 struct spoolss_GetPrinterDriverDirectory r
;
476 .server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
))
479 .server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
))
485 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
486 int level
= levels
[i
].level
;
489 r
.in
.server
= levels
[i
].server
;
490 r
.in
.environment
= ctx
->environment
;
494 r
.out
.needed
= &needed
;
496 torture_comment(tctx
, "Testing GetPrinterDriverDirectory level %u\n", r
.in
.level
);
498 status
= dcerpc_spoolss_GetPrinterDriverDirectory_r(b
, tctx
, &r
);
499 torture_assert_ntstatus_ok(tctx
, status
,
500 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
501 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
502 "GetPrinterDriverDirectory unexpected return code");
504 blob
= data_blob_talloc_zero(tctx
, needed
);
506 r
.in
.offered
= needed
;
508 status
= dcerpc_spoolss_GetPrinterDriverDirectory_r(b
, tctx
, &r
);
509 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
511 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrinterDriverDirectory failed");
513 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo
, r
.out
.info
, r
.in
.level
, needed
, 2);
519 static bool test_EnumPrinterDrivers_buffers(struct torture_context
*tctx
,
520 struct dcerpc_binding_handle
*b
,
521 const char *server_name
,
522 const char *environment
,
526 union spoolss_DriverInfo
**info_p
)
528 struct spoolss_EnumPrinterDrivers r
;
531 union spoolss_DriverInfo
*info
;
535 buffer
= data_blob_talloc_zero(tctx
, offered
);
538 r
.in
.server
= server_name
;
539 r
.in
.environment
= environment
;
541 r
.in
.buffer
= offered
? &buffer
: NULL
;
542 r
.in
.offered
= offered
;
543 r
.out
.needed
= &needed
;
544 r
.out
.count
= &count
;
547 torture_comment(tctx
, "Testing EnumPrinterDrivers(%s) level %u, offered: %u\n",
548 r
.in
.environment
, r
.in
.level
, r
.in
.offered
);
550 torture_assert_ntstatus_ok(tctx
,
551 dcerpc_spoolss_EnumPrinterDrivers_r(b
, tctx
, &r
),
552 "EnumPrinterDrivers failed");
553 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
554 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
556 r
.in
.offered
= needed
;
558 torture_assert_ntstatus_ok(tctx
,
559 dcerpc_spoolss_EnumPrinterDrivers_r(b
, tctx
, &r
),
560 "EnumPrinterDrivers failed");
563 torture_assert_werr_ok(tctx
, r
.out
.result
,
564 "EnumPrinterDrivers failed");
573 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers
, info
, r
.in
.level
, count
, needed
, 4);
580 static bool test_EnumPrinterDrivers_args(struct torture_context
*tctx
,
581 struct dcerpc_binding_handle
*b
,
582 const char *server_name
,
583 const char *environment
,
586 union spoolss_DriverInfo
**info_p
)
588 return test_EnumPrinterDrivers_buffers(tctx
, b
, server_name
,
589 environment
, level
, 0,
593 static bool test_EnumPrinterDrivers_findone(struct torture_context
*tctx
,
594 struct dcerpc_binding_handle
*b
,
595 const char *server_name
,
596 const char *environment
,
598 const char *driver_name
,
599 union spoolss_DriverInfo
*info_p
)
602 union spoolss_DriverInfo
*info
;
604 const char *environment_ret
= NULL
;
607 test_EnumPrinterDrivers_args(tctx
, b
, server_name
, environment
, level
, &count
, &info
),
608 "failed to enumerate printer drivers");
610 for (i
=0; i
< count
; i
++) {
611 const char *driver_name_ret
= "";
614 driver_name_ret
= info
[i
].info1
.driver_name
;
617 driver_name_ret
= info
[i
].info2
.driver_name
;
618 environment_ret
= info
[i
].info2
.architecture
;
621 driver_name_ret
= info
[i
].info3
.driver_name
;
622 environment_ret
= info
[i
].info3
.architecture
;
625 driver_name_ret
= info
[i
].info4
.driver_name
;
626 environment_ret
= info
[i
].info4
.architecture
;
629 driver_name_ret
= info
[i
].info5
.driver_name
;
630 environment_ret
= info
[i
].info5
.architecture
;
633 driver_name_ret
= info
[i
].info6
.driver_name
;
634 environment_ret
= info
[i
].info6
.architecture
;
637 driver_name_ret
= info
[i
].info7
.driver_name
;
640 driver_name_ret
= info
[i
].info8
.driver_name
;
641 environment_ret
= info
[i
].info8
.architecture
;
646 if (environment_ret
) {
647 torture_assert_str_equal(tctx
, environment
, environment_ret
, "architecture mismatch");
649 if (strequal(driver_name
, driver_name_ret
)) {
660 static bool test_EnumPrinterDrivers(struct torture_context
*tctx
,
663 struct test_spoolss_context
*ctx
=
664 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
665 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
666 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
667 uint16_t levels
[] = { 1, 2, 3, 4, 5, 6, 8 };
668 uint16_t buffer_sizes
[] = { 0, 1024, 6040, 0xffff };
671 /* FIXME: gd, come back and fix "" as server, and handle
672 * priority of returned error codes in torture test and samba 3
674 const char *server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
675 const char *environments
[2];
677 environments
[0] = SPOOLSS_ARCHITECTURE_ALL
;
678 environments
[1] = ctx
->environment
;
680 for (a
=0;a
<ARRAY_SIZE(environments
);a
++) {
682 for (i
=0;i
<ARRAY_SIZE(buffer_sizes
);i
++) {
684 test_EnumPrinterDrivers_buffers(tctx
, b
, server_name
,
688 "failed to enumerate drivers");
691 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
692 int level
= levels
[i
];
694 union spoolss_DriverInfo
*info
;
697 test_EnumPrinterDrivers_args(tctx
, b
, server_name
, environments
[a
], level
, &count
, &info
),
698 "failed to enumerate drivers");
700 ctx
->driver_count
[level
] = count
;
701 ctx
->drivers
[level
] = info
;
704 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
705 int level
= levels
[i
];
706 int old_level
= levels
[i
-1];
708 torture_assert_int_equal(tctx
, ctx
->driver_count
[level
], ctx
->driver_count
[old_level
],
709 "EnumPrinterDrivers invalid value");
712 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
713 int level
= levels
[i
];
715 for (j
=0;j
<ctx
->driver_count
[level
- 1];j
++) {
716 union spoolss_DriverInfo
*cur
= &ctx
->drivers
[level
- 1][j
];
717 union spoolss_DriverInfo
*ref
= &ctx
->drivers
[8][j
];
721 COMPARE_STRING(tctx
, cur
->info1
, ref
->info8
, driver_name
);
724 COMPARE_UINT32(tctx
, cur
->info2
, ref
->info8
, version
);
725 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, driver_name
);
726 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, architecture
);
727 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, driver_path
);
728 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, data_file
);
729 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, config_file
);
732 COMPARE_UINT32(tctx
, cur
->info3
, ref
->info8
, version
);
733 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, driver_name
);
734 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, architecture
);
735 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, driver_path
);
736 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, data_file
);
737 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, config_file
);
738 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, help_file
);
739 COMPARE_STRING_ARRAY(tctx
, cur
->info3
, ref
->info8
, dependent_files
);
740 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, monitor_name
);
741 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, default_datatype
);
744 COMPARE_UINT32(tctx
, cur
->info4
, ref
->info8
, version
);
745 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, driver_name
);
746 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, architecture
);
747 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, driver_path
);
748 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, data_file
);
749 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, config_file
);
750 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, help_file
);
751 COMPARE_STRING_ARRAY(tctx
, cur
->info4
, ref
->info8
, dependent_files
);
752 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, monitor_name
);
753 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, default_datatype
);
754 COMPARE_STRING_ARRAY(tctx
, cur
->info4
, ref
->info8
, previous_names
);
757 COMPARE_UINT32(tctx
, cur
->info5
, ref
->info8
, version
);
758 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, driver_name
);
759 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, architecture
);
760 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, driver_path
);
761 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, data_file
);
762 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, config_file
);
763 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
764 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
765 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
768 COMPARE_UINT32(tctx
, cur
->info6
, ref
->info8
, version
);
769 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, driver_name
);
770 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, architecture
);
771 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, driver_path
);
772 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, data_file
);
773 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, config_file
);
774 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, help_file
);
775 COMPARE_STRING_ARRAY(tctx
, cur
->info6
, ref
->info8
, dependent_files
);
776 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, monitor_name
);
777 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, default_datatype
);
778 COMPARE_STRING_ARRAY(tctx
, cur
->info6
, ref
->info8
, previous_names
);
779 COMPARE_NTTIME(tctx
, cur
->info6
, ref
->info8
, driver_date
);
780 COMPARE_UINT64(tctx
, cur
->info6
, ref
->info8
, driver_version
);
781 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, manufacturer_name
);
782 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, manufacturer_url
);
783 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, hardware_id
);
784 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, provider
);
787 /* level 8 is our reference, and it makes no sense to compare it to itself */
797 static bool test_EnumMonitors(struct torture_context
*tctx
,
800 struct test_spoolss_context
*ctx
=
801 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
802 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
803 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
805 struct spoolss_EnumMonitors r
;
806 uint16_t levels
[] = { 1, 2 };
809 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
810 int level
= levels
[i
];
814 union spoolss_MonitorInfo
*info
;
816 r
.in
.servername
= "";
820 r
.out
.needed
= &needed
;
821 r
.out
.count
= &count
;
824 torture_comment(tctx
, "Testing EnumMonitors level %u\n", r
.in
.level
);
826 status
= dcerpc_spoolss_EnumMonitors_r(b
, ctx
, &r
);
827 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumMonitors failed");
828 if (W_ERROR_IS_OK(r
.out
.result
)) {
829 /* TODO: do some more checks here */
832 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
833 "EnumMonitors failed");
835 blob
= data_blob_talloc_zero(ctx
, needed
);
837 r
.in
.offered
= needed
;
839 status
= dcerpc_spoolss_EnumMonitors_r(b
, ctx
, &r
);
840 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumMonitors failed");
842 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumMonitors failed");
844 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors
, info
, r
.in
.level
, count
, needed
, 4);
846 ctx
->monitor_count
[level
] = count
;
847 ctx
->monitors
[level
] = info
;
850 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
851 int level
= levels
[i
];
852 int old_level
= levels
[i
-1];
853 torture_assert_int_equal(tctx
, ctx
->monitor_count
[level
], ctx
->monitor_count
[old_level
],
854 "EnumMonitors invalid value");
857 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
858 int level
= levels
[i
];
859 for (j
=0;j
<ctx
->monitor_count
[level
];j
++) {
860 union spoolss_MonitorInfo
*cur
= &ctx
->monitors
[level
][j
];
861 union spoolss_MonitorInfo
*ref
= &ctx
->monitors
[2][j
];
864 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, monitor_name
);
867 torture_assert_str_equal(tctx
, ref
->info2
.environment
, ctx
->environment
, "invalid environment");
868 /* level 2 is our reference, and it makes no sense to compare it to itself */
877 static bool test_EnumPrintProcessors_level(struct torture_context
*tctx
,
878 struct dcerpc_binding_handle
*b
,
879 const char *environment
,
882 union spoolss_PrintProcessorInfo
**info_p
,
883 WERROR expected_result
)
885 struct spoolss_EnumPrintProcessors r
;
889 union spoolss_PrintProcessorInfo
*info
;
891 r
.in
.servername
= "";
892 r
.in
.environment
= environment
;
896 r
.out
.needed
= &needed
;
897 r
.out
.count
= &count
;
900 torture_comment(tctx
, "Testing EnumPrintProcessors(%s) level %u\n",
901 r
.in
.environment
, r
.in
.level
);
903 torture_assert_ntstatus_ok(tctx
,
904 dcerpc_spoolss_EnumPrintProcessors_r(b
, tctx
, &r
),
905 "EnumPrintProcessors failed");
906 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
907 blob
= data_blob_talloc_zero(tctx
, needed
);
909 r
.in
.offered
= needed
;
910 torture_assert_ntstatus_ok(tctx
,
911 dcerpc_spoolss_EnumPrintProcessors_r(b
, tctx
, &r
),
912 "EnumPrintProcessors failed");
914 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
915 "EnumPrintProcessors failed");
917 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors
, info
, level
, count
, needed
, 4);
929 static bool test_EnumPrintProcessors(struct torture_context
*tctx
,
932 struct test_spoolss_context
*ctx
=
933 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
935 uint16_t levels
[] = {0, 1, 2, 3, 32, 256 };
936 uint16_t ok
[] = {0, 1, 0, 0, 0, 0 };
938 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
939 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
942 test_EnumPrintProcessors_level(tctx
, b
, "phantasy", 1, NULL
, NULL
, WERR_INVALID_ENVIRONMENT
),
943 "test_EnumPrintProcessors_level failed");
945 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
946 union spoolss_PrintProcessorInfo
*info
;
948 WERROR expected_result
= ok
[i
] ? WERR_OK
: WERR_INVALID_LEVEL
;
951 test_EnumPrintProcessors_level(tctx
, b
, ctx
->environment
, levels
[i
], &count
, &info
, expected_result
),
952 "test_EnumPrintProcessors_level failed");
958 static bool test_EnumPrintProcessorDataTypes_level(struct torture_context
*tctx
,
959 struct dcerpc_binding_handle
*b
,
960 const char *print_processor_name
,
963 union spoolss_PrintProcDataTypesInfo
**info_p
,
964 WERROR expected_result
)
966 struct spoolss_EnumPrintProcessorDataTypes r
;
970 union spoolss_PrintProcDataTypesInfo
*info
;
972 r
.in
.servername
= "";
973 r
.in
.print_processor_name
= print_processor_name
;
977 r
.out
.needed
= &needed
;
978 r
.out
.count
= &count
;
981 torture_comment(tctx
, "Testing EnumPrintProcessorDataTypes(%s) level %u\n",
982 r
.in
.print_processor_name
, r
.in
.level
);
984 torture_assert_ntstatus_ok(tctx
,
985 dcerpc_spoolss_EnumPrintProcessorDataTypes_r(b
, tctx
, &r
),
986 "EnumPrintProcessorDataTypes failed");
987 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
988 blob
= data_blob_talloc_zero(tctx
, needed
);
990 r
.in
.offered
= needed
;
991 torture_assert_ntstatus_ok(tctx
,
992 dcerpc_spoolss_EnumPrintProcessorDataTypes_r(b
, tctx
, &r
),
993 "EnumPrintProcessorDataTypes failed");
995 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
996 "EnumPrintProcessorDataTypes failed");
998 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessorDataTypes
, info
, level
, count
, needed
, 4);
1010 static bool test_EnumPrintProcessorDataTypes(struct torture_context
*tctx
,
1013 struct test_spoolss_context
*ctx
=
1014 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
1016 uint16_t levels
[] = {0, 1, 2, 3, 32, 256 };
1017 uint16_t ok
[] = {0, 1, 0, 0, 0, 0 };
1019 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
1020 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
1022 torture_assert(tctx
,
1023 test_EnumPrintProcessorDataTypes_level(tctx
, b
, NULL
, 1, NULL
, NULL
, WERR_UNKNOWN_PRINTPROCESSOR
),
1024 "test_EnumPrintProcessorDataTypes_level failed");
1026 torture_assert(tctx
,
1027 test_EnumPrintProcessorDataTypes_level(tctx
, b
, "nonexisting", 1, NULL
, NULL
, WERR_UNKNOWN_PRINTPROCESSOR
),
1028 "test_EnumPrintProcessorDataTypes_level failed");
1030 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
1031 int level
= levels
[i
];
1033 union spoolss_PrintProcDataTypesInfo
*info
;
1034 WERROR expected_result
= ok
[i
] ? WERR_OK
: WERR_INVALID_LEVEL
;
1036 torture_assert(tctx
,
1037 test_EnumPrintProcessorDataTypes_level(tctx
, b
, "winprint", level
, &count
, &info
, expected_result
),
1038 "test_EnumPrintProcessorDataTypes_level failed");
1042 union spoolss_PrintProcessorInfo
*info
;
1045 torture_assert(tctx
,
1046 test_EnumPrintProcessors_level(tctx
, b
, ctx
->environment
, 1, &count
, &info
, WERR_OK
),
1047 "test_EnumPrintProcessors_level failed");
1049 for (i
=0; i
< count
; i
++) {
1050 torture_assert(tctx
,
1051 test_EnumPrintProcessorDataTypes_level(tctx
, b
, info
[i
].info1
.print_processor_name
, 1, NULL
, NULL
, WERR_OK
),
1052 "test_EnumPrintProcessorDataTypes_level failed");
1060 static bool test_EnumPrinters(struct torture_context
*tctx
,
1063 struct test_spoolss_context
*ctx
=
1064 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
1065 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
1066 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
1067 struct spoolss_EnumPrinters r
;
1069 uint16_t levels
[] = { 0, 1, 2, 4, 5 };
1072 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
1073 int level
= levels
[i
];
1077 union spoolss_PrinterInfo
*info
;
1079 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
1084 r
.out
.needed
= &needed
;
1085 r
.out
.count
= &count
;
1088 torture_comment(tctx
, "Testing EnumPrinters level %u\n", r
.in
.level
);
1090 status
= dcerpc_spoolss_EnumPrinters_r(b
, ctx
, &r
);
1091 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinters failed");
1092 if (W_ERROR_IS_OK(r
.out
.result
)) {
1093 /* TODO: do some more checks here */
1096 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
1097 "EnumPrinters unexpected return code");
1099 blob
= data_blob_talloc_zero(ctx
, needed
);
1100 r
.in
.buffer
= &blob
;
1101 r
.in
.offered
= needed
;
1103 status
= dcerpc_spoolss_EnumPrinters_r(b
, ctx
, &r
);
1104 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinters failed");
1106 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
1108 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters
, info
, r
.in
.level
, count
, needed
, 4);
1110 ctx
->printer_count
[level
] = count
;
1111 ctx
->printers
[level
] = info
;
1114 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
1115 int level
= levels
[i
];
1116 int old_level
= levels
[i
-1];
1117 torture_assert_int_equal(tctx
, ctx
->printer_count
[level
], ctx
->printer_count
[old_level
],
1118 "EnumPrinters invalid value");
1121 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
1122 int level
= levels
[i
];
1123 for (j
=0;j
<ctx
->printer_count
[level
];j
++) {
1124 union spoolss_PrinterInfo
*cur
= &ctx
->printers
[level
][j
];
1125 union spoolss_PrinterInfo
*ref
= &ctx
->printers
[2][j
];
1128 COMPARE_STRING(tctx
, cur
->info0
, ref
->info2
, printername
);
1129 COMPARE_STRING(tctx
, cur
->info0
, ref
->info2
, servername
);
1130 COMPARE_UINT32(tctx
, cur
->info0
, ref
->info2
, cjobs
);
1131 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
1132 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
1133 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
1134 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
1135 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
1136 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
1137 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
1138 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
1139 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
1140 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
1141 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
1142 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
1143 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
1144 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
1145 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
1146 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
1147 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
1148 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
1149 COMPARE_UINT32(tctx
, cur
->info0
, ref
->info2
, status
);
1150 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
1151 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
1152 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
1153 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
1154 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
1155 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
1156 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
1159 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
1160 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
1161 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
1162 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, comment
);
1165 /* level 2 is our reference, and it makes no sense to compare it to itself */
1168 COMPARE_STRING(tctx
, cur
->info4
, ref
->info2
, printername
);
1169 COMPARE_STRING(tctx
, cur
->info4
, ref
->info2
, servername
);
1170 COMPARE_UINT32(tctx
, cur
->info4
, ref
->info2
, attributes
);
1173 COMPARE_STRING(tctx
, cur
->info5
, ref
->info2
, printername
);
1174 COMPARE_STRING(tctx
, cur
->info5
, ref
->info2
, portname
);
1175 COMPARE_UINT32(tctx
, cur
->info5
, ref
->info2
, attributes
);
1176 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
1177 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
1184 * - verify that the port of a printer was in the list returned by EnumPorts
1190 static bool test_GetPrinterDriver2(struct torture_context
*tctx
,
1191 struct dcerpc_binding_handle
*b
,
1192 struct policy_handle
*handle
,
1193 const char *driver_name
,
1194 const char *environment
);
1196 bool test_GetPrinter_level_exp(struct torture_context
*tctx
,
1197 struct dcerpc_binding_handle
*b
,
1198 struct policy_handle
*handle
,
1200 WERROR expected_werror
,
1201 union spoolss_PrinterInfo
*info
)
1203 struct spoolss_GetPrinter r
;
1206 r
.in
.handle
= handle
;
1210 r
.out
.needed
= &needed
;
1212 torture_comment(tctx
, "Testing GetPrinter level %u\n", r
.in
.level
);
1214 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinter_r(b
, tctx
, &r
),
1215 "GetPrinter failed");
1217 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1218 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
1219 r
.in
.buffer
= &blob
;
1220 r
.in
.offered
= needed
;
1222 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinter_r(b
, tctx
, &r
),
1223 "GetPrinter failed");
1226 torture_assert_werr_equal(tctx
,
1227 r
.out
.result
, expected_werror
,
1228 "GetPrinter failed");
1230 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo
, r
.out
.info
, r
.in
.level
, needed
, 4);
1232 if (info
&& r
.out
.info
) {
1233 *info
= *r
.out
.info
;
1239 bool test_GetPrinter_level(struct torture_context
*tctx
,
1240 struct dcerpc_binding_handle
*b
,
1241 struct policy_handle
*handle
,
1243 union spoolss_PrinterInfo
*info
)
1245 return test_GetPrinter_level_exp(tctx
, b
, handle
, level
, WERR_OK
, info
);
1248 static bool test_GetPrinter(struct torture_context
*tctx
,
1249 struct dcerpc_binding_handle
*b
,
1250 struct policy_handle
*handle
,
1251 const char *environment
)
1253 uint32_t levels
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1256 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
1258 union spoolss_PrinterInfo info
;
1262 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, levels
[i
], &info
),
1263 "failed to call GetPrinter");
1265 if ((levels
[i
] == 2) && info
.info2
.drivername
&& strlen(info
.info2
.drivername
)) {
1266 torture_assert(tctx
,
1267 test_GetPrinterDriver2(tctx
, b
, handle
, info
.info2
.drivername
, environment
),
1268 "failed to call test_GetPrinterDriver2");
1275 static bool test_SetPrinter(struct torture_context
*tctx
,
1276 struct dcerpc_binding_handle
*b
,
1277 struct policy_handle
*handle
,
1278 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
1279 struct spoolss_DevmodeContainer
*devmode_ctr
,
1280 struct sec_desc_buf
*secdesc_ctr
,
1281 enum spoolss_PrinterControl command
)
1283 struct spoolss_SetPrinter r
;
1285 r
.in
.handle
= handle
;
1286 r
.in
.info_ctr
= info_ctr
;
1287 r
.in
.devmode_ctr
= devmode_ctr
;
1288 r
.in
.secdesc_ctr
= secdesc_ctr
;
1289 r
.in
.command
= command
;
1291 torture_comment(tctx
, "Testing SetPrinter level %d\n", r
.in
.info_ctr
->level
);
1293 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
),
1294 "failed to call SetPrinter");
1295 torture_assert(tctx
, (W_ERROR_EQUAL(r
.out
.result
, WERR_OK
)
1296 || W_ERROR_EQUAL(r
.out
.result
, WERR_IO_PENDING
)),
1297 "SetPrinter failed");
1302 static bool test_SetPrinter_errors(struct torture_context
*tctx
,
1303 struct dcerpc_binding_handle
*b
,
1304 struct policy_handle
*handle
)
1306 struct spoolss_SetPrinter r
;
1307 uint16_t levels
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1310 struct spoolss_SetPrinterInfoCtr info_ctr
;
1311 struct spoolss_DevmodeContainer devmode_ctr
;
1312 struct sec_desc_buf secdesc_ctr
;
1315 info_ctr
.info
.info0
= NULL
;
1317 ZERO_STRUCT(devmode_ctr
);
1318 ZERO_STRUCT(secdesc_ctr
);
1320 r
.in
.handle
= handle
;
1321 r
.in
.info_ctr
= &info_ctr
;
1322 r
.in
.devmode_ctr
= &devmode_ctr
;
1323 r
.in
.secdesc_ctr
= &secdesc_ctr
;
1326 torture_comment(tctx
, "Testing SetPrinter all zero\n");
1328 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
),
1329 "failed to call SetPrinter");
1330 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAMETER
,
1331 "failed to call SetPrinter");
1334 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
1336 struct spoolss_SetPrinterInfo0 info0
;
1337 struct spoolss_SetPrinterInfo1 info1
;
1338 struct spoolss_SetPrinterInfo2 info2
;
1339 struct spoolss_SetPrinterInfo3 info3
;
1340 struct spoolss_SetPrinterInfo4 info4
;
1341 struct spoolss_SetPrinterInfo5 info5
;
1342 struct spoolss_SetPrinterInfo6 info6
;
1343 struct spoolss_SetPrinterInfo7 info7
;
1344 struct spoolss_SetPrinterInfo8 info8
;
1345 struct spoolss_SetPrinterInfo9 info9
;
1348 info_ctr
.level
= levels
[i
];
1349 switch (levels
[i
]) {
1352 info_ctr
.info
.info0
= &info0
;
1356 info_ctr
.info
.info1
= &info1
;
1360 info_ctr
.info
.info2
= &info2
;
1364 info_ctr
.info
.info3
= &info3
;
1368 info_ctr
.info
.info4
= &info4
;
1372 info_ctr
.info
.info5
= &info5
;
1376 info_ctr
.info
.info6
= &info6
;
1380 info_ctr
.info
.info7
= &info7
;
1384 info_ctr
.info
.info8
= &info8
;
1388 info_ctr
.info
.info9
= &info9
;
1392 torture_comment(tctx
, "Testing SetPrinter level %d, command %d\n",
1393 info_ctr
.level
, r
.in
.command
);
1395 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
),
1396 "failed to call SetPrinter");
1398 switch (r
.in
.command
) {
1399 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
: /* 0 */
1400 /* is ignored for all levels other then 0 */
1401 if (info_ctr
.level
> 0) {
1407 case SPOOLSS_PRINTER_CONTROL_PAUSE
: /* 1 */
1408 case SPOOLSS_PRINTER_CONTROL_RESUME
: /* 2 */
1409 case SPOOLSS_PRINTER_CONTROL_PURGE
: /* 3 */
1410 if (info_ctr
.level
> 0) {
1411 /* is invalid for all levels other then 0 */
1412 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PRINTER_COMMAND
,
1413 "unexpected error code returned");
1416 torture_assert_werr_ok(tctx
, r
.out
.result
,
1417 "failed to call SetPrinter with non 0 command");
1422 case SPOOLSS_PRINTER_CONTROL_SET_STATUS
: /* 4 */
1423 /* FIXME: gd needs further investigation */
1425 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PRINTER_COMMAND
,
1426 "unexpected error code returned");
1430 switch (info_ctr
.level
) {
1432 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_LEVEL
,
1433 "unexpected error code returned");
1436 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_PRINTER_DRIVER
,
1437 "unexpected error code returned");
1443 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAMETER
,
1444 "unexpected error code returned");
1447 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_NOT_SUPPORTED
,
1448 "unexpected error code returned");
1451 torture_assert_werr_ok(tctx
, r
.out
.result
,
1452 "failed to call SetPrinter");
1457 if (r
.in
.command
< 5) {
1465 static void clear_info2(struct spoolss_SetPrinterInfoCtr
*r
)
1467 if ((r
->level
== 2) && (r
->info
.info2
)) {
1468 r
->info
.info2
->secdesc_ptr
= 0;
1469 r
->info
.info2
->devmode_ptr
= 0;
1473 static bool test_PrinterInfo(struct torture_context
*tctx
,
1474 struct dcerpc_binding_handle
*b
,
1475 struct policy_handle
*handle
)
1478 struct spoolss_SetPrinter s
;
1479 struct spoolss_GetPrinter q
;
1480 struct spoolss_GetPrinter q0
;
1481 struct spoolss_SetPrinterInfoCtr info_ctr
;
1482 union spoolss_PrinterInfo info
;
1483 struct spoolss_DevmodeContainer devmode_ctr
;
1484 struct sec_desc_buf secdesc_ctr
;
1485 uint32_t needed
= 0;
1486 DATA_BLOB blob
= data_blob_null
;
1490 uint32_t status_list
[] = {
1491 /* these do not stick
1492 PRINTER_STATUS_PAUSED,
1493 PRINTER_STATUS_ERROR,
1494 PRINTER_STATUS_PENDING_DELETION, */
1495 PRINTER_STATUS_PAPER_JAM
,
1496 PRINTER_STATUS_PAPER_OUT
,
1497 PRINTER_STATUS_MANUAL_FEED
,
1498 PRINTER_STATUS_PAPER_PROBLEM
,
1499 PRINTER_STATUS_OFFLINE
,
1500 PRINTER_STATUS_IO_ACTIVE
,
1501 PRINTER_STATUS_BUSY
,
1502 PRINTER_STATUS_PRINTING
,
1503 PRINTER_STATUS_OUTPUT_BIN_FULL
,
1504 PRINTER_STATUS_NOT_AVAILABLE
,
1505 PRINTER_STATUS_WAITING
,
1506 PRINTER_STATUS_PROCESSING
,
1507 PRINTER_STATUS_INITIALIZING
,
1508 PRINTER_STATUS_WARMING_UP
,
1509 PRINTER_STATUS_TONER_LOW
,
1510 PRINTER_STATUS_NO_TONER
,
1511 PRINTER_STATUS_PAGE_PUNT
,
1512 PRINTER_STATUS_USER_INTERVENTION
,
1513 PRINTER_STATUS_OUT_OF_MEMORY
,
1514 PRINTER_STATUS_DOOR_OPEN
,
1515 PRINTER_STATUS_SERVER_UNKNOWN
,
1516 PRINTER_STATUS_POWER_SAVE
,
1517 /* these do not stick
1526 uint32_t default_attribute
= PRINTER_ATTRIBUTE_LOCAL
;
1527 uint32_t attribute_list
[] = {
1528 PRINTER_ATTRIBUTE_QUEUED
,
1529 /* fails with WERR_INVALID_DATATYPE:
1530 PRINTER_ATTRIBUTE_DIRECT, */
1532 PRINTER_ATTRIBUTE_DEFAULT, */
1533 PRINTER_ATTRIBUTE_SHARED
,
1535 PRINTER_ATTRIBUTE_NETWORK, */
1536 PRINTER_ATTRIBUTE_HIDDEN
,
1537 PRINTER_ATTRIBUTE_LOCAL
,
1538 PRINTER_ATTRIBUTE_ENABLE_DEVQ
,
1539 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
,
1540 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST
,
1541 PRINTER_ATTRIBUTE_WORK_OFFLINE
,
1543 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1544 /* fails with WERR_INVALID_DATATYPE:
1545 PRINTER_ATTRIBUTE_RAW_ONLY, */
1546 /* these do not stick
1547 PRINTER_ATTRIBUTE_PUBLISHED,
1548 PRINTER_ATTRIBUTE_FAX,
1549 PRINTER_ATTRIBUTE_TS,
1568 torture_skip(tctx
, "Printer Info test is currently broken, skipping");
1571 ZERO_STRUCT(devmode_ctr
);
1572 ZERO_STRUCT(secdesc_ctr
);
1574 s
.in
.handle
= handle
;
1576 s
.in
.info_ctr
= &info_ctr
;
1577 s
.in
.devmode_ctr
= &devmode_ctr
;
1578 s
.in
.secdesc_ctr
= &secdesc_ctr
;
1580 q
.in
.handle
= handle
;
1584 #define TESTGETCALL(call, r, needed, blob) \
1585 r.in.buffer = NULL; \
1587 r.out.needed = &needed; \
1588 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1589 if (!NT_STATUS_IS_OK(status)) { \
1590 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1591 r.in.level, nt_errstr(status), __location__); \
1595 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1596 blob = data_blob_talloc_zero(tctx, needed); \
1597 r.in.buffer = &blob; \
1598 r.in.offered = needed; \
1600 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1601 if (!NT_STATUS_IS_OK(status)) { \
1602 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1603 r.in.level, nt_errstr(status), __location__); \
1607 if (!W_ERROR_IS_OK(r.out.result)) { \
1608 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1609 r.in.level, win_errstr(r.out.result), __location__); \
1615 #define TESTSETCALL_EXP(call, r, err) \
1616 clear_info2(&info_ctr);\
1617 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1618 if (!NT_STATUS_IS_OK(status)) { \
1619 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1620 r.in.info_ctr->level, nt_errstr(status), __location__); \
1624 if (!W_ERROR_IS_OK(err)) { \
1625 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1626 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1627 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1632 if (!W_ERROR_IS_OK(r.out.result)) { \
1633 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1634 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1639 #define TESTSETCALL(call, r) \
1640 TESTSETCALL_EXP(call, r, WERR_OK)
1642 #define STRING_EQUAL(s1, s2, field) \
1643 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1644 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1645 #field, s2, __location__); \
1650 #define MEM_EQUAL(s1, s2, length, field) \
1651 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1652 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1653 #field, (const char *)s2, __location__); \
1658 #define INT_EQUAL(i1, i2, field) \
1660 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1661 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1666 #define SD_EQUAL(sd1, sd2, field) \
1667 if (!security_descriptor_equal(sd1, sd2)) { \
1668 torture_comment(tctx, "Failed to set %s (%s)\n", \
1669 #field, __location__); \
1674 #define TEST_PRINTERINFO_STRING_EXP_ERR(q, s, needed, blob, lvl1, field1, lvl2, field2, value, err) do { \
1676 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1677 q.in.level = lvl1; \
1678 TESTGETCALL(GetPrinter, q, needed, blob) \
1679 info_ctr.level = lvl1; \
1680 p = (void *)&q.out.info->info ## lvl1; \
1681 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
1682 info_ctr.info.info ## lvl1->field1 = value;\
1683 TESTSETCALL_EXP(SetPrinter, s, err) \
1684 info_ctr.info.info ## lvl1->field1 = ""; \
1685 TESTGETCALL(GetPrinter, q, needed, blob) \
1686 info_ctr.info.info ## lvl1->field1 = value; \
1687 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1688 q.in.level = lvl2; \
1689 TESTGETCALL(GetPrinter, q, needed, blob) \
1690 p = (void *)&q.out.info->info ## lvl2; \
1691 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)p; \
1692 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1695 #define TEST_PRINTERINFO_STRING(q, s, needed, blob, lvl1, field1, lvl2, field2, value) do { \
1696 TEST_PRINTERINFO_STRING_EXP_ERR(q, s, needed, blob, lvl1, field1, lvl2, field2, value, WERR_OK); \
1699 #define TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, lvl1, field1, lvl2, field2, value, exp_value) do { \
1701 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1702 q.in.level = lvl1; \
1703 TESTGETCALL(GetPrinter, q, needed, blob) \
1704 info_ctr.level = lvl1; \
1705 p = (void *)&q.out.info->info ## lvl1; \
1706 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
1707 info_ctr.info.info ## lvl1->field1 = value; \
1708 TESTSETCALL(SetPrinter, s) \
1709 info_ctr.info.info ## lvl1->field1 = 0; \
1710 TESTGETCALL(GetPrinter, q, needed, blob) \
1711 p = (void *)&q.out.info->info ## lvl1; \
1712 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
1713 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1714 q.in.level = lvl2; \
1715 TESTGETCALL(GetPrinter, q, needed, blob) \
1716 p = (void *)&q.out.info->info ## lvl2; \
1717 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)p; \
1718 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1721 #define TEST_PRINTERINFO_INT(q, s, needed, blob, lvl1, field1, lvl2, field2, value) do { \
1722 TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, lvl1, field1, lvl2, field2, value, value); \
1726 do { TESTGETCALL(GetPrinter
, q0
, needed
, blob
) } while (0);
1728 TEST_PRINTERINFO_STRING(q
, s
, needed
, blob
, 2, comment
, 1, comment
, "xx2-1 comment");
1729 TEST_PRINTERINFO_STRING(q
, s
, needed
, blob
, 2, comment
, 2, comment
, "xx2-2 comment");
1731 /* level 0 printername does not stick */
1732 /* TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, printername, 0, printername, "xx2-0 printer"); */
1733 TEST_PRINTERINFO_STRING(q
, s
, needed
, blob
, 2, printername
, 1, name
, "xx2-1 printer");
1734 TEST_PRINTERINFO_STRING(q
, s
, needed
, blob
, 2, printername
, 2, printername
, "xx2-2 printer");
1735 TEST_PRINTERINFO_STRING(q
, s
, needed
, blob
, 2, printername
, 4, printername
, "xx2-4 printer");
1736 TEST_PRINTERINFO_STRING(q
, s
, needed
, blob
, 2, printername
, 5, printername
, "xx2-5 printer");
1737 /* TEST_PRINTERINFO_STRING(q, s, needed, blob, 4, printername, 0, printername, "xx4-0 printer"); */
1738 TEST_PRINTERINFO_STRING(q
, s
, needed
, blob
, 4, printername
, 1, name
, "xx4-1 printer");
1739 TEST_PRINTERINFO_STRING(q
, s
, needed
, blob
, 4, printername
, 2, printername
, "xx4-2 printer");
1740 TEST_PRINTERINFO_STRING(q
, s
, needed
, blob
, 4, printername
, 4, printername
, "xx4-4 printer");
1741 TEST_PRINTERINFO_STRING(q
, s
, needed
, blob
, 4, printername
, 5, printername
, "xx4-5 printer");
1742 /* TEST_PRINTERINFO_STRING(q, s, needed, blob, 5, printername, 0, printername, "xx5-0 printer"); */
1743 TEST_PRINTERINFO_STRING(q
, s
, needed
, blob
, 5, printername
, 1, name
, "xx5-1 printer");
1744 TEST_PRINTERINFO_STRING(q
, s
, needed
, blob
, 5, printername
, 2, printername
, "xx5-2 printer");
1745 TEST_PRINTERINFO_STRING(q
, s
, needed
, blob
, 5, printername
, 4, printername
, "xx5-4 printer");
1746 TEST_PRINTERINFO_STRING(q
, s
, needed
, blob
, 5, printername
, 5, printername
, "xx5-5 printer");
1748 /* servername can be set but does not stick
1749 TEST_PRINTERINFO_STRING(q, 2, servername, 0, servername, "xx2-0 servername");
1750 TEST_PRINTERINFO_STRING(q, 2, servername, 2, servername, "xx2-2 servername");
1751 TEST_PRINTERINFO_STRING(q, 2, servername, 4, servername, "xx2-4 servername");
1754 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1755 TEST_PRINTERINFO_STRING_EXP_ERR(q
, s
, needed
, blob
, 2, portname
, 2, portname
, "xx2-2 portname", WERR_UNKNOWN_PORT
);
1756 TEST_PRINTERINFO_STRING_EXP_ERR(q
, s
, needed
, blob
, 2, portname
, 5, portname
, "xx2-5 portname", WERR_UNKNOWN_PORT
);
1757 TEST_PRINTERINFO_STRING_EXP_ERR(q
, s
, needed
, blob
, 5, portname
, 2, portname
, "xx5-2 portname", WERR_UNKNOWN_PORT
);
1758 TEST_PRINTERINFO_STRING_EXP_ERR(q
, s
, needed
, blob
, 5, portname
, 5, portname
, "xx5-5 portname", WERR_UNKNOWN_PORT
);
1760 TEST_PRINTERINFO_STRING(q
, s
, needed
, blob
, 2, sharename
, 2, sharename
, "xx2-2 sharename");
1761 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1762 TEST_PRINTERINFO_STRING_EXP_ERR(q
, s
, needed
, blob
, 2, drivername
, 2, drivername
, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER
);
1763 TEST_PRINTERINFO_STRING(q
, s
, needed
, blob
, 2, location
, 2, location
, "xx2-2 location");
1764 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1765 TEST_PRINTERINFO_STRING_EXP_ERR(q
, s
, needed
, blob
, 2, sepfile
, 2, sepfile
, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE
);
1766 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1767 TEST_PRINTERINFO_STRING_EXP_ERR(q
, s
, needed
, blob
, 2, printprocessor
, 2, printprocessor
, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR
);
1768 TEST_PRINTERINFO_STRING(q
, s
, needed
, blob
, 2, datatype
, 2, datatype
, "xx2-2 datatype");
1769 TEST_PRINTERINFO_STRING(q
, s
, needed
, blob
, 2, parameters
, 2, parameters
, "xx2-2 parameters");
1771 for (i
=0; i
< ARRAY_SIZE(attribute_list
); i
++) {
1772 /* TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 2, attributes, 1, flags,
1774 (attribute_list[i] | default_attribute)
1776 TEST_PRINTERINFO_INT_EXP(q
, s
, needed
, blob
, 2, attributes
, 2, attributes
,
1778 (attribute_list
[i
] | default_attribute
)
1780 TEST_PRINTERINFO_INT_EXP(q
, s
, needed
, blob
, 2, attributes
, 4, attributes
,
1782 (attribute_list
[i
] | default_attribute
)
1784 TEST_PRINTERINFO_INT_EXP(q
, s
, needed
, blob
, 2, attributes
, 5, attributes
,
1786 (attribute_list
[i
] | default_attribute
)
1788 /* TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 4, attributes, 1, flags,
1790 (attribute_list[i] | default_attribute)
1792 TEST_PRINTERINFO_INT_EXP(q
, s
, needed
, blob
, 4, attributes
, 2, attributes
,
1794 (attribute_list
[i
] | default_attribute
)
1796 TEST_PRINTERINFO_INT_EXP(q
, s
, needed
, blob
, 4, attributes
, 4, attributes
,
1798 (attribute_list
[i
] | default_attribute
)
1800 TEST_PRINTERINFO_INT_EXP(q
, s
, needed
, blob
, 4, attributes
, 5, attributes
,
1802 (attribute_list
[i
] | default_attribute
)
1804 /* TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 5, attributes, 1, flags,
1806 (attribute_list[i] | default_attribute)
1808 TEST_PRINTERINFO_INT_EXP(q
, s
, needed
, blob
, 5, attributes
, 2, attributes
,
1810 (attribute_list
[i
] | default_attribute
)
1812 TEST_PRINTERINFO_INT_EXP(q
, s
, needed
, blob
, 5, attributes
, 4, attributes
,
1814 (attribute_list
[i
] | default_attribute
)
1816 TEST_PRINTERINFO_INT_EXP(q
, s
, needed
, blob
, 5, attributes
, 5, attributes
,
1818 (attribute_list
[i
] | default_attribute
)
1822 for (i
=0; i
< ARRAY_SIZE(status_list
); i
++) {
1823 /* level 2 sets do not stick
1824 TEST_PRINTERINFO_INT(q, s, needed, blob, 2, status, 0, status, status_list[i]);
1825 TEST_PRINTERINFO_INT(q, s, needed, blob, 2, status, 2, status, status_list[i]);
1826 TEST_PRINTERINFO_INT(q, s, needed, blob, 2, status, 6, status, status_list[i]); */
1827 TEST_PRINTERINFO_INT(q
, s
, needed
, blob
, 6, status
, 0, status
, status_list
[i
]);
1828 TEST_PRINTERINFO_INT(q
, s
, needed
, blob
, 6, status
, 2, status
, status_list
[i
]);
1829 TEST_PRINTERINFO_INT(q
, s
, needed
, blob
, 6, status
, 6, status
, status_list
[i
]);
1832 /* priorities need to be between 0 and 99
1833 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1834 TEST_PRINTERINFO_INT(q
, s
, needed
, blob
, 2, priority
, 2, priority
, 0);
1835 TEST_PRINTERINFO_INT(q
, s
, needed
, blob
, 2, priority
, 2, priority
, 1);
1836 TEST_PRINTERINFO_INT(q
, s
, needed
, blob
, 2, priority
, 2, priority
, 99);
1837 /* TEST_PRINTERINFO_INT(q, s, needed, blob, 2, priority, 2, priority, 100); */
1838 TEST_PRINTERINFO_INT(q
, s
, needed
, blob
, 2, defaultpriority
,2, defaultpriority
, 0);
1839 TEST_PRINTERINFO_INT(q
, s
, needed
, blob
, 2, defaultpriority
,2, defaultpriority
, 1);
1840 TEST_PRINTERINFO_INT(q
, s
, needed
, blob
, 2, defaultpriority
,2, defaultpriority
, 99);
1841 /* TEST_PRINTERINFO_INT(q, s, needed, blob, 2, defaultpriority,2, defaultpriority, 100); */
1843 TEST_PRINTERINFO_INT(q
, s
, needed
, blob
, 2, starttime
, 2, starttime
, __LINE__
);
1844 TEST_PRINTERINFO_INT(q
, s
, needed
, blob
, 2, untiltime
, 2, untiltime
, __LINE__
);
1847 TEST_PRINTERINFO_INT(q, s, needed, blob, 2, cjobs, 2, cjobs, __LINE__);
1848 TEST_PRINTERINFO_INT(q, s, needed, blob, 2, averageppm, 2, averageppm, __LINE__); */
1851 TEST_PRINTERINFO_INT(q, s, needed, blob, 5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1852 TEST_PRINTERINFO_INT(q, s, needed, blob, 5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1854 /* FIXME: gd also test devmode and secdesc behavior */
1857 /* verify composition of level 1 description field */
1858 const char *description
;
1862 do { TESTGETCALL(GetPrinter
, q0
, needed
, blob
) } while (0);
1864 description
= talloc_strdup(tctx
, q0
.out
.info
->info1
.description
);
1867 do { TESTGETCALL(GetPrinter
, q0
, needed
, blob
) } while (0);
1869 tmp
= talloc_asprintf(tctx
, "%s,%s,%s",
1870 q0
.out
.info
->info2
.printername
,
1871 q0
.out
.info
->info2
.drivername
,
1872 q0
.out
.info
->info2
.location
);
1874 do { STRING_EQUAL(description
, tmp
, "description")} while (0);
1880 static bool test_security_descriptor_equal(struct torture_context
*tctx
,
1881 const struct security_descriptor
*sd1
,
1882 const struct security_descriptor
*sd2
)
1889 torture_comment(tctx
, "%s\n", __location__
);
1893 torture_assert_int_equal(tctx
, sd1
->revision
, sd2
->revision
, "revision mismatch");
1894 torture_assert_int_equal(tctx
, sd1
->type
, sd2
->type
, "type mismatch");
1896 torture_assert_sid_equal(tctx
, sd1
->owner_sid
, sd2
->owner_sid
, "owner mismatch");
1897 torture_assert_sid_equal(tctx
, sd1
->group_sid
, sd2
->group_sid
, "group mismatch");
1899 if (!security_acl_equal(sd1
->sacl
, sd2
->sacl
)) {
1900 torture_comment(tctx
, "%s: sacl mismatch\n", __location__
);
1901 NDR_PRINT_DEBUG(security_acl
, sd1
->sacl
);
1902 NDR_PRINT_DEBUG(security_acl
, sd2
->sacl
);
1905 if (!security_acl_equal(sd1
->dacl
, sd2
->dacl
)) {
1906 torture_comment(tctx
, "%s: dacl mismatch\n", __location__
);
1907 NDR_PRINT_DEBUG(security_acl
, sd1
->dacl
);
1908 NDR_PRINT_DEBUG(security_acl
, sd2
->dacl
);
1915 static bool test_sd_set_level(struct torture_context
*tctx
,
1916 struct dcerpc_binding_handle
*b
,
1917 struct policy_handle
*handle
,
1919 struct security_descriptor
*sd
)
1921 struct spoolss_SetPrinterInfoCtr info_ctr
;
1922 struct spoolss_DevmodeContainer devmode_ctr
;
1923 struct sec_desc_buf secdesc_ctr
;
1924 union spoolss_SetPrinterInfo sinfo
;
1925 union spoolss_PrinterInfo info
;
1926 struct spoolss_SetPrinterInfo3 info3
;
1928 ZERO_STRUCT(devmode_ctr
);
1929 ZERO_STRUCT(secdesc_ctr
);
1933 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
1934 torture_assert(tctx
, PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
1937 info_ctr
.info
= sinfo
;
1943 info3
.sec_desc_ptr
= 0;
1946 info_ctr
.info
.info3
= &info3
;
1954 secdesc_ctr
.sd
= sd
;
1956 torture_assert(tctx
,
1957 test_SetPrinter(tctx
, b
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0), "");
1962 static bool test_PrinterInfo_SDs(struct torture_context
*tctx
,
1963 struct dcerpc_binding_handle
*b
,
1964 struct policy_handle
*handle
)
1966 union spoolss_PrinterInfo info
;
1967 struct security_descriptor
*sd1
, *sd2
;
1970 /* just compare level 2 and level 3 */
1972 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
1974 sd1
= info
.info2
.secdesc
;
1976 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 3, &info
), "");
1978 sd2
= info
.info3
.secdesc
;
1980 torture_assert(tctx
, test_security_descriptor_equal(tctx
, sd1
, sd2
),
1981 "SD level 2 != SD level 3");
1984 /* query level 2, set level 2, query level 2 */
1986 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
1988 sd1
= info
.info2
.secdesc
;
1990 torture_assert(tctx
, test_sd_set_level(tctx
, b
, handle
, 2, sd1
), "");
1992 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
1994 sd2
= info
.info2
.secdesc
;
1995 if (sd1
->type
& SEC_DESC_DACL_DEFAULTED
) {
1996 torture_comment(tctx
, "removing SEC_DESC_DACL_DEFAULTED\n");
1997 sd1
->type
&= ~SEC_DESC_DACL_DEFAULTED
;
2000 torture_assert(tctx
, test_security_descriptor_equal(tctx
, sd1
, sd2
),
2001 "SD level 2 != SD level 2 after SD has been set via level 2");
2004 /* query level 2, set level 3, query level 2 */
2006 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
2008 sd1
= info
.info2
.secdesc
;
2010 torture_assert(tctx
, test_sd_set_level(tctx
, b
, handle
, 3, sd1
), "");
2012 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
2014 sd2
= info
.info2
.secdesc
;
2016 torture_assert(tctx
, test_security_descriptor_equal(tctx
, sd1
, sd2
),
2017 "SD level 2 != SD level 2 after SD has been set via level 3");
2019 /* set modified sd level 3, query level 2 */
2021 for (i
=0; i
< 93; i
++) {
2022 struct security_ace a
= {};
2023 const char *sid_string
= talloc_asprintf(tctx
, "S-1-5-32-9999%i", i
);
2024 a
.type
= SEC_ACE_TYPE_ACCESS_ALLOWED
;
2026 a
.size
= 0; /* autogenerated */
2028 a
.trustee
= *dom_sid_parse_talloc(tctx
, sid_string
);
2029 torture_assert_ntstatus_ok(tctx
, security_descriptor_dacl_add(sd1
, &a
), "");
2032 torture_assert(tctx
, test_sd_set_level(tctx
, b
, handle
, 3, sd1
), "");
2034 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
2035 sd2
= info
.info2
.secdesc
;
2037 if (sd1
->type
& SEC_DESC_DACL_DEFAULTED
) {
2038 torture_comment(tctx
, "removing SEC_DESC_DACL_DEFAULTED\n");
2039 sd1
->type
&= ~SEC_DESC_DACL_DEFAULTED
;
2042 torture_assert(tctx
, test_security_descriptor_equal(tctx
, sd1
, sd2
),
2043 "modified SD level 2 != SD level 2 after SD has been set via level 3");
2050 * wrapper call that saves original sd, runs tests, and restores sd
2053 static bool test_PrinterInfo_SD(struct torture_context
*tctx
,
2054 struct dcerpc_binding_handle
*b
,
2055 struct policy_handle
*handle
)
2057 union spoolss_PrinterInfo info
;
2058 struct security_descriptor
*sd
;
2061 torture_comment(tctx
, "Testing Printer Security Descriptors\n");
2063 /* save original sd */
2065 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
2066 "failed to get initial security descriptor");
2068 sd
= security_descriptor_copy(tctx
, info
.info2
.secdesc
);
2072 ret
= test_PrinterInfo_SDs(tctx
, b
, handle
);
2074 /* restore original sd */
2076 torture_assert(tctx
, test_sd_set_level(tctx
, b
, handle
, 3, sd
),
2077 "failed to restore initial security descriptor");
2079 torture_comment(tctx
, "Printer Security Descriptors test %s\n\n",
2080 ret
? "succeeded" : "failed");
2086 static bool test_devmode_set_level(struct torture_context
*tctx
,
2087 struct dcerpc_binding_handle
*b
,
2088 struct policy_handle
*handle
,
2090 struct spoolss_DeviceMode
*devmode
)
2092 struct spoolss_SetPrinterInfo8 info8
;
2093 struct spoolss_SetPrinterInfoCtr info_ctr
;
2094 struct spoolss_DevmodeContainer devmode_ctr
;
2095 struct sec_desc_buf secdesc_ctr
;
2096 union spoolss_SetPrinterInfo sinfo
;
2098 ZERO_STRUCT(devmode_ctr
);
2099 ZERO_STRUCT(secdesc_ctr
);
2103 union spoolss_PrinterInfo info
;
2104 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
2105 torture_assert(tctx
, PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
2108 info_ctr
.info
= sinfo
;
2113 info8
.devmode_ptr
= 0;
2116 info_ctr
.info
.info8
= &info8
;
2124 devmode_ctr
.devmode
= devmode
;
2126 torture_assert(tctx
,
2127 test_SetPrinter(tctx
, b
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0), "");
2133 static bool test_devicemode_equal(struct torture_context
*tctx
,
2134 const struct spoolss_DeviceMode
*d1
,
2135 const struct spoolss_DeviceMode
*d2
)
2142 torture_comment(tctx
, "%s\n", __location__
);
2145 torture_assert_str_equal(tctx
, d1
->devicename
, d2
->devicename
, "devicename mismatch");
2146 torture_assert_int_equal(tctx
, d1
->specversion
, d2
->specversion
, "specversion mismatch");
2147 torture_assert_int_equal(tctx
, d1
->driverversion
, d2
->driverversion
, "driverversion mismatch");
2148 torture_assert_int_equal(tctx
, d1
->size
, d2
->size
, "size mismatch");
2149 torture_assert_int_equal(tctx
, d1
->__driverextra_length
, d2
->__driverextra_length
, "__driverextra_length mismatch");
2150 torture_assert_int_equal(tctx
, d1
->fields
, d2
->fields
, "fields mismatch");
2151 torture_assert_int_equal(tctx
, d1
->orientation
, d2
->orientation
, "orientation mismatch");
2152 torture_assert_int_equal(tctx
, d1
->papersize
, d2
->papersize
, "papersize mismatch");
2153 torture_assert_int_equal(tctx
, d1
->paperlength
, d2
->paperlength
, "paperlength mismatch");
2154 torture_assert_int_equal(tctx
, d1
->paperwidth
, d2
->paperwidth
, "paperwidth mismatch");
2155 torture_assert_int_equal(tctx
, d1
->scale
, d2
->scale
, "scale mismatch");
2156 torture_assert_int_equal(tctx
, d1
->copies
, d2
->copies
, "copies mismatch");
2157 torture_assert_int_equal(tctx
, d1
->defaultsource
, d2
->defaultsource
, "defaultsource mismatch");
2158 torture_assert_int_equal(tctx
, d1
->printquality
, d2
->printquality
, "printquality mismatch");
2159 torture_assert_int_equal(tctx
, d1
->color
, d2
->color
, "color mismatch");
2160 torture_assert_int_equal(tctx
, d1
->duplex
, d2
->duplex
, "duplex mismatch");
2161 torture_assert_int_equal(tctx
, d1
->yresolution
, d2
->yresolution
, "yresolution mismatch");
2162 torture_assert_int_equal(tctx
, d1
->ttoption
, d2
->ttoption
, "ttoption mismatch");
2163 torture_assert_int_equal(tctx
, d1
->collate
, d2
->collate
, "collate mismatch");
2164 torture_assert_str_equal(tctx
, d1
->formname
, d2
->formname
, "formname mismatch");
2165 torture_assert_int_equal(tctx
, d1
->logpixels
, d2
->logpixels
, "logpixels mismatch");
2166 torture_assert_int_equal(tctx
, d1
->bitsperpel
, d2
->bitsperpel
, "bitsperpel mismatch");
2167 torture_assert_int_equal(tctx
, d1
->pelswidth
, d2
->pelswidth
, "pelswidth mismatch");
2168 torture_assert_int_equal(tctx
, d1
->pelsheight
, d2
->pelsheight
, "pelsheight mismatch");
2169 torture_assert_int_equal(tctx
, d1
->displayflags
, d2
->displayflags
, "displayflags mismatch");
2170 torture_assert_int_equal(tctx
, d1
->displayfrequency
, d2
->displayfrequency
, "displayfrequency mismatch");
2171 torture_assert_int_equal(tctx
, d1
->icmmethod
, d2
->icmmethod
, "icmmethod mismatch");
2172 torture_assert_int_equal(tctx
, d1
->icmintent
, d2
->icmintent
, "icmintent mismatch");
2173 torture_assert_int_equal(tctx
, d1
->mediatype
, d2
->mediatype
, "mediatype mismatch");
2174 torture_assert_int_equal(tctx
, d1
->dithertype
, d2
->dithertype
, "dithertype mismatch");
2175 torture_assert_int_equal(tctx
, d1
->reserved1
, d2
->reserved1
, "reserved1 mismatch");
2176 torture_assert_int_equal(tctx
, d1
->reserved2
, d2
->reserved2
, "reserved2 mismatch");
2177 torture_assert_int_equal(tctx
, d1
->panningwidth
, d2
->panningwidth
, "panningwidth mismatch");
2178 torture_assert_int_equal(tctx
, d1
->panningheight
, d2
->panningheight
, "panningheight mismatch");
2179 torture_assert_data_blob_equal(tctx
, d1
->driverextra_data
, d2
->driverextra_data
, "driverextra_data mismatch");
2184 static bool test_devicemode_full(struct torture_context
*tctx
,
2185 struct dcerpc_binding_handle
*b
,
2186 struct policy_handle
*handle
)
2188 struct spoolss_SetPrinter s
;
2189 struct spoolss_GetPrinter q
;
2190 struct spoolss_SetPrinterInfoCtr info_ctr
;
2191 struct spoolss_SetPrinterInfo8 info8
;
2192 union spoolss_PrinterInfo info
;
2193 struct spoolss_DevmodeContainer devmode_ctr
;
2194 struct sec_desc_buf secdesc_ctr
;
2195 uint32_t needed
= 0;
2196 DATA_BLOB blob
= data_blob_null
;
2200 #define TEST_DEVMODE_INT_EXP_RESULT(q, s, needed, blob, lvl1, field1, lvl2, field2, value, exp_value, expected_result) do { \
2201 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2202 q.in.level = lvl1; \
2203 TESTGETCALL(GetPrinter, q, needed, blob) \
2204 info_ctr.level = lvl1; \
2206 void *p = (void *)&q.out.info->info ## lvl1; \
2207 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
2208 } else if (lvl1 == 8) {\
2209 info_ctr.info.info ## lvl1 = &info8; \
2211 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2212 devmode_ctr.devmode->field1 = value; \
2213 TESTSETCALL_EXP(SetPrinter, s, expected_result) \
2214 if (W_ERROR_IS_OK(expected_result)) { \
2215 TESTGETCALL(GetPrinter, q, needed, blob) \
2216 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2217 q.in.level = lvl2; \
2218 TESTGETCALL(GetPrinter, q, needed, blob) \
2219 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2223 #define TEST_DEVMODE_INT_EXP(q, s, needed, blob, lvl1, field1, lvl2, field2, value, expected_result) do { \
2224 TEST_DEVMODE_INT_EXP_RESULT(q, s, needed, blob, lvl1, field1, lvl2, field2, value, value, expected_result); \
2227 #define TEST_DEVMODE_INT(q, s, needed, blob, lvl1, field1, lvl2, field2, value) do { \
2228 TEST_DEVMODE_INT_EXP_RESULT(q, s, needed, blob, lvl1, field1, lvl2, field2, value, value, WERR_OK); \
2231 ZERO_STRUCT(devmode_ctr
);
2232 ZERO_STRUCT(secdesc_ctr
);
2235 s
.in
.handle
= handle
;
2237 s
.in
.info_ctr
= &info_ctr
;
2238 s
.in
.devmode_ctr
= &devmode_ctr
;
2239 s
.in
.secdesc_ctr
= &secdesc_ctr
;
2241 q
.in
.handle
= handle
;
2245 const char *devicename
;/* [charset(UTF16)] */
2246 enum spoolss_DeviceModeSpecVersion specversion
;
2247 uint16_t driverversion
;
2248 uint16_t __driverextra_length
;/* [value(r->driverextra_data.length)] */
2251 TEST_DEVMODE_INT_EXP(q
, s
, needed
, blob
, 8, size
, 8, size
, __LINE__
, WERR_INVALID_PARAMETER
);
2252 TEST_DEVMODE_INT_EXP(q
, s
, needed
, blob
, 8, size
, 8, size
, 0, WERR_INVALID_PARAMETER
);
2253 TEST_DEVMODE_INT_EXP(q
, s
, needed
, blob
, 8, size
, 8, size
, 0xffff, WERR_INVALID_PARAMETER
);
2254 TEST_DEVMODE_INT_EXP(q
, s
, needed
, blob
, 8, size
, 8, size
, ndr_size_spoolss_DeviceMode(devmode_ctr
.devmode
, 0), (devmode_ctr
.devmode
->__driverextra_length
> 0 ) ? WERR_INVALID_PARAMETER
: WERR_OK
);
2255 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, size
, 8, size
, ndr_size_spoolss_DeviceMode(devmode_ctr
.devmode
, 0) - devmode_ctr
.devmode
->__driverextra_length
);
2257 devmode_ctr
.devmode
->driverextra_data
= data_blob_string_const("foobar");
2258 torture_assert(tctx
,
2259 test_devmode_set_level(tctx
, b
, handle
, 8, devmode_ctr
.devmode
),
2260 "failed to set devmode");
2262 TEST_DEVMODE_INT_EXP(q
, s
, needed
, blob
, 8, size
, 8, size
, ndr_size_spoolss_DeviceMode(devmode_ctr
.devmode
, 0), (devmode_ctr
.devmode
->__driverextra_length
> 0 ) ? WERR_INVALID_PARAMETER
: WERR_OK
);
2263 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, size
, 8, size
, ndr_size_spoolss_DeviceMode(devmode_ctr
.devmode
, 0) - devmode_ctr
.devmode
->__driverextra_length
);
2265 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, orientation
, 8, orientation
, __LINE__
);
2266 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, papersize
, 8, papersize
, __LINE__
);
2267 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, paperlength
, 8, paperlength
, __LINE__
);
2268 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, paperwidth
, 8, paperwidth
, __LINE__
);
2269 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, scale
, 8, scale
, __LINE__
);
2270 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, copies
, 8, copies
, __LINE__
);
2271 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, defaultsource
, 8, defaultsource
, __LINE__
);
2272 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, printquality
, 8, printquality
, __LINE__
);
2273 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, color
, 8, color
, __LINE__
);
2274 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, duplex
, 8, duplex
, __LINE__
);
2275 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, yresolution
, 8, yresolution
, __LINE__
);
2276 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, ttoption
, 8, ttoption
, __LINE__
);
2277 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, collate
, 8, collate
, __LINE__
);
2279 const char *formname
;/* [charset(UTF16)] */
2281 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, logpixels
, 8, logpixels
, __LINE__
);
2282 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, bitsperpel
, 8, bitsperpel
, __LINE__
);
2283 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, pelswidth
, 8, pelswidth
, __LINE__
);
2284 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, pelsheight
, 8, pelsheight
, __LINE__
);
2285 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, displayflags
, 8, displayflags
, __LINE__
);
2286 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, displayfrequency
, 8, displayfrequency
, __LINE__
);
2287 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, icmmethod
, 8, icmmethod
, __LINE__
);
2288 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, icmintent
, 8, icmintent
, __LINE__
);
2289 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, mediatype
, 8, mediatype
, __LINE__
);
2290 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, dithertype
, 8, dithertype
, __LINE__
);
2291 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, reserved1
, 8, reserved1
, __LINE__
);
2292 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, reserved2
, 8, reserved2
, __LINE__
);
2293 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, panningwidth
, 8, panningwidth
, __LINE__
);
2294 TEST_DEVMODE_INT(q
, s
, needed
, blob
, 8, panningheight
, 8, panningheight
, __LINE__
);
2299 static bool call_OpenPrinterEx(struct torture_context
*tctx
,
2300 struct dcerpc_pipe
*p
,
2302 struct spoolss_DeviceMode
*devmode
,
2303 struct policy_handle
*handle
);
2305 static bool test_PrinterInfo_DevModes(struct torture_context
*tctx
,
2306 struct dcerpc_pipe
*p
,
2307 struct policy_handle
*handle
,
2310 union spoolss_PrinterInfo info
;
2311 struct spoolss_DeviceMode
*devmode
;
2312 struct spoolss_DeviceMode
*devmode2
;
2313 struct policy_handle handle_devmode
;
2314 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
2316 /* simply compare level8 and level2 devmode */
2318 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 8, &info
), "");
2320 devmode
= info
.info8
.devmode
;
2322 if (devmode
&& devmode
->size
== 0) {
2324 "devmode of zero size!");
2327 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
2329 devmode2
= info
.info2
.devmode
;
2331 if (devmode2
&& devmode2
->size
== 0) {
2333 "devmode of zero size!");
2336 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2337 "DM level 8 != DM level 2");
2340 /* set devicemode level 8 and see if it persists */
2342 devmode
->copies
= 93;
2343 devmode
->formname
= talloc_strdup(tctx
, "Legal");
2345 torture_assert(tctx
, test_devmode_set_level(tctx
, b
, handle
, 8, devmode
), "");
2347 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 8, &info
), "");
2349 devmode2
= info
.info8
.devmode
;
2351 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2352 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2354 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
2356 devmode2
= info
.info2
.devmode
;
2358 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2359 "modified DM level 8 != DM level 2");
2362 /* set devicemode level 2 and see if it persists */
2364 devmode
->copies
= 39;
2365 devmode
->formname
= talloc_strdup(tctx
, "Executive");
2367 torture_assert(tctx
, test_devmode_set_level(tctx
, b
, handle
, 2, devmode
), "");
2369 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 8, &info
), "");
2371 devmode2
= info
.info8
.devmode
;
2373 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2374 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2376 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
2378 devmode2
= info
.info2
.devmode
;
2380 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2381 "modified DM level 8 != DM level 2");
2384 /* check every single bit in public part of devicemode */
2386 torture_assert(tctx
, test_devicemode_full(tctx
, b
, handle
),
2387 "failed to set every single devicemode component");
2390 /* change formname upon open and see if it persists in getprinter calls */
2392 devmode
->formname
= talloc_strdup(tctx
, "A4");
2393 devmode
->copies
= 42;
2395 torture_assert(tctx
, call_OpenPrinterEx(tctx
, p
, name
, devmode
, &handle_devmode
),
2396 "failed to open printer handle");
2398 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, &handle_devmode
, 8, &info
), "");
2400 devmode2
= info
.info8
.devmode
;
2402 if (strequal(devmode
->devicename
, devmode2
->devicename
)) {
2403 torture_warning(tctx
, "devicenames are the same\n");
2405 torture_comment(tctx
, "devicename passed in for open: %s\n", devmode
->devicename
);
2406 torture_comment(tctx
, "devicename after level 8 get: %s\n", devmode2
->devicename
);
2409 if (strequal(devmode
->formname
, devmode2
->formname
)) {
2410 torture_warning(tctx
, "formname are the same\n");
2412 torture_comment(tctx
, "formname passed in for open: %s\n", devmode
->formname
);
2413 torture_comment(tctx
, "formname after level 8 get: %s\n", devmode2
->formname
);
2416 if (devmode
->copies
== devmode2
->copies
) {
2417 torture_warning(tctx
, "copies are the same\n");
2419 torture_comment(tctx
, "copies passed in for open: %d\n", devmode
->copies
);
2420 torture_comment(tctx
, "copies after level 8 get: %d\n", devmode2
->copies
);
2423 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, &handle_devmode
, 2, &info
), "");
2425 devmode2
= info
.info2
.devmode
;
2427 if (strequal(devmode
->devicename
, devmode2
->devicename
)) {
2428 torture_warning(tctx
, "devicenames are the same\n");
2430 torture_comment(tctx
, "devicename passed in for open: %s\n", devmode
->devicename
);
2431 torture_comment(tctx
, "devicename after level 2 get: %s\n", devmode2
->devicename
);
2434 if (strequal(devmode
->formname
, devmode2
->formname
)) {
2435 torture_warning(tctx
, "formname is the same\n");
2437 torture_comment(tctx
, "formname passed in for open: %s\n", devmode
->formname
);
2438 torture_comment(tctx
, "formname after level 2 get: %s\n", devmode2
->formname
);
2441 if (devmode
->copies
== devmode2
->copies
) {
2442 torture_warning(tctx
, "copies are the same\n");
2444 torture_comment(tctx
, "copies passed in for open: %d\n", devmode
->copies
);
2445 torture_comment(tctx
, "copies after level 2 get: %d\n", devmode2
->copies
);
2448 test_ClosePrinter(tctx
, b
, &handle_devmode
);
2454 * wrapper call that saves original devmode, runs tests, and restores devmode
2457 static bool test_PrinterInfo_DevMode(struct torture_context
*tctx
,
2458 struct dcerpc_pipe
*p
,
2459 struct policy_handle
*handle
,
2461 struct spoolss_DeviceMode
*addprinter_devmode
)
2463 union spoolss_PrinterInfo info
;
2464 struct spoolss_DeviceMode
*devmode
;
2466 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
2468 torture_comment(tctx
, "Testing Printer Devicemodes\n");
2470 /* save original devmode */
2472 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 8, &info
),
2473 "failed to get initial global devicemode");
2475 devmode
= info
.info8
.devmode
;
2477 if (devmode
&& devmode
->size
== 0) {
2479 "devmode of zero size!");
2482 if (addprinter_devmode
) {
2483 if (!test_devicemode_equal(tctx
, devmode
, addprinter_devmode
)) {
2484 torture_warning(tctx
, "current global DM is != DM provided in addprinter");
2490 ret
= test_PrinterInfo_DevModes(tctx
, p
, handle
, name
);
2492 /* restore original devmode */
2494 torture_assert(tctx
, test_devmode_set_level(tctx
, b
, handle
, 8, devmode
),
2495 "failed to restore initial global device mode");
2497 torture_comment(tctx
, "Printer Devicemodes test %s\n\n",
2498 ret
? "succeeded" : "failed");
2504 bool test_ClosePrinter(struct torture_context
*tctx
,
2505 struct dcerpc_binding_handle
*b
,
2506 struct policy_handle
*handle
)
2509 struct spoolss_ClosePrinter r
;
2511 r
.in
.handle
= handle
;
2512 r
.out
.handle
= handle
;
2514 torture_comment(tctx
, "Testing ClosePrinter\n");
2516 status
= dcerpc_spoolss_ClosePrinter_r(b
, tctx
, &r
);
2517 torture_assert_ntstatus_ok(tctx
, status
, "ClosePrinter failed");
2518 torture_assert_werr_ok(tctx
, r
.out
.result
, "ClosePrinter failed");
2523 static bool test_GetForm_args(struct torture_context
*tctx
,
2524 struct dcerpc_binding_handle
*b
,
2525 struct policy_handle
*handle
,
2526 const char *form_name
,
2528 union spoolss_FormInfo
*info_p
)
2531 struct spoolss_GetForm r
;
2534 r
.in
.handle
= handle
;
2535 r
.in
.form_name
= form_name
;
2539 r
.out
.needed
= &needed
;
2541 torture_comment(tctx
, "Testing GetForm(%s) level %d\n", form_name
, r
.in
.level
);
2543 status
= dcerpc_spoolss_GetForm_r(b
, tctx
, &r
);
2544 torture_assert_ntstatus_ok(tctx
, status
, "GetForm failed");
2546 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2547 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
2548 r
.in
.buffer
= &blob
;
2549 r
.in
.offered
= needed
;
2550 status
= dcerpc_spoolss_GetForm_r(b
, tctx
, &r
);
2551 torture_assert_ntstatus_ok(tctx
, status
, "GetForm failed");
2553 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetForm failed");
2555 torture_assert(tctx
, r
.out
.info
, "No form info returned");
2558 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetForm failed");
2560 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo
, r
.out
.info
, r
.in
.level
, needed
, 4);
2563 *info_p
= *r
.out
.info
;
2569 static bool test_GetForm(struct torture_context
*tctx
,
2570 struct dcerpc_binding_handle
*b
,
2571 struct policy_handle
*handle
,
2572 const char *form_name
,
2575 return test_GetForm_args(tctx
, b
, handle
, form_name
, level
, NULL
);
2578 static bool test_EnumForms(struct torture_context
*tctx
,
2579 struct dcerpc_binding_handle
*b
,
2580 struct policy_handle
*handle
,
2584 union spoolss_FormInfo
**info_p
)
2586 struct spoolss_EnumForms r
;
2589 union spoolss_FormInfo
*info
;
2591 r
.in
.handle
= handle
;
2595 r
.out
.needed
= &needed
;
2596 r
.out
.count
= &count
;
2599 torture_comment(tctx
, "Testing EnumForms level %d\n", r
.in
.level
);
2601 torture_assert_ntstatus_ok(tctx
,
2602 dcerpc_spoolss_EnumForms_r(b
, tctx
, &r
),
2603 "EnumForms failed");
2605 if ((r
.in
.level
== 2) && (W_ERROR_EQUAL(r
.out
.result
, WERR_INVALID_LEVEL
))) {
2606 torture_skip(tctx
, "EnumForms level 2 not supported");
2609 if (print_server
&& W_ERROR_EQUAL(r
.out
.result
, WERR_INVALID_HANDLE
)) {
2610 torture_fail(tctx
, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2613 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2614 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
2615 r
.in
.buffer
= &blob
;
2616 r
.in
.offered
= needed
;
2618 torture_assert_ntstatus_ok(tctx
,
2619 dcerpc_spoolss_EnumForms_r(b
, tctx
, &r
),
2620 "EnumForms failed");
2622 torture_assert(tctx
, info
, "No forms returned");
2625 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumForms failed");
2627 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms
, info
, r
.in
.level
, count
, needed
, 4);
2639 static bool test_EnumForms_all(struct torture_context
*tctx
,
2640 struct dcerpc_binding_handle
*b
,
2641 struct policy_handle
*handle
,
2644 uint32_t levels
[] = { 1, 2 };
2647 for (i
=0; i
<ARRAY_SIZE(levels
); i
++) {
2650 union spoolss_FormInfo
*info
= NULL
;
2652 torture_assert(tctx
,
2653 test_EnumForms(tctx
, b
, handle
, print_server
, levels
[i
], &count
, &info
),
2654 "failed to enum forms");
2656 for (j
= 0; j
< count
; j
++) {
2657 if (!print_server
) {
2658 torture_assert(tctx
,
2659 test_GetForm(tctx
, b
, handle
, info
[j
].info1
.form_name
, levels
[i
]),
2660 "failed to get form");
2668 static bool test_EnumForms_find_one(struct torture_context
*tctx
,
2669 struct dcerpc_binding_handle
*b
,
2670 struct policy_handle
*handle
,
2672 const char *form_name
)
2674 union spoolss_FormInfo
*info
= NULL
;
2679 torture_assert(tctx
,
2680 test_EnumForms(tctx
, b
, handle
, print_server
, 1, &count
, &info
),
2681 "failed to enumerate forms");
2683 for (i
=0; i
<count
; i
++) {
2684 if (strequal(form_name
, info
[i
].info1
.form_name
)) {
2693 static bool test_DeleteForm(struct torture_context
*tctx
,
2694 struct dcerpc_binding_handle
*b
,
2695 struct policy_handle
*handle
,
2696 const char *form_name
,
2697 WERROR expected_result
)
2699 struct spoolss_DeleteForm r
;
2701 r
.in
.handle
= handle
;
2702 r
.in
.form_name
= form_name
;
2704 torture_comment(tctx
, "Testing DeleteForm(%s)\n", form_name
);
2706 torture_assert_ntstatus_ok(tctx
,
2707 dcerpc_spoolss_DeleteForm_r(b
, tctx
, &r
),
2708 "DeleteForm failed");
2709 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
2710 "DeleteForm gave unexpected result");
2711 if (W_ERROR_IS_OK(r
.out
.result
)) {
2712 torture_assert_ntstatus_ok(tctx
,
2713 dcerpc_spoolss_DeleteForm_r(b
, tctx
, &r
),
2714 "2nd DeleteForm failed");
2715 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_FORM_NAME
,
2716 "2nd DeleteForm failed");
2722 static bool test_AddForm(struct torture_context
*tctx
,
2723 struct dcerpc_binding_handle
*b
,
2724 struct policy_handle
*handle
,
2726 union spoolss_AddFormInfo
*info
,
2727 WERROR expected_result
)
2729 struct spoolss_AddForm r
;
2730 struct spoolss_AddFormInfoCtr info_ctr
;
2732 info_ctr
.level
= level
;
2733 info_ctr
.info
= *info
;
2736 torture_skip(tctx
, "only level 1 supported");
2739 r
.in
.handle
= handle
;
2740 r
.in
.info_ctr
= &info_ctr
;
2742 torture_comment(tctx
, "Testing AddForm(%s) level %d, type %d\n",
2743 r
.in
.info_ctr
->info
.info1
->form_name
, level
,
2744 r
.in
.info_ctr
->info
.info1
->flags
);
2746 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_AddForm_r(b
, tctx
, &r
),
2748 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
2749 "AddForm gave unexpected result");
2751 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_AddForm_r(b
, tctx
, &r
),
2752 "2nd AddForm failed");
2753 if (W_ERROR_EQUAL(expected_result
, WERR_INVALID_PARAMETER
)) {
2754 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAMETER
,
2755 "2nd AddForm gave unexpected result");
2757 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_FILE_EXISTS
,
2758 "2nd AddForm gave unexpected result");
2764 static bool test_SetForm(struct torture_context
*tctx
,
2765 struct dcerpc_binding_handle
*b
,
2766 struct policy_handle
*handle
,
2767 const char *form_name
,
2769 union spoolss_AddFormInfo
*info
)
2771 struct spoolss_SetForm r
;
2772 struct spoolss_AddFormInfoCtr info_ctr
;
2774 info_ctr
.level
= level
;
2775 info_ctr
.info
= *info
;
2777 r
.in
.handle
= handle
;
2778 r
.in
.form_name
= form_name
;
2779 r
.in
.info_ctr
= &info_ctr
;
2781 torture_comment(tctx
, "Testing SetForm(%s) level %d\n",
2784 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetForm_r(b
, tctx
, &r
),
2787 torture_assert_werr_ok(tctx
, r
.out
.result
,
2793 static bool test_GetForm_winreg(struct torture_context
*tctx
,
2794 struct dcerpc_binding_handle
*b
,
2795 struct policy_handle
*handle
,
2796 const char *key_name
,
2797 const char *form_name
,
2798 enum winreg_Type
*w_type
,
2803 static bool test_Forms_args(struct torture_context
*tctx
,
2804 struct dcerpc_binding_handle
*b
,
2805 struct policy_handle
*handle
,
2807 const char *printer_name
,
2808 struct dcerpc_binding_handle
*winreg_handle
,
2809 struct policy_handle
*hive_handle
,
2810 const char *form_name
,
2811 struct spoolss_AddFormInfo1
*info1
,
2812 WERROR expected_add_result
,
2813 WERROR expected_delete_result
)
2815 union spoolss_FormInfo info
;
2816 union spoolss_AddFormInfo add_info
;
2818 enum winreg_Type w_type
;
2823 add_info
.info1
= info1
;
2825 torture_assert(tctx
,
2826 test_AddForm(tctx
, b
, handle
, 1, &add_info
, expected_add_result
),
2827 "failed to add form");
2829 if (winreg_handle
&& hive_handle
&& W_ERROR_IS_OK(expected_add_result
)) {
2831 struct spoolss_FormInfo1 i1
;
2833 torture_assert(tctx
,
2834 test_GetForm_winreg(tctx
, winreg_handle
, hive_handle
, TOP_LEVEL_CONTROL_FORMS_KEY
, form_name
, &w_type
, &w_size
, &w_length
, &w_data
),
2835 "failed to get form via winreg");
2837 i1
.size
.width
= IVAL(w_data
, 0);
2838 i1
.size
.height
= IVAL(w_data
, 4);
2839 i1
.area
.left
= IVAL(w_data
, 8);
2840 i1
.area
.top
= IVAL(w_data
, 12);
2841 i1
.area
.right
= IVAL(w_data
, 16);
2842 i1
.area
.bottom
= IVAL(w_data
, 20);
2843 /* skip index here */
2844 i1
.flags
= IVAL(w_data
, 28);
2846 torture_assert_int_equal(tctx
, w_type
, REG_BINARY
, "unexpected type");
2847 torture_assert_int_equal(tctx
, w_size
, 0x20, "unexpected size");
2848 torture_assert_int_equal(tctx
, w_length
, 0x20, "unexpected length");
2849 torture_assert_int_equal(tctx
, i1
.size
.width
, add_info
.info1
->size
.width
, "width mismatch");
2850 torture_assert_int_equal(tctx
, i1
.size
.height
, add_info
.info1
->size
.height
, "height mismatch");
2851 torture_assert_int_equal(tctx
, i1
.area
.left
, add_info
.info1
->area
.left
, "left mismatch");
2852 torture_assert_int_equal(tctx
, i1
.area
.top
, add_info
.info1
->area
.top
, "top mismatch");
2853 torture_assert_int_equal(tctx
, i1
.area
.right
, add_info
.info1
->area
.right
, "right mismatch");
2854 torture_assert_int_equal(tctx
, i1
.area
.bottom
, add_info
.info1
->area
.bottom
, "bottom mismatch");
2855 torture_assert_int_equal(tctx
, i1
.flags
, add_info
.info1
->flags
, "flags mismatch");
2858 if (!print_server
&& W_ERROR_IS_OK(expected_add_result
)) {
2859 torture_assert(tctx
,
2860 test_GetForm_args(tctx
, b
, handle
, form_name
, 1, &info
),
2861 "failed to get added form");
2863 torture_assert_int_equal(tctx
, info
.info1
.size
.width
, add_info
.info1
->size
.width
, "width mismatch");
2864 torture_assert_int_equal(tctx
, info
.info1
.size
.height
, add_info
.info1
->size
.height
, "height mismatch");
2865 torture_assert_int_equal(tctx
, info
.info1
.area
.left
, add_info
.info1
->area
.left
, "left mismatch");
2866 torture_assert_int_equal(tctx
, info
.info1
.area
.top
, add_info
.info1
->area
.top
, "top mismatch");
2867 torture_assert_int_equal(tctx
, info
.info1
.area
.right
, add_info
.info1
->area
.right
, "right mismatch");
2868 torture_assert_int_equal(tctx
, info
.info1
.area
.bottom
, add_info
.info1
->area
.bottom
, "bottom mismatch");
2869 torture_assert_int_equal(tctx
, info
.info1
.flags
, add_info
.info1
->flags
, "flags mismatch");
2871 if (winreg_handle
&& hive_handle
) {
2873 struct spoolss_FormInfo1 i1
;
2875 i1
.size
.width
= IVAL(w_data
, 0);
2876 i1
.size
.height
= IVAL(w_data
, 4);
2877 i1
.area
.left
= IVAL(w_data
, 8);
2878 i1
.area
.top
= IVAL(w_data
, 12);
2879 i1
.area
.right
= IVAL(w_data
, 16);
2880 i1
.area
.bottom
= IVAL(w_data
, 20);
2881 /* skip index here */
2882 i1
.flags
= IVAL(w_data
, 28);
2884 torture_assert_int_equal(tctx
, i1
.size
.width
, info
.info1
.size
.width
, "width mismatch");
2885 torture_assert_int_equal(tctx
, i1
.size
.height
, info
.info1
.size
.height
, "height mismatch");
2886 torture_assert_int_equal(tctx
, i1
.area
.left
, info
.info1
.area
.left
, "left mismatch");
2887 torture_assert_int_equal(tctx
, i1
.area
.top
, info
.info1
.area
.top
, "top mismatch");
2888 torture_assert_int_equal(tctx
, i1
.area
.right
, info
.info1
.area
.right
, "right mismatch");
2889 torture_assert_int_equal(tctx
, i1
.area
.bottom
, info
.info1
.area
.bottom
, "bottom mismatch");
2890 torture_assert_int_equal(tctx
, i1
.flags
, info
.info1
.flags
, "flags mismatch");
2893 add_info
.info1
->size
.width
= 1234;
2895 torture_assert(tctx
,
2896 test_SetForm(tctx
, b
, handle
, form_name
, 1, &add_info
),
2897 "failed to set form");
2898 torture_assert(tctx
,
2899 test_GetForm_args(tctx
, b
, handle
, form_name
, 1, &info
),
2900 "failed to get set form");
2902 torture_assert_int_equal(tctx
, info
.info1
.size
.width
, add_info
.info1
->size
.width
, "width mismatch");
2905 if (!W_ERROR_EQUAL(expected_add_result
, WERR_INVALID_PARAMETER
)) {
2906 torture_assert(tctx
,
2907 test_EnumForms_find_one(tctx
, b
, handle
, print_server
, form_name
),
2908 "Newly added form not found in enum call");
2911 torture_assert(tctx
,
2912 test_DeleteForm(tctx
, b
, handle
, form_name
, expected_delete_result
),
2913 "failed to delete form");
2918 static bool test_Forms(struct torture_context
*tctx
,
2919 struct dcerpc_binding_handle
*b
,
2920 struct policy_handle
*handle
,
2922 const char *printer_name
,
2923 struct dcerpc_binding_handle
*winreg_handle
,
2924 struct policy_handle
*hive_handle
)
2926 const struct spoolss_FormSize size
= {
2930 const struct spoolss_FormArea area
= {
2939 struct spoolss_AddFormInfo1 info1
;
2940 WERROR expected_add_result
;
2941 WERROR expected_delete_result
;
2945 .flags
= SPOOLSS_FORM_USER
,
2946 .form_name
= "testform_user",
2950 .expected_add_result
= WERR_OK
,
2951 .expected_delete_result
= WERR_OK
2954 weird, we can add a builtin form but we can never remove it
2959 .flags = SPOOLSS_FORM_BUILTIN,
2960 .form_name = "testform_builtin",
2964 .expected_add_result = WERR_OK,
2965 .expected_delete_result = WERR_INVALID_PARAMETER,
2970 .flags
= SPOOLSS_FORM_PRINTER
,
2971 .form_name
= "testform_printer",
2975 .expected_add_result
= WERR_OK
,
2976 .expected_delete_result
= WERR_OK
2980 .flags
= SPOOLSS_FORM_USER
,
2981 .form_name
= "Letter",
2985 .expected_add_result
= WERR_FILE_EXISTS
,
2986 .expected_delete_result
= WERR_INVALID_PARAMETER
2990 .flags
= SPOOLSS_FORM_BUILTIN
,
2991 .form_name
= "Letter",
2995 .expected_add_result
= WERR_FILE_EXISTS
,
2996 .expected_delete_result
= WERR_INVALID_PARAMETER
3000 .flags
= SPOOLSS_FORM_PRINTER
,
3001 .form_name
= "Letter",
3005 .expected_add_result
= WERR_FILE_EXISTS
,
3006 .expected_delete_result
= WERR_INVALID_PARAMETER
3011 .form_name
= "invalid_flags",
3015 .expected_add_result
= WERR_INVALID_PARAMETER
,
3016 .expected_delete_result
= WERR_INVALID_FORM_NAME
3021 for (i
=0; i
< ARRAY_SIZE(forms
); i
++) {
3022 torture_assert(tctx
,
3023 test_Forms_args(tctx
, b
, handle
, print_server
, printer_name
,
3024 winreg_handle
, hive_handle
,
3025 forms
[i
].info1
.form_name
,
3027 forms
[i
].expected_add_result
,
3028 forms
[i
].expected_delete_result
),
3029 talloc_asprintf(tctx
, "failed to test form '%s'", forms
[i
].info1
.form_name
));
3035 static bool test_EnumPorts_old(struct torture_context
*tctx
,
3038 struct test_spoolss_context
*ctx
=
3039 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
3042 struct spoolss_EnumPorts r
;
3045 union spoolss_PortInfo
*info
;
3046 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
3047 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
3049 r
.in
.servername
= talloc_asprintf(tctx
, "\\\\%s",
3050 dcerpc_server_name(p
));
3054 r
.out
.needed
= &needed
;
3055 r
.out
.count
= &count
;
3058 torture_comment(tctx
, "Testing EnumPorts\n");
3060 status
= dcerpc_spoolss_EnumPorts_r(b
, tctx
, &r
);
3062 torture_assert_ntstatus_ok(tctx
, status
, "EnumPorts failed");
3064 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
3065 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
3066 r
.in
.buffer
= &blob
;
3067 r
.in
.offered
= needed
;
3069 status
= dcerpc_spoolss_EnumPorts_r(b
, tctx
, &r
);
3070 torture_assert_ntstatus_ok(tctx
, status
, "EnumPorts failed");
3071 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
3073 torture_assert(tctx
, info
, "No ports returned");
3076 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
3078 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts
, info
, 2, count
, needed
, 4);
3083 static bool test_AddPort(struct torture_context
*tctx
,
3086 struct test_spoolss_context
*ctx
=
3087 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
3090 struct spoolss_AddPort r
;
3091 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
3092 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
3094 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s",
3095 dcerpc_server_name(p
));
3097 r
.in
.monitor_name
= "foo";
3099 torture_comment(tctx
, "Testing AddPort\n");
3101 status
= dcerpc_spoolss_AddPort_r(b
, tctx
, &r
);
3103 torture_assert_ntstatus_ok(tctx
, status
, "AddPort failed");
3105 /* win2k3 returns WERR_NOT_SUPPORTED */
3109 if (!W_ERROR_IS_OK(r
.out
.result
)) {
3110 printf("AddPort failed - %s\n", win_errstr(r
.out
.result
));
3119 static bool test_GetJob_args(struct torture_context
*tctx
,
3120 struct dcerpc_binding_handle
*b
,
3121 struct policy_handle
*handle
,
3124 union spoolss_JobInfo
*info_p
)
3127 struct spoolss_GetJob r
;
3128 union spoolss_JobInfo info
;
3131 r
.in
.handle
= handle
;
3132 r
.in
.job_id
= job_id
;
3136 r
.out
.needed
= &needed
;
3139 torture_comment(tctx
, "Testing GetJob(%d), level %d\n", job_id
, r
.in
.level
);
3141 status
= dcerpc_spoolss_GetJob_r(b
, tctx
, &r
);
3142 torture_assert_ntstatus_ok(tctx
, status
, "GetJob failed");
3144 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_LEVEL
, "Unexpected return code");
3147 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
3148 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
3149 r
.in
.buffer
= &blob
;
3150 r
.in
.offered
= needed
;
3152 status
= dcerpc_spoolss_GetJob_r(b
, tctx
, &r
);
3153 torture_assert_ntstatus_ok(tctx
, status
, "GetJob failed");
3156 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetJob failed");
3157 torture_assert(tctx
, r
.out
.info
, "No job info returned");
3159 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo
, r
.out
.info
, r
.in
.level
, needed
, 4);
3162 *info_p
= *r
.out
.info
;
3169 static bool test_GetJob(struct torture_context
*tctx
,
3170 struct dcerpc_binding_handle
*b
,
3171 struct policy_handle
*handle
,
3174 uint32_t levels
[] = {0, 1, 2 /* 3, 4 */};
3177 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
3178 torture_assert(tctx
,
3179 test_GetJob_args(tctx
, b
, handle
, job_id
, levels
[i
], NULL
),
3187 static bool test_SetJob(struct torture_context
*tctx
,
3188 struct dcerpc_binding_handle
*b
,
3189 struct policy_handle
*handle
,
3191 struct spoolss_JobInfoContainer
*ctr
,
3192 enum spoolss_JobControl command
)
3195 struct spoolss_SetJob r
;
3197 r
.in
.handle
= handle
;
3198 r
.in
.job_id
= job_id
;
3200 r
.in
.command
= command
;
3203 case SPOOLSS_JOB_CONTROL_PAUSE
:
3204 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id
);
3206 case SPOOLSS_JOB_CONTROL_RESUME
:
3207 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id
);
3209 case SPOOLSS_JOB_CONTROL_CANCEL
:
3210 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id
);
3212 case SPOOLSS_JOB_CONTROL_RESTART
:
3213 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id
);
3215 case SPOOLSS_JOB_CONTROL_DELETE
:
3216 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id
);
3218 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER
:
3219 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id
);
3221 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED
:
3222 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id
);
3224 case SPOOLSS_JOB_CONTROL_RETAIN
:
3225 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id
);
3227 case SPOOLSS_JOB_CONTROL_RELEASE
:
3228 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id
);
3231 torture_comment(tctx
, "Testing SetJob(%d)\n", job_id
);
3235 status
= dcerpc_spoolss_SetJob_r(b
, tctx
, &r
);
3236 torture_assert_ntstatus_ok(tctx
, status
, "SetJob failed");
3237 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetJob failed");
3242 static bool test_AddJob(struct torture_context
*tctx
,
3243 struct dcerpc_binding_handle
*b
,
3244 struct policy_handle
*handle
)
3247 struct spoolss_AddJob r
;
3251 r
.in
.handle
= handle
;
3253 r
.out
.needed
= &needed
;
3254 r
.in
.buffer
= r
.out
.buffer
= NULL
;
3256 torture_comment(tctx
, "Testing AddJob\n");
3258 status
= dcerpc_spoolss_AddJob_r(b
, tctx
, &r
);
3259 torture_assert_ntstatus_ok(tctx
, status
, "AddJob failed");
3260 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_LEVEL
, "AddJob failed");
3264 status
= dcerpc_spoolss_AddJob_r(b
, tctx
, &r
);
3265 torture_assert_ntstatus_ok(tctx
, status
, "AddJob failed");
3266 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAMETER
, "AddJob failed");
3272 static bool test_EnumJobs_args(struct torture_context
*tctx
,
3273 struct dcerpc_binding_handle
*b
,
3274 struct policy_handle
*handle
,
3276 WERROR werr_expected
,
3278 union spoolss_JobInfo
**info_p
)
3281 struct spoolss_EnumJobs r
;
3284 union spoolss_JobInfo
*info
;
3286 r
.in
.handle
= handle
;
3288 r
.in
.numjobs
= 0xffffffff;
3292 r
.out
.needed
= &needed
;
3293 r
.out
.count
= &count
;
3296 torture_comment(tctx
, "Testing EnumJobs level %d\n", level
);
3298 status
= dcerpc_spoolss_EnumJobs_r(b
, tctx
, &r
);
3300 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
3302 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
3303 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
3304 r
.in
.buffer
= &blob
;
3305 r
.in
.offered
= needed
;
3307 status
= dcerpc_spoolss_EnumJobs_r(b
, tctx
, &r
);
3309 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
3310 torture_assert_werr_equal(tctx
, r
.out
.result
, werr_expected
,
3312 torture_assert(tctx
, info
, "No jobs returned");
3314 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs
, *r
.out
.info
, r
.in
.level
, count
, needed
, 4);
3317 torture_assert_werr_equal(tctx
, r
.out
.result
, werr_expected
,
3331 static bool test_JobPropertiesEnum(struct torture_context
*tctx
,
3332 struct dcerpc_binding_handle
*b
,
3333 struct policy_handle
*handle
,
3336 struct spoolss_EnumJobNamedProperties r
;
3337 uint32_t pcProperties
= 0;
3338 struct spoolss_PrintNamedProperty
*ppProperties
= NULL
;
3340 r
.in
.hPrinter
= handle
;
3341 r
.in
.JobId
= job_id
;
3342 r
.out
.pcProperties
= &pcProperties
;
3343 r
.out
.ppProperties
= &ppProperties
;
3345 torture_comment(tctx
, "Testing EnumJobNamedProperties(%d)\n", job_id
);
3347 torture_assert_ntstatus_ok(tctx
,
3348 dcerpc_spoolss_EnumJobNamedProperties_r(b
, tctx
, &r
),
3349 "spoolss_EnumJobNamedProperties failed");
3350 torture_assert_werr_ok(tctx
, r
.out
.result
,
3351 "spoolss_EnumJobNamedProperties failed");
3356 static bool test_JobPropertySet(struct torture_context
*tctx
,
3357 struct dcerpc_binding_handle
*b
,
3358 struct policy_handle
*handle
,
3360 struct spoolss_PrintNamedProperty
*property
)
3362 struct spoolss_SetJobNamedProperty r
;
3364 r
.in
.hPrinter
= handle
;
3365 r
.in
.JobId
= job_id
;
3366 r
.in
.pProperty
= property
;
3368 torture_comment(tctx
, "Testing SetJobNamedProperty(%d) %s - %d\n",
3369 job_id
, property
->propertyName
,
3370 property
->propertyValue
.ePropertyType
);
3372 torture_assert_ntstatus_ok(tctx
,
3373 dcerpc_spoolss_SetJobNamedProperty_r(b
, tctx
, &r
),
3374 "spoolss_SetJobNamedProperty failed");
3375 torture_assert_werr_ok(tctx
, r
.out
.result
,
3376 "spoolss_SetJobNamedProperty failed");
3381 static bool test_JobPropertyGetValue(struct torture_context
*tctx
,
3382 struct dcerpc_binding_handle
*b
,
3383 struct policy_handle
*handle
,
3385 const char *property_name
,
3386 struct spoolss_PrintPropertyValue
*value
)
3388 struct spoolss_GetJobNamedPropertyValue r
;
3390 r
.in
.hPrinter
= handle
;
3391 r
.in
.JobId
= job_id
;
3392 r
.in
.pszName
= property_name
;
3393 r
.out
.pValue
= value
;
3395 torture_comment(tctx
, "Testing GetJobNamedPropertyValue(%d) %s\n",
3396 job_id
, property_name
);
3398 torture_assert_ntstatus_ok(tctx
,
3399 dcerpc_spoolss_GetJobNamedPropertyValue_r(b
, tctx
, &r
),
3400 "spoolss_GetJobNamedPropertyValue failed");
3401 torture_assert_werr_ok(tctx
, r
.out
.result
,
3402 "spoolss_GetJobNamedPropertyValue failed");
3407 static bool test_JobPropertyDelete(struct torture_context
*tctx
,
3408 struct dcerpc_binding_handle
*b
,
3409 struct policy_handle
*handle
,
3411 const char *property_name
)
3413 struct spoolss_DeleteJobNamedProperty r
;
3415 r
.in
.hPrinter
= handle
;
3416 r
.in
.JobId
= job_id
;
3417 r
.in
.pszName
= property_name
;
3419 torture_comment(tctx
, "Testing DeleteJobNamedProperty(%d) %s\n",
3420 job_id
, property_name
);
3422 torture_assert_ntstatus_ok(tctx
,
3423 dcerpc_spoolss_DeleteJobNamedProperty_r(b
, tctx
, &r
),
3424 "spoolss_DeleteJobNamedProperty failed");
3425 torture_assert_werr_ok(tctx
, r
.out
.result
,
3426 "spoolss_DeleteJobNamedProperty failed");
3431 static bool test_DoPrintTest_add_one_job_common(struct torture_context
*tctx
,
3432 struct dcerpc_binding_handle
*b
,
3433 struct policy_handle
*handle
,
3434 const char *document_name
,
3435 const char *datatype
,
3439 struct spoolss_StartDocPrinter s
;
3440 struct spoolss_DocumentInfoCtr info_ctr
;
3441 struct spoolss_DocumentInfo1 info1
;
3442 struct spoolss_StartPagePrinter sp
;
3443 struct spoolss_WritePrinter w
;
3444 struct spoolss_EndPagePrinter ep
;
3445 struct spoolss_EndDocPrinter e
;
3447 uint32_t num_written
;
3449 torture_comment(tctx
, "Testing StartDocPrinter\n");
3451 s
.in
.handle
= handle
;
3452 s
.in
.info_ctr
= &info_ctr
;
3453 s
.out
.job_id
= job_id
;
3455 info1
.document_name
= document_name
;
3456 info1
.output_file
= NULL
;
3457 info1
.datatype
= datatype
;
3460 info_ctr
.info
.info1
= &info1
;
3462 status
= dcerpc_spoolss_StartDocPrinter_r(b
, tctx
, &s
);
3463 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_StartDocPrinter failed");
3464 torture_assert_werr_ok(tctx
, s
.out
.result
, "StartDocPrinter failed");
3466 for (i
=1; i
< 4; i
++) {
3467 union spoolss_JobInfo ginfo
;
3470 torture_comment(tctx
, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i
, *job_id
);
3472 sp
.in
.handle
= handle
;
3474 status
= dcerpc_spoolss_StartPagePrinter_r(b
, tctx
, &sp
);
3475 torture_assert_ntstatus_ok(tctx
, status
,
3476 "dcerpc_spoolss_StartPagePrinter failed");
3477 torture_assert_werr_ok(tctx
, sp
.out
.result
, "StartPagePrinter failed");
3479 ok
= test_GetJob_args(tctx
, b
, handle
, *job_id
, 1, &ginfo
);
3481 torture_comment(tctx
, "test_GetJob failed for JobId[%d]\n", *job_id
);
3484 torture_comment(tctx
, "Testing WritePrinter: Page[%d], JobId[%d]\n", i
, *job_id
);
3486 w
.in
.handle
= handle
;
3487 w
.in
.data
= data_blob_string_const(talloc_asprintf(tctx
,"TortureTestPage: %d\nData\n",i
));
3488 w
.out
.num_written
= &num_written
;
3490 status
= dcerpc_spoolss_WritePrinter_r(b
, tctx
, &w
);
3491 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_WritePrinter failed");
3492 torture_assert_werr_ok(tctx
, w
.out
.result
, "WritePrinter failed");
3494 torture_comment(tctx
, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i
, *job_id
);
3496 ep
.in
.handle
= handle
;
3498 status
= dcerpc_spoolss_EndPagePrinter_r(b
, tctx
, &ep
);
3499 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndPagePrinter failed");
3500 torture_assert_werr_ok(tctx
, ep
.out
.result
, "EndPagePrinter failed");
3503 torture_comment(tctx
, "Testing EndDocPrinter: JobId[%d]\n", *job_id
);
3505 e
.in
.handle
= handle
;
3507 status
= dcerpc_spoolss_EndDocPrinter_r(b
, tctx
, &e
);
3508 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndDocPrinter failed");
3509 torture_assert_werr_ok(tctx
, e
.out
.result
, "EndDocPrinter failed");
3514 static bool test_DoPrintTest_add_one_job(struct torture_context
*tctx
,
3515 struct dcerpc_binding_handle
*b
,
3516 struct policy_handle
*handle
,
3517 const char *document_name
,
3520 test_DoPrintTest_add_one_job_common(tctx
, b
, handle
, document_name
, "RAW", job_id
);
3525 static bool test_DoPrintTest_add_one_job_v4(struct torture_context
*tctx
,
3526 struct dcerpc_binding_handle
*b
,
3527 struct policy_handle
*handle
,
3528 const char *document_name
,
3531 test_DoPrintTest_add_one_job_common(tctx
, b
, handle
, document_name
, "XPS_PASS", job_id
);
3537 static bool test_DoPrintTest_check_jobs(struct torture_context
*tctx
,
3538 struct dcerpc_binding_handle
*b
,
3539 struct policy_handle
*handle
,
3544 union spoolss_JobInfo
*info
= NULL
;
3547 torture_assert(tctx
,
3548 test_AddJob(tctx
, b
, handle
),
3551 torture_assert(tctx
,
3552 test_EnumJobs_args(tctx
, b
, handle
, 1, WERR_OK
, &count
, &info
),
3553 "EnumJobs level 1 failed");
3555 torture_assert_int_equal(tctx
, count
, num_jobs
, "unexpected number of jobs in queue");
3557 for (i
=0; i
< num_jobs
; i
++) {
3558 union spoolss_JobInfo ginfo
;
3559 const char *document_name
;
3560 const char *new_document_name
= "any_other_docname";
3561 struct spoolss_JobInfoContainer ctr
;
3562 struct spoolss_SetJobInfo1 info1
;
3564 torture_assert_int_equal(tctx
, info
[i
].info1
.job_id
, job_ids
[i
], "job id mismatch");
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 torture_assert_int_equal(tctx
, ginfo
.info1
.job_id
, info
[i
].info1
.job_id
, "job id mismatch");
3572 document_name
= ginfo
.info1
.document_name
;
3574 info1
.job_id
= ginfo
.info1
.job_id
;
3575 info1
.printer_name
= ginfo
.info1
.printer_name
;
3576 info1
.server_name
= ginfo
.info1
.server_name
;
3577 info1
.user_name
= ginfo
.info1
.user_name
;
3578 info1
.document_name
= new_document_name
;
3579 info1
.data_type
= ginfo
.info1
.data_type
;
3580 info1
.text_status
= ginfo
.info1
.text_status
;
3581 info1
.status
= ginfo
.info1
.status
;
3582 info1
.priority
= ginfo
.info1
.priority
;
3583 info1
.position
= ginfo
.info1
.position
;
3584 info1
.total_pages
= ginfo
.info1
.total_pages
;
3585 info1
.pages_printed
= ginfo
.info1
.pages_printed
;
3586 info1
.submitted
= ginfo
.info1
.submitted
;
3589 ctr
.info
.info1
= &info1
;
3591 torture_assert(tctx
,
3592 test_SetJob(tctx
, b
, handle
, info
[i
].info1
.job_id
, &ctr
, 0),
3593 "failed to call test_SetJob level 1");
3595 torture_assert(tctx
,
3596 test_GetJob_args(tctx
, b
, handle
, info
[i
].info1
.job_id
, 1, &ginfo
),
3597 "failed to call test_GetJob");
3599 if (strequal(ginfo
.info1
.document_name
, document_name
)) {
3600 torture_warning(tctx
,
3601 "document_name did *NOT* change from '%s' to '%s'\n",
3602 document_name
, new_document_name
);
3606 for (i
=0; i
< num_jobs
; i
++) {
3607 if (!test_SetJob(tctx
, b
, handle
, info
[i
].info1
.job_id
, NULL
, SPOOLSS_JOB_CONTROL_PAUSE
)) {
3608 torture_warning(tctx
, "failed to pause printjob\n");
3610 if (!test_SetJob(tctx
, b
, handle
, info
[i
].info1
.job_id
, NULL
, SPOOLSS_JOB_CONTROL_RESUME
)) {
3611 torture_warning(tctx
, "failed to resume printjob\n");
3618 static bool test_DoPrintTest(struct torture_context
*tctx
,
3619 struct dcerpc_binding_handle
*b
,
3620 struct policy_handle
*handle
)
3623 uint32_t num_jobs
= 8;
3627 torture_comment(tctx
, "Testing real print operations\n");
3629 job_ids
= talloc_zero_array(tctx
, uint32_t, num_jobs
);
3631 for (i
=0; i
< num_jobs
; i
++) {
3632 ret
&= test_DoPrintTest_add_one_job(tctx
, b
, handle
, "TorturePrintJob", &job_ids
[i
]);
3635 for (i
=0; i
< num_jobs
; i
++) {
3636 ret
&= test_SetJob(tctx
, b
, handle
, job_ids
[i
], NULL
, SPOOLSS_JOB_CONTROL_DELETE
);
3639 for (i
=0; i
< num_jobs
; i
++) {
3640 ret
&= test_DoPrintTest_add_one_job_v4(tctx
, b
, handle
, "TorturePrintJob v4", &job_ids
[i
]);
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 test succeeded\n\n");
3654 static bool test_DoPrintTest_extended(struct torture_context
*tctx
,
3655 struct dcerpc_binding_handle
*b
,
3656 struct policy_handle
*handle
)
3659 uint32_t num_jobs
= 8;
3662 torture_comment(tctx
, "Testing real print operations (extended)\n");
3664 job_ids
= talloc_zero_array(tctx
, uint32_t, num_jobs
);
3666 for (i
=0; i
< num_jobs
; i
++) {
3667 ret
&= test_DoPrintTest_add_one_job(tctx
, b
, handle
, "TorturePrintJob", &job_ids
[i
]);
3670 ret
&= test_DoPrintTest_check_jobs(tctx
, b
, handle
, num_jobs
, job_ids
);
3672 for (i
=0; i
< num_jobs
; i
++) {
3673 ret
&= test_SetJob(tctx
, b
, handle
, job_ids
[i
], NULL
, SPOOLSS_JOB_CONTROL_DELETE
);
3677 torture_comment(tctx
, "real print operations (extended) test succeeded\n\n");
3683 static bool test_JobPrintProperties_equal(struct torture_context
*tctx
,
3684 struct spoolss_PrintPropertyValue
*got
,
3685 struct spoolss_PrintNamedProperty
*exp
)
3687 torture_assert_int_equal(tctx
,
3689 exp
->propertyValue
.ePropertyType
,
3692 switch (exp
->propertyValue
.ePropertyType
) {
3693 case kRpcPropertyTypeString
:
3694 torture_assert_str_equal(tctx
,
3695 got
->value
.propertyString
,
3696 exp
->propertyValue
.value
.propertyString
,
3699 case kRpcPropertyTypeInt32
:
3700 torture_assert_int_equal(tctx
,
3701 got
->value
.propertyInt32
,
3702 exp
->propertyValue
.value
.propertyInt32
,
3705 case kRpcPropertyTypeInt64
:
3706 torture_assert_u64_equal(tctx
,
3707 got
->value
.propertyInt64
,
3708 exp
->propertyValue
.value
.propertyInt64
,
3711 case kRpcPropertyTypeByte
:
3712 torture_assert_int_equal(tctx
,
3713 got
->value
.propertyByte
,
3714 exp
->propertyValue
.value
.propertyByte
,
3717 case kRpcPropertyTypeBuffer
:
3718 torture_assert_int_equal(tctx
,
3719 got
->value
.propertyBlob
.cbBuf
,
3720 exp
->propertyValue
.value
.propertyBlob
.cbBuf
,
3721 "propertyBlob.cbBuf");
3722 torture_assert_mem_equal(tctx
,
3723 got
->value
.propertyBlob
.pBuf
,
3724 exp
->propertyValue
.value
.propertyBlob
.pBuf
,
3725 exp
->propertyValue
.value
.propertyBlob
.cbBuf
,
3726 "propertyBlob.pBuf");
3735 static bool test_JobPrintProperties(struct torture_context
*tctx
,
3736 struct dcerpc_binding_handle
*b
,
3737 struct policy_handle
*handle
,
3740 struct spoolss_PrintNamedProperty in
;
3741 struct spoolss_PrintPropertyValue out
;
3743 DATA_BLOB blob
= data_blob_string_const("blob");
3745 const char *property_name
;
3746 enum spoolss_EPrintPropertyType type
;
3747 union spoolss_PrintPropertyValueUnion value
;
3748 WERROR expected_result
;
3751 .property_name
= "torture_property_string",
3752 .type
= kRpcPropertyTypeString
,
3753 .value
.propertyString
= "torture_property_value_string",
3755 .property_name
= "torture_property_int32",
3756 .type
= kRpcPropertyTypeInt32
,
3757 .value
.propertyInt32
= 42,
3759 .property_name
= "torture_property_int64",
3760 .type
= kRpcPropertyTypeInt64
,
3761 .value
.propertyInt64
= 0xaffe,
3763 .property_name
= "torture_property_byte",
3764 .type
= kRpcPropertyTypeByte
,
3765 .value
.propertyByte
= 0xab,
3767 .property_name
= "torture_property_buffer",
3768 .type
= kRpcPropertyTypeBuffer
,
3769 .value
.propertyBlob
.cbBuf
= blob
.length
,
3770 .value
.propertyBlob
.pBuf
= blob
.data
,
3774 torture_assert(tctx
,
3775 test_JobPropertiesEnum(tctx
, b
, handle
, job_id
),
3776 "failed to enum properties");
3778 for (i
=0; i
<ARRAY_SIZE(tests
); i
++) {
3780 in
.propertyName
= tests
[i
].property_name
;
3781 in
.propertyValue
.ePropertyType
= tests
[i
].type
;
3782 in
.propertyValue
.value
= tests
[i
].value
;
3784 torture_assert(tctx
,
3785 test_JobPropertySet(tctx
, b
, handle
, job_id
, &in
),
3786 "failed to set property");
3788 torture_assert(tctx
,
3789 test_JobPropertyGetValue(tctx
, b
, handle
, job_id
, in
.propertyName
, &out
),
3790 "failed to get property");
3792 torture_assert(tctx
,
3793 test_JobPrintProperties_equal(tctx
, &out
, &in
),
3794 "property unequal");
3796 torture_assert(tctx
,
3797 test_JobPropertiesEnum(tctx
, b
, handle
, job_id
),
3798 "failed to enum properties");
3800 torture_assert(tctx
,
3801 test_JobPropertyDelete(tctx
, b
, handle
, job_id
, in
.propertyName
),
3802 "failed to delete job property");
3805 torture_assert(tctx
,
3806 test_JobPropertiesEnum(tctx
, b
, handle
, job_id
),
3807 "failed to enum properties");
3812 static bool test_DoPrintTest_properties(struct torture_context
*tctx
,
3813 struct dcerpc_binding_handle
*b
,
3814 struct policy_handle
*handle
)
3816 uint32_t num_jobs
= 8;
3819 torture_comment(tctx
, "Testing real print operations (properties)\n");
3821 job_ids
= talloc_zero_array(tctx
, uint32_t, num_jobs
);
3823 for (i
=0; i
< num_jobs
; i
++) {
3824 torture_assert(tctx
,
3825 test_DoPrintTest_add_one_job(tctx
, b
, handle
, "TorturePrintJob", &job_ids
[i
]),
3826 "failed to create print job");
3829 for (i
=0; i
< num_jobs
; i
++) {
3830 torture_assert(tctx
,
3831 test_JobPrintProperties(tctx
, b
, handle
, job_ids
[i
]),
3832 "failed to test job properties");
3836 for (i
=0; i
< num_jobs
; i
++) {
3837 torture_assert(tctx
,
3838 test_SetJob(tctx
, b
, handle
, job_ids
[i
], NULL
, SPOOLSS_JOB_CONTROL_DELETE
),
3839 "failed to delete printjob");
3842 torture_comment(tctx
, "real print operations (properties) test succeeded\n\n");
3847 static bool test_PausePrinter(struct torture_context
*tctx
,
3848 struct dcerpc_binding_handle
*b
,
3849 struct policy_handle
*handle
)
3852 struct spoolss_SetPrinter r
;
3853 struct spoolss_SetPrinterInfoCtr info_ctr
;
3854 struct spoolss_DevmodeContainer devmode_ctr
;
3855 struct sec_desc_buf secdesc_ctr
;
3858 info_ctr
.info
.info0
= NULL
;
3860 ZERO_STRUCT(devmode_ctr
);
3861 ZERO_STRUCT(secdesc_ctr
);
3863 r
.in
.handle
= handle
;
3864 r
.in
.info_ctr
= &info_ctr
;
3865 r
.in
.devmode_ctr
= &devmode_ctr
;
3866 r
.in
.secdesc_ctr
= &secdesc_ctr
;
3867 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
3869 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3871 status
= dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
);
3873 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
3875 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
3880 static bool test_ResumePrinter(struct torture_context
*tctx
,
3881 struct dcerpc_binding_handle
*b
,
3882 struct policy_handle
*handle
)
3885 struct spoolss_SetPrinter r
;
3886 struct spoolss_SetPrinterInfoCtr info_ctr
;
3887 struct spoolss_DevmodeContainer devmode_ctr
;
3888 struct sec_desc_buf secdesc_ctr
;
3891 info_ctr
.info
.info0
= NULL
;
3893 ZERO_STRUCT(devmode_ctr
);
3894 ZERO_STRUCT(secdesc_ctr
);
3896 r
.in
.handle
= handle
;
3897 r
.in
.info_ctr
= &info_ctr
;
3898 r
.in
.devmode_ctr
= &devmode_ctr
;
3899 r
.in
.secdesc_ctr
= &secdesc_ctr
;
3900 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
3902 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3904 status
= dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
);
3906 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
3908 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
3913 static bool test_printer_purge(struct torture_context
*tctx
,
3914 struct dcerpc_binding_handle
*b
,
3915 struct policy_handle
*handle
)
3918 struct spoolss_SetPrinter r
;
3919 struct spoolss_SetPrinterInfoCtr info_ctr
;
3920 struct spoolss_DevmodeContainer devmode_ctr
;
3921 struct sec_desc_buf secdesc_ctr
;
3924 info_ctr
.info
.info0
= NULL
;
3926 ZERO_STRUCT(devmode_ctr
);
3927 ZERO_STRUCT(secdesc_ctr
);
3929 r
.in
.handle
= handle
;
3930 r
.in
.info_ctr
= &info_ctr
;
3931 r
.in
.devmode_ctr
= &devmode_ctr
;
3932 r
.in
.secdesc_ctr
= &secdesc_ctr
;
3933 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_PURGE
;
3935 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PURGE\n");
3937 status
= dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
);
3938 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
3939 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
3944 static bool test_GetPrinterData_checktype(struct torture_context
*tctx
,
3945 struct dcerpc_binding_handle
*b
,
3946 struct policy_handle
*handle
,
3947 const char *value_name
,
3948 enum winreg_Type
*expected_type
,
3949 enum winreg_Type
*type_p
,
3954 struct spoolss_GetPrinterData r
;
3956 enum winreg_Type type
;
3957 union spoolss_PrinterData data
;
3959 r
.in
.handle
= handle
;
3960 r
.in
.value_name
= value_name
;
3962 r
.out
.needed
= &needed
;
3964 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
3966 torture_comment(tctx
, "Testing GetPrinterData(%s)\n", r
.in
.value_name
);
3968 status
= dcerpc_spoolss_GetPrinterData_r(b
, tctx
, &r
);
3969 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
3971 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
3972 if (expected_type
) {
3973 torture_assert_int_equal(tctx
, type
, *expected_type
, "unexpected type");
3975 r
.in
.offered
= needed
;
3976 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
3977 status
= dcerpc_spoolss_GetPrinterData_r(b
, tctx
, &r
);
3978 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
3981 torture_assert_werr_ok(tctx
, r
.out
.result
,
3982 talloc_asprintf(tctx
, "GetPrinterData(%s) failed", r
.in
.value_name
));
3984 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData
, &data
, type
, needed
, 1);
3991 *data_p
= r
.out
.data
;
4001 static bool test_GetPrinterData(struct torture_context
*tctx
,
4002 struct dcerpc_binding_handle
*b
,
4003 struct policy_handle
*handle
,
4004 const char *value_name
,
4005 enum winreg_Type
*type_p
,
4009 return test_GetPrinterData_checktype(tctx
, b
, handle
, value_name
,
4010 NULL
, type_p
, data_p
, needed_p
);
4013 static bool test_GetPrinterDataEx_checktype(struct torture_context
*tctx
,
4014 struct dcerpc_pipe
*p
,
4015 struct policy_handle
*handle
,
4016 const char *key_name
,
4017 const char *value_name
,
4018 enum winreg_Type
*expected_type
,
4019 enum winreg_Type
*type_p
,
4024 struct spoolss_GetPrinterDataEx r
;
4025 enum winreg_Type type
;
4027 union spoolss_PrinterData data
;
4028 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4030 r
.in
.handle
= handle
;
4031 r
.in
.key_name
= key_name
;
4032 r
.in
.value_name
= value_name
;
4035 r
.out
.needed
= &needed
;
4036 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
4038 torture_comment(tctx
, "Testing GetPrinterDataEx(%s - %s)\n",
4039 r
.in
.key_name
, r
.in
.value_name
);
4041 status
= dcerpc_spoolss_GetPrinterDataEx_r(b
, tctx
, &r
);
4042 if (!NT_STATUS_IS_OK(status
)) {
4043 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
)) {
4044 torture_skip(tctx
, "GetPrinterDataEx not supported by server\n");
4046 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
4049 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
4050 if (expected_type
) {
4051 torture_assert_int_equal(tctx
, type
, *expected_type
, "unexpected type");
4053 r
.in
.offered
= needed
;
4054 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
4055 status
= dcerpc_spoolss_GetPrinterDataEx_r(b
, tctx
, &r
);
4056 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
4059 torture_assert_werr_ok(tctx
, r
.out
.result
,
4060 talloc_asprintf(tctx
, "GetPrinterDataEx(%s - %s) failed", r
.in
.key_name
, r
.in
.value_name
));
4062 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData
, &data
, type
, needed
, 1);
4069 *data_p
= r
.out
.data
;
4079 static bool test_GetPrinterDataEx(struct torture_context
*tctx
,
4080 struct dcerpc_pipe
*p
,
4081 struct policy_handle
*handle
,
4082 const char *key_name
,
4083 const char *value_name
,
4084 enum winreg_Type
*type_p
,
4088 return test_GetPrinterDataEx_checktype(tctx
, p
, handle
, key_name
, value_name
,
4089 NULL
, type_p
, data_p
, needed_p
);
4092 static bool test_get_environment(struct torture_context
*tctx
,
4093 struct dcerpc_binding_handle
*b
,
4094 struct policy_handle
*handle
,
4095 const char **architecture
)
4098 enum winreg_Type type
;
4102 torture_assert(tctx
,
4103 test_GetPrinterData(tctx
, b
, handle
, "Architecture", &type
, &data
, &needed
),
4104 "failed to get Architecture");
4106 torture_assert_int_equal(tctx
, type
, REG_SZ
, "unexpected type");
4108 blob
= data_blob_const(data
, needed
);
4109 *architecture
= reg_val_data_string(tctx
, REG_SZ
, blob
);
4114 static bool test_GetPrinterData_list(struct torture_context
*tctx
,
4117 struct test_spoolss_context
*ctx
=
4118 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
4119 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
4120 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4121 const char *list
[] = {
4125 /* "NetPopup", not on w2k8 */
4126 /* "NetPopupToComputer", not on w2k8 */
4129 "DefaultSpoolDirectory",
4133 /* "OSVersionEx", not on s3 */
4138 for (i
=0; i
< ARRAY_SIZE(list
); i
++) {
4139 enum winreg_Type type
= REG_NONE
;
4140 enum winreg_Type type_ex1
= REG_NONE
;
4141 enum winreg_Type type_ex2
= REG_NONE
;
4143 uint8_t *data_ex1
= NULL
;
4144 uint8_t *data_ex2
= NULL
;
4146 uint32_t needed_ex1
= 0;
4147 uint32_t needed_ex2
= 0;
4149 torture_assert(tctx
, test_GetPrinterData(tctx
, b
, &ctx
->server_handle
, list
[i
], &type
, &data
, &needed
),
4150 talloc_asprintf(tctx
, "GetPrinterData failed on %s\n", list
[i
]));
4151 torture_assert(tctx
, test_GetPrinterDataEx(tctx
, p
, &ctx
->server_handle
, "random_string", list
[i
], &type_ex1
, &data_ex1
, &needed_ex1
),
4152 talloc_asprintf(tctx
, "GetPrinterDataEx failed on %s\n", list
[i
]));
4153 torture_assert(tctx
, test_GetPrinterDataEx(tctx
, p
, &ctx
->server_handle
, "", list
[i
], &type_ex2
, &data_ex2
, &needed_ex2
),
4154 talloc_asprintf(tctx
, "GetPrinterDataEx failed on %s\n", list
[i
]));
4155 torture_assert_int_equal(tctx
, type
, type_ex1
, "type mismatch");
4156 torture_assert_int_equal(tctx
, type
, type_ex2
, "type mismatch");
4157 torture_assert_int_equal(tctx
, needed
, needed_ex1
, "needed mismatch");
4158 torture_assert_int_equal(tctx
, needed
, needed_ex2
, "needed mismatch");
4159 torture_assert_mem_equal(tctx
, data
, data_ex1
, needed
, "data mismatch");
4160 torture_assert_mem_equal(tctx
, data
, data_ex2
, needed
, "data mismatch");
4166 static bool test_EnumPrinterData(struct torture_context
*tctx
,
4167 struct dcerpc_pipe
*p
,
4168 struct policy_handle
*handle
,
4169 uint32_t enum_index
,
4170 uint32_t value_offered
,
4171 uint32_t data_offered
,
4172 enum winreg_Type
*type_p
,
4173 uint32_t *value_needed_p
,
4174 uint32_t *data_needed_p
,
4175 const char **value_name_p
,
4179 struct spoolss_EnumPrinterData r
;
4180 uint32_t data_needed
;
4181 uint32_t value_needed
;
4182 enum winreg_Type type
;
4183 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4185 r
.in
.handle
= handle
;
4186 r
.in
.enum_index
= enum_index
;
4187 r
.in
.value_offered
= value_offered
;
4188 r
.in
.data_offered
= data_offered
;
4189 r
.out
.data_needed
= &data_needed
;
4190 r
.out
.value_needed
= &value_needed
;
4192 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.data_offered
);
4193 r
.out
.value_name
= talloc_zero_array(tctx
, const char, r
.in
.value_offered
);
4195 torture_comment(tctx
, "Testing EnumPrinterData(%d)\n", enum_index
);
4197 torture_assert_ntstatus_ok(tctx
,
4198 dcerpc_spoolss_EnumPrinterData_r(b
, tctx
, &r
),
4199 "EnumPrinterData failed");
4204 if (value_needed_p
) {
4205 *value_needed_p
= value_needed
;
4207 if (data_needed_p
) {
4208 *data_needed_p
= data_needed
;
4211 *value_name_p
= r
.out
.value_name
;
4214 *data_p
= r
.out
.data
;
4217 *result_p
= r
.out
.result
;
4224 static bool test_EnumPrinterData_all(struct torture_context
*tctx
,
4225 struct dcerpc_pipe
*p
,
4226 struct policy_handle
*handle
)
4228 uint32_t enum_index
= 0;
4229 enum winreg_Type type
;
4230 uint32_t value_needed
;
4231 uint32_t data_needed
;
4233 const char *value_name
;
4236 torture_comment(tctx
, "Testing EnumPrinterData\n");
4239 torture_assert(tctx
,
4240 test_EnumPrinterData(tctx
, p
, handle
, enum_index
, 0, 0,
4241 &type
, &value_needed
, &data_needed
,
4242 &value_name
, &data
, &result
),
4243 "EnumPrinterData failed");
4245 if (W_ERROR_EQUAL(result
, WERR_NO_MORE_ITEMS
)) {
4249 torture_assert(tctx
,
4250 test_EnumPrinterData(tctx
, p
, handle
, enum_index
, value_needed
, data_needed
,
4251 &type
, &value_needed
, &data_needed
,
4252 &value_name
, &data
, &result
),
4253 "EnumPrinterData failed");
4255 if (W_ERROR_EQUAL(result
, WERR_NO_MORE_ITEMS
)) {
4261 } while (W_ERROR_IS_OK(result
));
4263 torture_comment(tctx
, "EnumPrinterData test succeeded\n");
4268 static bool test_EnumPrinterDataEx(struct torture_context
*tctx
,
4269 struct dcerpc_binding_handle
*b
,
4270 struct policy_handle
*handle
,
4271 const char *key_name
,
4273 struct spoolss_PrinterEnumValues
**info_p
)
4275 struct spoolss_EnumPrinterDataEx r
;
4276 struct spoolss_PrinterEnumValues
*info
;
4280 r
.in
.handle
= handle
;
4281 r
.in
.key_name
= key_name
;
4283 r
.out
.needed
= &needed
;
4284 r
.out
.count
= &count
;
4287 torture_comment(tctx
, "Testing EnumPrinterDataEx(%s)\n", key_name
);
4289 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterDataEx_r(b
, tctx
, &r
),
4290 "EnumPrinterDataEx failed");
4291 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
4292 r
.in
.offered
= needed
;
4293 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterDataEx_r(b
, tctx
, &r
),
4294 "EnumPrinterDataEx failed");
4297 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDataEx failed");
4299 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx
, info
, count
, needed
, 1);
4311 static bool test_SetPrinterData(struct torture_context
*tctx
,
4312 struct dcerpc_binding_handle
*b
,
4313 struct policy_handle
*handle
,
4314 const char *value_name
,
4315 enum winreg_Type type
,
4318 static bool test_DeletePrinterData(struct torture_context
*tctx
,
4319 struct dcerpc_binding_handle
*b
,
4320 struct policy_handle
*handle
,
4321 const char *value_name
);
4323 static bool test_EnumPrinterData_consistency(struct torture_context
*tctx
,
4324 struct dcerpc_pipe
*p
,
4325 struct policy_handle
*handle
)
4328 struct spoolss_PrinterEnumValues
*info
;
4330 uint32_t value_needed
, data_needed
;
4331 uint32_t value_offered
, data_offered
;
4333 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4335 enum winreg_Type type
;
4338 torture_comment(tctx
, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
4340 torture_assert(tctx
, push_reg_sz(tctx
, &blob
, "torture_data1"), "");
4343 torture_assert(tctx
,
4344 test_SetPrinterData(tctx
, b
, handle
, "torture_value1", type
, blob
.data
, blob
.length
),
4345 "SetPrinterData failed");
4347 blob
= data_blob_string_const("torture_data2");
4349 torture_assert(tctx
,
4350 test_SetPrinterData(tctx
, b
, handle
, "torture_value2", REG_BINARY
, blob
.data
, blob
.length
),
4351 "SetPrinterData failed");
4353 blob
= data_blob_talloc(tctx
, NULL
, 4);
4354 SIVAL(blob
.data
, 0, 0x11223344);
4356 torture_assert(tctx
,
4357 test_SetPrinterData(tctx
, b
, handle
, "torture_value3", type
, blob
.data
, blob
.length
),
4358 "SetPrinterData failed");
4360 torture_assert(tctx
,
4361 test_EnumPrinterDataEx(tctx
, b
, handle
, "PrinterDriverData", &count
, &info
),
4362 "failed to call EnumPrinterDataEx");
4364 /* get the max sizes for value and data */
4366 torture_assert(tctx
,
4367 test_EnumPrinterData(tctx
, p
, handle
, 0, 0, 0,
4368 NULL
, &value_needed
, &data_needed
,
4369 NULL
, NULL
, &result
),
4370 "EnumPrinterData failed");
4371 torture_assert_werr_ok(tctx
, result
, "unexpected result");
4373 /* check if the reply from the EnumPrinterData really matches max values */
4375 for (i
=0; i
< count
; i
++) {
4376 if (info
[i
].value_name_len
> value_needed
) {
4378 talloc_asprintf(tctx
,
4379 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
4380 info
[i
].value_name_len
, value_needed
));
4382 if (info
[i
].data_length
> data_needed
) {
4384 talloc_asprintf(tctx
,
4385 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
4386 info
[i
].data_length
, data_needed
));
4390 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
4391 * sort or not sort the replies by value name, we should be able to do
4392 * the following entry comparison */
4394 data_offered
= data_needed
;
4395 value_offered
= value_needed
;
4397 for (i
=0; i
< count
; i
++) {
4399 const char *value_name
;
4402 torture_assert(tctx
,
4403 test_EnumPrinterData(tctx
, p
, handle
, i
, value_offered
, data_offered
,
4404 &type
, &value_needed
, &data_needed
,
4405 &value_name
, &data
, &result
),
4406 "EnumPrinterData failed");
4408 if (i
-1 == count
) {
4409 torture_assert_werr_equal(tctx
, result
, WERR_NO_MORE_ITEMS
,
4410 "unexpected result");
4413 torture_assert_werr_ok(tctx
, result
, "unexpected result");
4416 torture_assert_int_equal(tctx
, type
, info
[i
].type
, "type mismatch");
4417 torture_assert_int_equal(tctx
, value_needed
, info
[i
].value_name_len
, "value name length mismatch");
4418 torture_assert_str_equal(tctx
, value_name
, info
[i
].value_name
, "value name mismatch");
4419 torture_assert_int_equal(tctx
, data_needed
, info
[i
].data_length
, "data length mismatch");
4420 torture_assert_mem_equal(tctx
, data
, info
[i
].data
->data
, info
[i
].data_length
, "data mismatch");
4423 torture_assert(tctx
,
4424 test_DeletePrinterData(tctx
, b
, handle
, "torture_value1"),
4425 "DeletePrinterData failed");
4426 torture_assert(tctx
,
4427 test_DeletePrinterData(tctx
, b
, handle
, "torture_value2"),
4428 "DeletePrinterData failed");
4429 torture_assert(tctx
,
4430 test_DeletePrinterData(tctx
, b
, handle
, "torture_value3"),
4431 "DeletePrinterData failed");
4433 torture_comment(tctx
, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4438 static bool test_DeletePrinterData(struct torture_context
*tctx
,
4439 struct dcerpc_binding_handle
*b
,
4440 struct policy_handle
*handle
,
4441 const char *value_name
)
4444 struct spoolss_DeletePrinterData r
;
4446 r
.in
.handle
= handle
;
4447 r
.in
.value_name
= value_name
;
4449 torture_comment(tctx
, "Testing DeletePrinterData(%s)\n",
4452 status
= dcerpc_spoolss_DeletePrinterData_r(b
, tctx
, &r
);
4454 torture_assert_ntstatus_ok(tctx
, status
, "DeletePrinterData failed");
4455 torture_assert_werr_ok(tctx
, r
.out
.result
, "DeletePrinterData failed");
4460 static bool test_DeletePrinterDataEx(struct torture_context
*tctx
,
4461 struct dcerpc_binding_handle
*b
,
4462 struct policy_handle
*handle
,
4463 const char *key_name
,
4464 const char *value_name
)
4466 struct spoolss_DeletePrinterDataEx r
;
4468 r
.in
.handle
= handle
;
4469 r
.in
.key_name
= key_name
;
4470 r
.in
.value_name
= value_name
;
4472 torture_comment(tctx
, "Testing DeletePrinterDataEx(%s - %s)\n",
4473 r
.in
.key_name
, r
.in
.value_name
);
4475 torture_assert_ntstatus_ok(tctx
,
4476 dcerpc_spoolss_DeletePrinterDataEx_r(b
, tctx
, &r
),
4477 "DeletePrinterDataEx failed");
4478 torture_assert_werr_ok(tctx
, r
.out
.result
,
4479 "DeletePrinterDataEx failed");
4484 static bool test_DeletePrinterKey(struct torture_context
*tctx
,
4485 struct dcerpc_binding_handle
*b
,
4486 struct policy_handle
*handle
,
4487 const char *key_name
)
4489 struct spoolss_DeletePrinterKey r
;
4491 r
.in
.handle
= handle
;
4492 r
.in
.key_name
= key_name
;
4494 torture_comment(tctx
, "Testing DeletePrinterKey(%s)\n", r
.in
.key_name
);
4496 if (strequal(key_name
, "") && !torture_setting_bool(tctx
, "dangerous", false)) {
4497 torture_skip(tctx
, "not wiping out printer registry - enable dangerous tests to use\n");
4501 torture_assert_ntstatus_ok(tctx
,
4502 dcerpc_spoolss_DeletePrinterKey_r(b
, tctx
, &r
),
4503 "DeletePrinterKey failed");
4504 torture_assert_werr_ok(tctx
, r
.out
.result
,
4505 "DeletePrinterKey failed");
4510 static bool test_winreg_OpenHKLM(struct torture_context
*tctx
,
4511 struct dcerpc_binding_handle
*b
,
4512 struct policy_handle
*handle
)
4514 struct winreg_OpenHKLM r
;
4516 r
.in
.system_name
= NULL
;
4517 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4518 r
.out
.handle
= handle
;
4520 torture_comment(tctx
, "Testing winreg_OpenHKLM\n");
4522 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_OpenHKLM_r(b
, tctx
, &r
), "OpenHKLM failed");
4523 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenHKLM failed");
4528 static void init_winreg_String(struct winreg_String
*name
, const char *s
)
4532 name
->name_len
= 2 * (strlen_m(s
) + 1);
4533 name
->name_size
= name
->name_len
;
4536 name
->name_size
= 0;
4540 static bool test_winreg_OpenKey_opts(struct torture_context
*tctx
,
4541 struct dcerpc_binding_handle
*b
,
4542 struct policy_handle
*hive_handle
,
4543 const char *keyname
,
4545 struct policy_handle
*key_handle
)
4547 struct winreg_OpenKey r
;
4549 r
.in
.parent_handle
= hive_handle
;
4550 init_winreg_String(&r
.in
.keyname
, keyname
);
4551 r
.in
.options
= options
;
4552 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4553 r
.out
.handle
= key_handle
;
4555 torture_comment(tctx
, "Testing winreg_OpenKey(%s)\n", keyname
);
4557 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_OpenKey_r(b
, tctx
, &r
), "OpenKey failed");
4558 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenKey failed");
4563 static bool test_winreg_OpenKey(struct torture_context
*tctx
,
4564 struct dcerpc_binding_handle
*b
,
4565 struct policy_handle
*hive_handle
,
4566 const char *keyname
,
4567 struct policy_handle
*key_handle
)
4569 return test_winreg_OpenKey_opts(tctx
, b
, hive_handle
, keyname
,
4570 REG_OPTION_NON_VOLATILE
, key_handle
);
4573 static bool test_winreg_CloseKey(struct torture_context
*tctx
,
4574 struct dcerpc_binding_handle
*b
,
4575 struct policy_handle
*handle
)
4577 struct winreg_CloseKey r
;
4579 r
.in
.handle
= handle
;
4580 r
.out
.handle
= handle
;
4582 torture_comment(tctx
, "Testing winreg_CloseKey\n");
4584 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_CloseKey_r(b
, tctx
, &r
), "CloseKey failed");
4585 torture_assert_werr_ok(tctx
, r
.out
.result
, "CloseKey failed");
4590 bool test_winreg_QueryValue(struct torture_context
*tctx
,
4591 struct dcerpc_binding_handle
*b
,
4592 struct policy_handle
*handle
,
4593 const char *value_name
,
4594 enum winreg_Type
*type_p
,
4595 uint32_t *data_size_p
,
4596 uint32_t *data_length_p
,
4599 struct winreg_QueryValue r
;
4600 enum winreg_Type type
= REG_NONE
;
4601 uint32_t data_size
= 0;
4602 uint32_t data_length
= 0;
4603 struct winreg_String valuename
;
4604 uint8_t *data
= NULL
;
4606 init_winreg_String(&valuename
, value_name
);
4608 data
= talloc_zero_array(tctx
, uint8_t, 0);
4610 r
.in
.handle
= handle
;
4611 r
.in
.value_name
= &valuename
;
4613 r
.in
.data_size
= &data_size
;
4614 r
.in
.data_length
= &data_length
;
4618 r
.out
.data_size
= &data_size
;
4619 r
.out
.data_length
= &data_length
;
4621 torture_comment(tctx
, "Testing winreg_QueryValue(%s)\n", value_name
);
4623 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_QueryValue_r(b
, tctx
, &r
), "QueryValue failed");
4624 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
4625 *r
.in
.data_size
= *r
.out
.data_size
;
4626 data
= talloc_zero_array(tctx
, uint8_t, *r
.in
.data_size
);
4629 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_QueryValue_r(b
, tctx
, &r
), "QueryValue failed");
4631 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryValue failed");
4634 *type_p
= *r
.out
.type
;
4637 *data_size_p
= *r
.out
.data_size
;
4639 if (data_length_p
) {
4640 *data_length_p
= *r
.out
.data_length
;
4643 *data_p
= r
.out
.data
;
4649 static bool test_winreg_query_printerdata(struct torture_context
*tctx
,
4650 struct dcerpc_binding_handle
*b
,
4651 struct policy_handle
*handle
,
4652 const char *printer_name
,
4653 const char *key_name
,
4654 const char *value_name
,
4655 enum winreg_Type
*w_type
,
4660 const char *printer_key
;
4661 struct policy_handle key_handle
;
4663 printer_key
= talloc_asprintf(tctx
, "%s\\%s\\%s",
4664 TOP_LEVEL_PRINT_PRINTERS_KEY
, printer_name
, key_name
);
4666 torture_assert(tctx
,
4667 test_winreg_OpenKey(tctx
, b
, handle
, printer_key
, &key_handle
), "");
4669 torture_assert(tctx
,
4670 test_winreg_QueryValue(tctx
, b
, &key_handle
, value_name
, w_type
, w_size
, w_length
, w_data
), "");
4672 torture_assert(tctx
,
4673 test_winreg_CloseKey(tctx
, b
, &key_handle
), "");
4678 static bool test_GetForm_winreg(struct torture_context
*tctx
,
4679 struct dcerpc_binding_handle
*b
,
4680 struct policy_handle
*handle
,
4681 const char *key_name
,
4682 const char *form_name
,
4683 enum winreg_Type
*w_type
,
4688 struct policy_handle key_handle
;
4690 torture_assert(tctx
,
4691 test_winreg_OpenKey(tctx
, b
, handle
, key_name
, &key_handle
), "");
4693 torture_assert(tctx
,
4694 test_winreg_QueryValue(tctx
, b
, &key_handle
, form_name
, w_type
, w_size
, w_length
, w_data
), "");
4696 torture_assert(tctx
,
4697 test_winreg_CloseKey(tctx
, b
, &key_handle
), "");
4702 static bool test_winreg_symbolic_link(struct torture_context
*tctx
,
4703 struct dcerpc_binding_handle
*b
,
4704 struct policy_handle
*handle
,
4705 const char *symlink_keyname
,
4706 const char *symlink_destination
)
4708 /* check if the first key is a symlink to the second key */
4710 enum winreg_Type w_type
;
4714 struct policy_handle key_handle
;
4718 if (torture_setting_bool(tctx
, "samba3", false)) {
4719 torture_skip(tctx
, "skip winreg symlink test against samba");
4722 torture_assert(tctx
,
4723 test_winreg_OpenKey_opts(tctx
, b
, handle
, symlink_keyname
, REG_OPTION_OPEN_LINK
, &key_handle
),
4724 "failed to open key link");
4726 torture_assert(tctx
,
4727 test_winreg_QueryValue(tctx
, b
, &key_handle
,
4728 "SymbolicLinkValue",
4729 &w_type
, &w_size
, &w_length
, &w_data
),
4730 "failed to query for 'SymbolicLinkValue' attribute");
4732 torture_assert_int_equal(tctx
, w_type
, REG_LINK
, "unexpected type");
4734 blob
= data_blob(w_data
, w_size
);
4735 str
= reg_val_data_string(tctx
, REG_SZ
, blob
);
4737 torture_assert_str_equal(tctx
, str
, symlink_destination
, "unexpected symlink target string");
4739 torture_assert(tctx
,
4740 test_winreg_CloseKey(tctx
, b
, &key_handle
),
4741 "failed to close key link");
4746 static const char *strip_unc(const char *unc
)
4754 if (unc
[0] == '\\' && unc
[1] == '\\') {
4758 name
= strchr(unc
, '\\');
4766 static bool test_GetPrinterInfo_winreg(struct torture_context
*tctx
,
4767 struct dcerpc_binding_handle
*b
,
4768 struct policy_handle
*handle
,
4769 const char *printer_name
,
4770 struct dcerpc_binding_handle
*winreg_handle
,
4771 struct policy_handle
*hive_handle
)
4773 union spoolss_PrinterInfo info
;
4774 const char *keys
[] = {
4775 TOP_LEVEL_CONTROL_PRINTERS_KEY
,
4776 TOP_LEVEL_PRINT_PRINTERS_KEY
4779 const char *printername
, *sharename
;
4781 torture_comment(tctx
, "Testing Printer Info and winreg consistency\n");
4783 torture_assert(tctx
,
4784 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
4785 "failed to get printer info level 2");
4787 printername
= strip_unc(info
.info2
.printername
);
4788 sharename
= strip_unc(info
.info2
.sharename
);
4790 #define test_sz(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_SZ, "unexpected type");\
4803 blob = data_blob(w_data, w_size);\
4804 str = reg_val_data_string(tctx, REG_SZ, blob);\
4805 if (w_size == 2 && iname == NULL) {\
4806 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4808 torture_assert_str_equal(tctx, str, iname,\
4809 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4813 #define test_dword(wname, iname) \
4816 enum winreg_Type w_type;\
4820 torture_assert(tctx,\
4821 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4822 &w_type, &w_size, &w_length, &w_data),\
4823 "failed to query winreg");\
4824 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4825 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4826 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4827 value = IVAL(w_data, 0);\
4828 torture_assert_int_equal(tctx, value, iname,\
4829 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4832 #define test_binary(wname, iname) \
4834 enum winreg_Type w_type;\
4838 torture_assert(tctx,\
4839 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4840 &w_type, &w_size, &w_length, &w_data),\
4841 "failed to query winreg");\
4842 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4843 torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4844 torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4849 #define test_dm(wname, iname) \
4852 struct spoolss_DeviceMode dm;\
4853 enum ndr_err_code ndr_err;\
4854 enum winreg_Type w_type;\
4858 torture_assert(tctx,\
4859 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4860 &w_type, &w_size, &w_length, &w_data),\
4861 "failed to query winreg");\
4862 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4863 blob = data_blob(w_data, w_size);\
4864 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4865 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4866 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4867 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4871 #define test_sd(wname, iname) \
4874 struct security_descriptor sd;\
4875 enum ndr_err_code ndr_err;\
4876 enum winreg_Type w_type;\
4880 torture_assert(tctx,\
4881 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4882 &w_type, &w_size, &w_length, &w_data),\
4883 "failed to query winreg");\
4884 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4885 blob = data_blob(w_data, w_size);\
4886 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4887 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4888 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4889 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4893 #define test_multi_sz(wname, iname) \
4896 const char **array;\
4897 enum winreg_Type w_type;\
4902 torture_assert(tctx,\
4903 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4904 &w_type, &w_size, &w_length, &w_data),\
4905 "failed to query winreg");\
4906 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4907 blob = data_blob(w_data, w_size);\
4908 torture_assert(tctx, \
4909 pull_reg_multi_sz(tctx, &blob, &array),\
4910 "failed to pull multi sz");\
4911 for (i=0; array[i] != NULL; i++) {\
4912 torture_assert_str_equal(tctx, array[i], iname[i],\
4913 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4917 if (!test_winreg_symbolic_link(tctx
, winreg_handle
, hive_handle
,
4918 TOP_LEVEL_CONTROL_PRINTERS_KEY
,
4919 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4921 torture_warning(tctx
, "failed to check for winreg symlink");
4924 for (i
=0; i
< ARRAY_SIZE(keys
); i
++) {
4926 const char *printer_key
;
4927 struct policy_handle key_handle
;
4929 printer_key
= talloc_asprintf(tctx
, "%s\\%s",
4930 keys
[i
], printer_name
);
4932 torture_assert(tctx
,
4933 test_winreg_OpenKey(tctx
, winreg_handle
, hive_handle
, printer_key
, &key_handle
), "");
4935 test_sz("Name", printername
);
4936 test_sz("Share Name", sharename
);
4937 test_sz("Port", info
.info2
.portname
);
4938 test_sz("Printer Driver", info
.info2
.drivername
);
4939 test_sz("Description", info
.info2
.comment
);
4940 test_sz("Location", info
.info2
.location
);
4941 test_sz("Separator File", info
.info2
.sepfile
);
4942 test_sz("Print Processor", info
.info2
.printprocessor
);
4943 test_sz("Datatype", info
.info2
.datatype
);
4944 test_sz("Parameters", info
.info2
.parameters
);
4945 /* winreg: 0, spoolss not */
4946 /* test_dword("Attributes", info.info2.attributes); */
4947 test_dword("Priority", info
.info2
.priority
);
4948 test_dword("Default Priority", info
.info2
.defaultpriority
);
4949 /* winreg: 60, spoolss: 0 */
4950 /* test_dword("StartTime", info.info2.starttime); */
4951 /* test_dword("UntilTime", info.info2.untiltime); */
4952 /* winreg != spoolss */
4953 /* test_dword("Status", info.info2.status); */
4954 test_dm("Default DevMode", info
.info2
.devmode
);
4955 test_sd("Security", info
.info2
.secdesc
);
4957 torture_assert(tctx
,
4958 test_winreg_CloseKey(tctx
, winreg_handle
, &key_handle
), "");
4963 torture_comment(tctx
, "Printer Info and winreg consistency test succeeded\n\n");
4968 static bool test_GetPrintserverInfo_winreg(struct torture_context
*tctx
,
4969 struct dcerpc_binding_handle
*b
,
4970 struct policy_handle
*handle
,
4971 struct dcerpc_binding_handle
*winreg_handle
,
4972 struct policy_handle
*hive_handle
)
4974 union spoolss_PrinterInfo info
;
4975 struct policy_handle key_handle
;
4977 torture_comment(tctx
,
4978 "Testing Printserver Info and winreg consistency\n");
4980 torture_assert(tctx
,
4981 test_GetPrinter_level(tctx
, b
, handle
, 3, &info
),
4982 "failed to get printer info level 2");
4984 torture_assert(tctx
,
4985 test_winreg_OpenKey(tctx
, winreg_handle
, hive_handle
,
4986 TOP_LEVEL_CONTROL_KEY
, &key_handle
), "");
4988 test_sd("ServerSecurityDescriptor", info
.info3
.secdesc
);
4990 torture_assert(tctx
,
4991 test_winreg_CloseKey(tctx
, winreg_handle
, &key_handle
), "");
4995 torture_comment(tctx
,
4996 "Printserver Info and winreg consistency test succeeded\n\n");
5002 static bool test_PrintProcessors(struct torture_context
*tctx
,
5003 struct dcerpc_binding_handle
*b
,
5004 const char *environment
,
5005 struct dcerpc_binding_handle
*winreg_handle
,
5006 struct policy_handle
*hive_handle
)
5008 union spoolss_PrintProcessorInfo
*info
;
5012 torture_comment(tctx
, "Testing Print Processor Info and winreg consistency\n");
5014 torture_assert(tctx
,
5015 test_EnumPrintProcessors_level(tctx
, b
, environment
, 1, &count
, &info
, WERR_OK
),
5016 "failed to enum print processors level 1");
5018 for (i
=0; i
< count
; i
++) {
5020 const char *processor_key
;
5021 struct policy_handle key_handle
;
5023 processor_key
= talloc_asprintf(tctx
, "%s\\%s\\Print Processors\\%s",
5024 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY
,
5026 info
[i
].info1
.print_processor_name
);
5028 torture_assert(tctx
,
5029 test_winreg_OpenKey(tctx
, winreg_handle
, hive_handle
, processor_key
, &key_handle
), "");
5031 /* nothing to check in there so far */
5033 torture_assert(tctx
,
5034 test_winreg_CloseKey(tctx
, winreg_handle
, &key_handle
), "");
5037 torture_comment(tctx
, "Print Processor Info and winreg consistency test succeeded\n\n");
5042 static bool test_GetPrinterDriver2_level(struct torture_context
*tctx
,
5043 struct dcerpc_binding_handle
*b
,
5044 struct policy_handle
*handle
,
5045 const char *driver_name
,
5046 const char *architecture
,
5048 uint32_t client_major_version
,
5049 uint32_t client_minor_version
,
5050 union spoolss_DriverInfo
*info_p
,
5053 static const char *strip_path(const char *path
)
5061 p
= strrchr(path
, '\\');
5069 static const char **strip_paths(const char **path_array
)
5073 if (path_array
== NULL
) {
5077 for (i
=0; path_array
[i
] != NULL
; i
++) {
5078 path_array
[i
] = strip_path(path_array
[i
]);
5084 static const char *driver_winreg_date(TALLOC_CTX
*mem_ctx
, NTTIME nt
)
5090 return talloc_strdup(mem_ctx
, "01/01/1601");
5093 t
= nt_time_to_unix(nt
);
5096 return talloc_asprintf(mem_ctx
, "%02d/%02d/%04d",
5097 tm
->tm_mon
+ 1, tm
->tm_mday
, tm
->tm_year
+ 1900);
5100 static const char *driver_winreg_version(TALLOC_CTX
*mem_ctx
, uint64_t v
)
5102 return talloc_asprintf(mem_ctx
, "%u.%u.%u.%u",
5103 (unsigned)((v
>> 48) & 0xFFFF),
5104 (unsigned)((v
>> 32) & 0xFFFF),
5105 (unsigned)((v
>> 16) & 0xFFFF),
5106 (unsigned)(v
& 0xFFFF));
5109 static bool test_GetDriverInfo_winreg(struct torture_context
*tctx
,
5110 struct dcerpc_binding_handle
*b
,
5111 struct policy_handle
*handle
,
5112 const char *printer_name
,
5113 const char *driver_name
,
5114 const char *environment
,
5115 enum spoolss_DriverOSVersion version
,
5116 struct dcerpc_binding_handle
*winreg_handle
,
5117 struct policy_handle
*hive_handle
,
5118 const char *server_name_slash
)
5120 WERROR result
= WERR_OK
;
5121 union spoolss_DriverInfo info
;
5122 const char *driver_key
;
5123 struct policy_handle key_handle
;
5125 const char *driver_path
;
5126 const char *data_file
;
5127 const char *config_file
;
5128 const char *help_file
;
5129 const char **dependent_files
;
5131 const char *driver_date
;
5132 const char *inbox_driver_date
;
5134 const char *driver_version
;
5135 const char *inbox_driver_version
;
5137 ZERO_STRUCT(key_handle
);
5139 torture_comment(tctx
, "Testing Driver Info and winreg consistency\n");
5141 driver_key
= talloc_asprintf(tctx
, "%s\\%s\\Drivers\\Version-%d\\%s",
5142 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY
,
5147 torture_assert(tctx
,
5148 test_winreg_OpenKey(tctx
, winreg_handle
, hive_handle
, driver_key
, &key_handle
),
5149 "failed to open driver key");
5151 if (torture_setting_bool(tctx
, "samba3", false) ||
5152 torture_setting_bool(tctx
, "w2k3", false)) {
5157 torture_assert(tctx
,
5158 test_GetPrinterDriver2_level(tctx
, b
, handle
, driver_name
, environment
, 8, version
, 0, &info
, &result
),
5159 "failed to get driver info level 8");
5161 torture_assert(tctx
,
5162 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, environment
, 8, driver_name
, &info
),
5163 "failed to get driver info level 8");
5166 if (W_ERROR_EQUAL(result
, WERR_INVALID_LEVEL
)) {
5170 driver_path
= strip_path(info
.info8
.driver_path
);
5171 data_file
= strip_path(info
.info8
.data_file
);
5172 config_file
= strip_path(info
.info8
.config_file
);
5173 help_file
= strip_path(info
.info8
.help_file
);
5174 dependent_files
= strip_paths(info
.info8
.dependent_files
);
5176 driver_date
= driver_winreg_date(tctx
, info
.info8
.driver_date
);
5177 inbox_driver_date
= driver_winreg_date(tctx
, info
.info8
.min_inbox_driver_ver_date
);
5179 driver_version
= driver_winreg_version(tctx
, info
.info8
.driver_version
);
5180 inbox_driver_version
= driver_winreg_version(tctx
, info
.info8
.min_inbox_driver_ver_version
);
5182 test_sz("Configuration File", config_file
);
5183 test_sz("Data File", data_file
);
5184 test_sz("Datatype", info
.info8
.default_datatype
);
5185 test_sz("Driver", driver_path
);
5186 test_sz("DriverDate", driver_date
);
5187 test_sz("DriverVersion", driver_version
);
5188 test_sz("HardwareID", info
.info8
.hardware_id
);
5189 test_sz("Help File", help_file
);
5190 test_sz("InfPath", info
.info8
.inf_path
);
5191 test_sz("Manufacturer", info
.info8
.manufacturer_name
);
5192 test_sz("MinInboxDriverVerDate", inbox_driver_date
);
5193 test_sz("MinInboxDriverVerVersion", inbox_driver_version
);
5194 test_sz("Monitor", info
.info8
.monitor_name
);
5195 test_sz("OEM URL", info
.info8
.manufacturer_url
);
5196 test_sz("Print Processor", info
.info8
.print_processor
);
5197 test_sz("Provider", info
.info8
.provider
);
5198 test_sz("VendorSetup", info
.info8
.vendor_setup
);
5199 test_multi_sz("ColorProfiles", info
.info8
.color_profiles
);
5200 test_multi_sz("Dependent Files", dependent_files
);
5201 test_multi_sz("CoreDependencies", info
.info8
.core_driver_dependencies
);
5202 test_multi_sz("Previous Names", info
.info8
.previous_names
);
5203 /* test_dword("Attributes", ?); */
5204 test_dword("PrinterDriverAttributes", info
.info8
.printer_driver_attributes
);
5205 test_dword("Version", info
.info8
.version
);
5206 /* test_dword("TempDir", ?); */
5211 torture_assert(tctx
,
5212 test_GetPrinterDriver2_level(tctx
, b
, handle
, driver_name
, environment
, 6, version
, 0, &info
, &result
),
5213 "failed to get driver info level 6");
5215 torture_assert(tctx
,
5216 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, environment
, 6, driver_name
, &info
),
5217 "failed to get driver info level 6");
5220 driver_path
= strip_path(info
.info6
.driver_path
);
5221 data_file
= strip_path(info
.info6
.data_file
);
5222 config_file
= strip_path(info
.info6
.config_file
);
5223 help_file
= strip_path(info
.info6
.help_file
);
5224 dependent_files
= strip_paths(info
.info6
.dependent_files
);
5226 driver_date
= driver_winreg_date(tctx
, info
.info6
.driver_date
);
5228 driver_version
= driver_winreg_version(tctx
, info
.info6
.driver_version
);
5230 test_sz("Configuration File", config_file
);
5231 test_sz("Data File", data_file
);
5232 test_sz("Datatype", info
.info6
.default_datatype
);
5233 test_sz("Driver", driver_path
);
5234 if (torture_setting_bool(tctx
, "w2k3", false)) {
5235 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, 8);
5236 push_nttime(blob
.data
, 0, info
.info6
.driver_date
);
5237 test_binary("DriverDate", blob
);
5238 SBVAL(blob
.data
, 0, info
.info6
.driver_version
);
5239 test_binary("DriverVersion", blob
);
5241 test_sz("DriverDate", driver_date
);
5242 test_sz("DriverVersion", driver_version
);
5244 test_sz("HardwareID", info
.info6
.hardware_id
);
5245 test_sz("Help File", help_file
);
5246 test_sz("Manufacturer", info
.info6
.manufacturer_name
);
5247 test_sz("Monitor", info
.info6
.monitor_name
);
5248 test_sz("OEM URL", info
.info6
.manufacturer_url
);
5249 test_sz("Provider", info
.info6
.provider
);
5250 test_multi_sz("Dependent Files", dependent_files
);
5251 test_multi_sz("Previous Names", info
.info6
.previous_names
);
5252 /* test_dword("Attributes", ?); */
5253 test_dword("Version", info
.info6
.version
);
5254 /* test_dword("TempDir", ?); */
5257 torture_assert(tctx
,
5258 test_GetPrinterDriver2_level(tctx
, b
, handle
, driver_name
, environment
, 3, version
, 0, &info
, &result
),
5259 "failed to get driver info level 3");
5261 torture_assert(tctx
,
5262 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, environment
, 3, driver_name
, &info
),
5263 "failed to get driver info level 3");
5266 driver_path
= strip_path(info
.info3
.driver_path
);
5267 data_file
= strip_path(info
.info3
.data_file
);
5268 config_file
= strip_path(info
.info3
.config_file
);
5269 help_file
= strip_path(info
.info3
.help_file
);
5270 dependent_files
= strip_paths(info
.info3
.dependent_files
);
5272 test_sz("Configuration File", config_file
);
5273 test_sz("Data File", data_file
);
5274 test_sz("Datatype", info
.info3
.default_datatype
);
5275 test_sz("Driver", driver_path
);
5276 test_sz("Help File", help_file
);
5277 test_sz("Monitor", info
.info3
.monitor_name
);
5278 test_multi_sz("Dependent Files", dependent_files
);
5279 /* test_dword("Attributes", ?); */
5280 test_dword("Version", info
.info3
.version
);
5281 /* test_dword("TempDir", ?); */
5284 torture_assert(tctx
,
5285 test_winreg_CloseKey(tctx
, winreg_handle
, &key_handle
), "");
5287 torture_comment(tctx
, "Driver Info and winreg consistency test succeeded\n\n");
5295 static bool test_SetPrinterData(struct torture_context
*tctx
,
5296 struct dcerpc_binding_handle
*b
,
5297 struct policy_handle
*handle
,
5298 const char *value_name
,
5299 enum winreg_Type type
,
5303 struct spoolss_SetPrinterData r
;
5305 r
.in
.handle
= handle
;
5306 r
.in
.value_name
= value_name
;
5309 r
.in
.offered
= offered
;
5311 torture_comment(tctx
, "Testing SetPrinterData(%s)\n",
5314 torture_assert_ntstatus_ok(tctx
,
5315 dcerpc_spoolss_SetPrinterData_r(b
, tctx
, &r
),
5316 "SetPrinterData failed");
5317 torture_assert_werr_ok(tctx
, r
.out
.result
,
5318 "SetPrinterData failed");
5323 static bool test_SetPrinterData_matrix(struct torture_context
*tctx
,
5324 struct dcerpc_binding_handle
*b
,
5325 struct policy_handle
*handle
,
5326 const char *printer_name
,
5327 struct dcerpc_binding_handle
*winreg_handle
,
5328 struct policy_handle
*hive_handle
)
5330 const char *values
[] = {
5334 /* FIXME: not working with s3 atm. */
5340 /* FIXME: not working with s3 atm. */
5347 for (i
=0; i
< ARRAY_SIZE(values
); i
++) {
5349 enum winreg_Type type
, expected_type
= REG_SZ
;
5354 torture_assert(tctx
, push_reg_sz(tctx
, &blob
, "dog"), "");
5357 torture_assert(tctx
,
5358 test_SetPrinterData(tctx
, b
, handle
, values
[i
], REG_SZ
, blob
.data
, blob
.length
),
5359 "SetPrinterData failed");
5361 torture_assert(tctx
,
5362 test_GetPrinterData_checktype(tctx
, b
, handle
, values
[i
], &expected_type
, &type
, &data
, &needed
),
5363 "GetPrinterData failed");
5365 torture_assert_int_equal(tctx
, type
, REG_SZ
, "type mismatch");
5366 torture_assert_int_equal(tctx
, needed
, blob
.length
, "size mismatch");
5367 torture_assert_mem_equal(tctx
, data
, blob
.data
, blob
.length
, "buffer mismatch");
5369 if (winreg_handle
&& hive_handle
) {
5371 enum winreg_Type w_type
;
5376 torture_assert(tctx
,
5377 test_winreg_query_printerdata(tctx
, winreg_handle
, hive_handle
,
5378 printer_name
, "PrinterDriverData", values
[i
],
5379 &w_type
, &w_size
, &w_length
, &w_data
), "");
5381 torture_assert_int_equal(tctx
, w_type
, REG_SZ
, "winreg type mismatch");
5382 torture_assert_int_equal(tctx
, w_size
, blob
.length
, "winreg size mismatch");
5383 torture_assert_int_equal(tctx
, w_length
, blob
.length
, "winreg length mismatch");
5384 torture_assert_mem_equal(tctx
, w_data
, blob
.data
, blob
.length
, "winreg buffer mismatch");
5387 torture_assert(tctx
,
5388 test_DeletePrinterData(tctx
, b
, handle
, values
[i
]),
5389 "DeletePrinterData failed");
5396 static bool test_EnumPrinterKey(struct torture_context
*tctx
,
5397 struct dcerpc_binding_handle
*b
,
5398 struct policy_handle
*handle
,
5399 const char *key_name
,
5400 const char ***array
);
5402 static bool test_SetPrinterDataEx(struct torture_context
*tctx
,
5403 struct dcerpc_binding_handle
*b
,
5404 struct policy_handle
*handle
,
5405 const char *key_name
,
5406 const char *value_name
,
5407 enum winreg_Type type
,
5412 struct spoolss_SetPrinterDataEx r
;
5414 r
.in
.handle
= handle
;
5415 r
.in
.key_name
= key_name
;
5416 r
.in
.value_name
= value_name
;
5419 r
.in
.offered
= offered
;
5421 torture_comment(tctx
, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
5422 r
.in
.key_name
, r
.in
.value_name
, str_regtype(r
.in
.type
), r
.in
.offered
);
5424 status
= dcerpc_spoolss_SetPrinterDataEx_r(b
, tctx
, &r
);
5426 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinterDataEx failed");
5427 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinterDataEx failed");
5432 static bool test_SetPrinterDataEx_keys(struct torture_context
*tctx
,
5433 struct dcerpc_pipe
*p
,
5434 struct policy_handle
*handle
)
5436 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5437 const char *value_name
= "dog";
5438 const char *keys
[] = {
5441 "torturedataex_with_subkey\\subkey",
5442 "torturedataex_with_subkey\\subkey:0",
5443 "torturedataex_with_subkey\\subkey:1",
5444 "torturedataex_with_subkey\\subkey\\subsubkey",
5445 "torturedataex_with_subkey\\subkey\\subsubkey:0",
5446 "torturedataex_with_subkey\\subkey\\subsubkey:1",
5453 "torture/data ex/sub",
5456 "torture//data ex/sub",
5457 "torture//data ex//sub",
5461 for (i
=0; i
< ARRAY_SIZE(keys
); i
++) {
5465 enum winreg_Type type
;
5466 DATA_BLOB blob_in
, blob_out
;
5467 const char **subkeys
;
5469 struct spoolss_PrinterEnumValues
*einfo
;
5472 blob_in
= data_blob_talloc(tctx
, NULL
, 42);
5474 generate_random_buffer(blob_in
.data
, blob_in
.length
);
5476 torture_assert(tctx
,
5477 test_SetPrinterDataEx(tctx
, b
, handle
, keys
[i
], value_name
, REG_BINARY
, blob_in
.data
, blob_in
.length
),
5478 "failed to call SetPrinterDataEx");
5480 torture_assert(tctx
,
5481 test_GetPrinterDataEx(tctx
, p
, handle
, keys
[i
], value_name
, &type
, &blob_out
.data
, &needed
),
5482 "failed to call GetPrinterDataEx");
5484 blob_out
.length
= needed
;
5485 torture_assert(tctx
,
5486 test_EnumPrinterDataEx(tctx
, b
, handle
, keys
[i
], &ecount
, &einfo
),
5487 "failed to call EnumPrinterDataEx");
5489 torture_assert_int_equal(tctx
, type
, REG_BINARY
, "type mismatch");
5490 torture_assert_int_equal(tctx
, blob_out
.length
, blob_in
.length
, "size mismatch");
5491 torture_assert_mem_equal(tctx
, blob_out
.data
, blob_in
.data
, blob_in
.length
, "buffer mismatch");
5493 torture_assert_int_equal(tctx
, ecount
, 1, "unexpected enum count");
5494 torture_assert_str_equal(tctx
, einfo
[0].value_name
, value_name
, "value_name mismatch");
5495 torture_assert_int_equal(tctx
, einfo
[0].value_name_len
, strlen_m_term(value_name
)*2, "unexpected value_name_len");
5496 torture_assert_int_equal(tctx
, einfo
[0].type
, REG_BINARY
, "type mismatch");
5497 torture_assert_int_equal(tctx
, einfo
[0].data_length
, blob_in
.length
, "size mismatch");
5498 if (einfo
[0].data_length
> 0) {
5499 torture_assert_mem_equal(tctx
, einfo
[0].data
->data
, blob_in
.data
, blob_in
.length
, "buffer mismatch");
5502 key
= talloc_strdup(tctx
, keys
[i
]);
5504 if (!test_DeletePrinterDataEx(tctx
, b
, handle
, keys
[i
], value_name
)) {
5508 c
= strchr(key
, '\\');
5512 /* we have subkeys */
5516 if (!test_EnumPrinterKey(tctx
, b
, handle
, key
, &subkeys
)) {
5520 for (k
=0; subkeys
&& subkeys
[k
]; k
++) {
5522 const char *current_key
= talloc_asprintf(tctx
, "%s\\%s", key
, subkeys
[k
]);
5524 if (!test_DeletePrinterKey(tctx
, b
, handle
, current_key
)) {
5529 if (!test_DeletePrinterKey(tctx
, b
, handle
, key
)) {
5534 if (!test_DeletePrinterKey(tctx
, b
, handle
, key
)) {
5543 static bool test_SetPrinterDataEx_values(struct torture_context
*tctx
,
5544 struct dcerpc_pipe
*p
,
5545 struct policy_handle
*handle
)
5547 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5548 const char *key
= "torturedataex";
5549 const char *values
[] = {
5559 for (i
=0; i
< ARRAY_SIZE(values
); i
++) {
5561 enum winreg_Type type
= REG_NONE
;
5562 DATA_BLOB blob_in
= data_blob_null
;
5563 DATA_BLOB blob_out
= data_blob_null
;
5565 struct spoolss_PrinterEnumValues
*einfo
;
5566 uint32_t needed
= 0;
5568 if (torture_setting_bool(tctx
, "samba3", false)) {
5570 q
= strrchr(values
[i
], ',');
5572 torture_comment(tctx
, "skipping valuename '%s' including ',' character against Samba3\n",
5578 blob_in
= data_blob_talloc(tctx
, NULL
, 42);
5580 generate_random_buffer(blob_in
.data
, blob_in
.length
);
5582 torture_assert(tctx
,
5583 test_SetPrinterDataEx(tctx
, b
, handle
, key
, values
[i
], REG_BINARY
, blob_in
.data
, blob_in
.length
),
5584 "failed to call SetPrinterDataEx");
5586 torture_assert(tctx
,
5587 test_GetPrinterDataEx(tctx
, p
, handle
, key
, values
[i
], &type
, &blob_out
.data
, &needed
),
5588 "failed to call GetPrinterDataEx");
5590 blob_out
.length
= needed
;
5591 torture_assert(tctx
,
5592 test_EnumPrinterDataEx(tctx
, b
, handle
, key
, &ecount
, &einfo
),
5593 "failed to call EnumPrinterDataEx");
5595 torture_assert_int_equal(tctx
, type
, REG_BINARY
, "type mismatch");
5596 torture_assert_int_equal(tctx
, blob_out
.length
, blob_in
.length
, "size mismatch");
5597 torture_assert_mem_equal(tctx
, blob_out
.data
, blob_in
.data
, blob_in
.length
, "buffer mismatch");
5599 torture_assert_int_equal(tctx
, ecount
, 1, "unexpected enum count");
5600 torture_assert_str_equal(tctx
, einfo
[0].value_name
, values
[i
], "value_name mismatch");
5601 torture_assert_int_equal(tctx
, einfo
[0].value_name_len
, strlen_m_term(values
[i
])*2, "unexpected value_name_len");
5602 torture_assert_int_equal(tctx
, einfo
[0].type
, REG_BINARY
, "type mismatch");
5603 torture_assert_int_equal(tctx
, einfo
[0].data_length
, blob_in
.length
, "size mismatch");
5604 if (einfo
[0].data_length
> 0) {
5605 torture_assert_mem_equal(tctx
, einfo
[0].data
->data
, blob_in
.data
, blob_in
.length
, "buffer mismatch");
5608 torture_assert(tctx
,
5609 test_DeletePrinterDataEx(tctx
, b
, handle
, key
, values
[i
]),
5610 "failed to call DeletePrinterDataEx");
5617 static bool test_SetPrinterDataEx_matrix(struct torture_context
*tctx
,
5618 struct dcerpc_pipe
*p
,
5619 struct policy_handle
*handle
,
5620 const char *printername
,
5621 struct dcerpc_binding_handle
*winreg_handle
,
5622 struct policy_handle
*hive_handle
)
5624 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5625 const char *value_name
= "dog";
5626 const char *key_name
= "torturedataex";
5627 enum winreg_Type types
[] = {
5633 const char *str
= "abcdefghi";
5636 for (t
=0; t
< ARRAY_SIZE(types
); t
++) {
5637 for (s
=0; s
< strlen(str
); s
++) {
5639 enum winreg_Type type
;
5640 const char *string
= talloc_strndup(tctx
, str
, s
);
5641 const char *array
[2];
5642 DATA_BLOB blob
= data_blob_string_const(string
);
5645 uint32_t needed
, offered
= 0;
5647 struct spoolss_PrinterEnumValues
*einfo
;
5649 array
[0] = talloc_strdup(tctx
, string
);
5652 if (types
[t
] == REG_DWORD
) {
5659 offered
= blob
.length
;
5662 data
= data_blob_talloc(tctx
, NULL
, 4);
5663 SIVAL(data
.data
, 0, 0x12345678);
5667 torture_assert(tctx
, push_reg_sz(tctx
, &data
, string
), "");
5669 offered
= data
.length
;
5670 /*strlen_m_term(data.string)*2;*/
5673 torture_assert(tctx
, push_reg_multi_sz(tctx
, &data
, array
), "");
5674 type
= REG_MULTI_SZ
;
5675 offered
= data
.length
;
5678 torture_fail(tctx
, talloc_asprintf(tctx
, "type %d untested\n", types
[t
]));
5681 torture_assert(tctx
,
5682 test_SetPrinterDataEx(tctx
, b
, handle
, key_name
, value_name
, types
[t
], data
.data
, offered
),
5683 "failed to call SetPrinterDataEx");
5685 torture_assert(tctx
,
5686 test_GetPrinterDataEx_checktype(tctx
, p
, handle
, key_name
, value_name
, &types
[t
], &type
, &data_out
, &needed
),
5687 "failed to call GetPrinterDataEx");
5689 torture_assert(tctx
,
5690 test_EnumPrinterDataEx(tctx
, b
, handle
, key_name
, &ecount
, &einfo
),
5691 "failed to call EnumPrinterDataEx");
5693 torture_assert_int_equal(tctx
, types
[t
], type
, "type mismatch");
5694 torture_assert_int_equal(tctx
, needed
, offered
, "size mismatch");
5695 torture_assert_mem_equal(tctx
, data_out
, data
.data
, offered
, "buffer mismatch");
5697 torture_assert_int_equal(tctx
, ecount
, 1, "unexpected enum count");
5698 torture_assert_str_equal(tctx
, einfo
[0].value_name
, value_name
, "value_name mismatch");
5699 torture_assert_int_equal(tctx
, einfo
[0].value_name_len
, strlen_m_term(value_name
)*2, "unexpected value_name_len");
5700 torture_assert_int_equal(tctx
, einfo
[0].type
, types
[t
], "type mismatch");
5701 torture_assert_int_equal(tctx
, einfo
[0].data_length
, offered
, "size mismatch");
5702 if (einfo
[0].data_length
> 0) {
5703 torture_assert_mem_equal(tctx
, einfo
[0].data
->data
, data
.data
, offered
, "buffer mismatch");
5706 if (winreg_handle
&& hive_handle
) {
5707 enum winreg_Type w_type
;
5712 torture_assert(tctx
,
5713 test_winreg_query_printerdata(tctx
, winreg_handle
, hive_handle
,
5714 printername
, key_name
, value_name
,
5715 &w_type
, &w_size
, &w_length
, &w_data
), "");
5717 torture_assert_int_equal(tctx
, w_type
, types
[t
], "winreg type mismatch");
5718 torture_assert_int_equal(tctx
, w_size
, offered
, "winreg size mismatch");
5719 torture_assert_int_equal(tctx
, w_length
, offered
, "winreg length mismatch");
5720 torture_assert_mem_equal(tctx
, w_data
, data
.data
, offered
, "winreg buffer mismatch");
5723 torture_assert(tctx
,
5724 test_DeletePrinterDataEx(tctx
, b
, handle
, key_name
, value_name
),
5725 "failed to call DeletePrinterDataEx");
5732 static bool test_PrinterData_winreg(struct torture_context
*tctx
,
5733 struct dcerpc_pipe
*p
,
5734 struct policy_handle
*handle
,
5735 const char *printer_name
)
5737 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5738 struct dcerpc_pipe
*p2
;
5740 struct policy_handle hive_handle
;
5741 struct dcerpc_binding_handle
*b2
;
5743 torture_assert_ntstatus_ok(tctx
,
5744 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
5745 "could not open winreg pipe");
5746 b2
= p2
->binding_handle
;
5748 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
5750 ret
&= test_SetPrinterData_matrix(tctx
, b
, handle
, printer_name
, b2
, &hive_handle
);
5751 ret
&= test_SetPrinterDataEx_matrix(tctx
, p
, handle
, printer_name
, b2
, &hive_handle
);
5753 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
5760 static bool test_Forms_winreg(struct torture_context
*tctx
,
5761 struct dcerpc_binding_handle
*b
,
5762 struct policy_handle
*handle
,
5764 const char *printer_name
)
5766 struct dcerpc_pipe
*p2
;
5768 struct policy_handle hive_handle
;
5769 struct dcerpc_binding_handle
*b2
;
5771 torture_assert_ntstatus_ok(tctx
,
5772 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
5773 "could not open winreg pipe");
5774 b2
= p2
->binding_handle
;
5776 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
5778 ret
= test_Forms(tctx
, b
, handle
, print_server
, printer_name
, b2
, &hive_handle
);
5780 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
5787 static bool test_PrinterInfo_winreg(struct torture_context
*tctx
,
5788 struct dcerpc_pipe
*p
,
5789 struct policy_handle
*handle
,
5790 const char *printer_name
)
5792 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5793 struct dcerpc_pipe
*p2
;
5795 struct policy_handle hive_handle
;
5796 struct dcerpc_binding_handle
*b2
;
5798 torture_assert_ntstatus_ok(tctx
,
5799 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
5800 "could not open winreg pipe");
5801 b2
= p2
->binding_handle
;
5803 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
5805 ret
= test_GetPrinterInfo_winreg(tctx
, b
, handle
, printer_name
, b2
, &hive_handle
);
5807 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
5814 static bool test_PrintserverInfo_winreg(struct torture_context
*tctx
,
5815 struct dcerpc_pipe
*p
,
5816 struct policy_handle
*handle
)
5818 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5819 struct dcerpc_pipe
*p2
;
5821 struct policy_handle hive_handle
;
5822 struct dcerpc_binding_handle
*b2
;
5824 torture_assert_ntstatus_ok(tctx
,
5825 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
5826 "could not open winreg pipe");
5827 b2
= p2
->binding_handle
;
5829 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
5831 ret
= test_GetPrintserverInfo_winreg(tctx
, b
, handle
, b2
, &hive_handle
);
5833 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
5841 static bool test_DriverInfo_winreg(struct torture_context
*tctx
,
5842 struct dcerpc_pipe
*p
,
5843 struct policy_handle
*handle
,
5844 const char *printer_name
,
5845 const char *driver_name
,
5846 const char *environment
,
5847 enum spoolss_DriverOSVersion version
)
5849 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5850 struct dcerpc_pipe
*p2
;
5852 struct policy_handle hive_handle
;
5853 struct dcerpc_binding_handle
*b2
;
5855 torture_assert_ntstatus_ok(tctx
,
5856 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
5857 "could not open winreg pipe");
5858 b2
= p2
->binding_handle
;
5860 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
5862 ret
= test_GetDriverInfo_winreg(tctx
, b
, handle
, printer_name
, driver_name
, environment
, version
, b2
, &hive_handle
, NULL
);
5864 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
5871 static bool test_PrintProcessors_winreg(struct torture_context
*tctx
,
5872 struct dcerpc_binding_handle
*b
,
5873 const char *environment
)
5875 struct dcerpc_pipe
*p2
;
5877 struct policy_handle hive_handle
;
5878 struct dcerpc_binding_handle
*b2
;
5880 torture_assert_ntstatus_ok(tctx
,
5881 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
5882 "could not open winreg pipe");
5883 b2
= p2
->binding_handle
;
5885 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
5887 ret
= test_PrintProcessors(tctx
, b
, environment
, b2
, &hive_handle
);
5889 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
5896 static bool test_PrinterData_DsSpooler(struct torture_context
*tctx
,
5897 struct dcerpc_pipe
*p
,
5898 struct policy_handle
*handle
,
5899 const char *printer_name
)
5901 struct spoolss_SetPrinterInfoCtr info_ctr
;
5902 struct spoolss_DevmodeContainer devmode_ctr
;
5903 struct sec_desc_buf secdesc_ctr
;
5904 union spoolss_SetPrinterInfo sinfo
;
5905 union spoolss_PrinterInfo info
;
5906 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5909 ZERO_STRUCT(info_ctr
);
5910 ZERO_STRUCT(devmode_ctr
);
5911 ZERO_STRUCT(secdesc_ctr
);
5913 torture_comment(tctx
, "Testing DsSpooler <-> SetPrinter relations\n");
5915 torture_assert(tctx
,
5916 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
5917 "failed to query Printer level 2");
5919 torture_assert(tctx
,
5920 PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
),
5921 "failed to convert");
5924 info_ctr
.info
= sinfo
;
5926 #define TEST_SZ(wname, iname) \
5928 enum winreg_Type type;\
5933 torture_assert(tctx,\
5934 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5935 "failed to query");\
5936 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5937 blob = data_blob_const(data, needed);\
5938 torture_assert(tctx,\
5939 pull_reg_sz(tctx, &blob, &str),\
5940 "failed to pull REG_SZ");\
5941 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5945 #define TEST_SET_SZ(wname, iname, val) \
5947 enum winreg_Type type;\
5952 sinfo.info2->iname = val;\
5953 torture_assert(tctx,\
5954 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5955 "failed to call SetPrinter");\
5956 torture_assert(tctx,\
5957 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5958 "failed to query");\
5959 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5960 blob = data_blob_const(data, needed);\
5961 torture_assert(tctx,\
5962 pull_reg_sz(tctx, &blob, &str),\
5963 "failed to pull REG_SZ");\
5964 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5967 #define TEST_SET_DWORD(wname, iname, val) \
5969 enum winreg_Type type;\
5973 sinfo.info2->iname = val;\
5974 torture_assert(tctx,\
5975 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5976 "failed to call SetPrinter");\
5977 torture_assert(tctx,\
5978 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5979 "failed to query");\
5980 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5981 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5982 value = IVAL(data, 0); \
5983 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5986 TEST_SET_SZ("description", comment
, "newval");
5987 TEST_SET_SZ("location", location
, "newval");
5988 TEST_SET_SZ("driverName", drivername
, "newval");
5989 /* TEST_SET_DWORD("priority", priority, 25); */
5991 torture_assert(tctx
,
5992 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
5993 "failed to query Printer level 2");
5995 TEST_SZ("description", info
.info2
.comment
);
5996 TEST_SZ("driverName", info
.info2
.drivername
);
5997 TEST_SZ("location", info
.info2
.location
);
5999 pname
= strrchr(info
.info2
.printername
, '\\');
6000 if (pname
== NULL
) {
6001 pname
= info
.info2
.printername
;
6005 TEST_SZ("printerName", pname
);
6006 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
6007 /* TEST_SZ("printShareName", info.info2.sharename); */
6009 /* FIXME gd: complete the list */
6015 torture_comment(tctx
, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
6020 static bool test_print_processors_winreg(struct torture_context
*tctx
,
6023 struct test_spoolss_context
*ctx
=
6024 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
6025 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
6026 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6028 return test_PrintProcessors_winreg(tctx
, b
, ctx
->environment
);
6031 static bool test_AddPrintProcessor(struct torture_context
*tctx
,
6032 struct dcerpc_binding_handle
*b
,
6033 const char *environment
,
6034 const char *path_name
,
6035 const char *print_processor_name
,
6036 WERROR expected_error
)
6038 struct spoolss_AddPrintProcessor r
;
6041 r
.in
.architecture
= environment
;
6042 r
.in
.path_name
= path_name
;
6043 r
.in
.print_processor_name
= print_processor_name
;
6045 torture_comment(tctx
, "Testing AddPrintProcessor(%s)\n",
6046 print_processor_name
);
6048 torture_assert_ntstatus_ok(tctx
,
6049 dcerpc_spoolss_AddPrintProcessor_r(b
, tctx
, &r
),
6050 "spoolss_AddPrintProcessor failed");
6051 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_error
,
6052 "spoolss_AddPrintProcessor failed");
6057 static bool test_DeletePrintProcessor(struct torture_context
*tctx
,
6058 struct dcerpc_binding_handle
*b
,
6059 const char *environment
,
6060 const char *print_processor_name
,
6061 WERROR expected_error
)
6063 struct spoolss_DeletePrintProcessor r
;
6066 r
.in
.architecture
= environment
;
6067 r
.in
.print_processor_name
= print_processor_name
;
6069 torture_comment(tctx
, "Testing DeletePrintProcessor(%s)\n",
6070 print_processor_name
);
6072 torture_assert_ntstatus_ok(tctx
,
6073 dcerpc_spoolss_DeletePrintProcessor_r(b
, tctx
, &r
),
6074 "spoolss_DeletePrintProcessor failed");
6075 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_error
,
6076 "spoolss_DeletePrintProcessor failed");
6081 static bool test_add_print_processor(struct torture_context
*tctx
,
6084 struct test_spoolss_context
*ctx
=
6085 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
6086 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
6087 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6091 const char *environment
;
6092 const char *path_name
;
6093 const char *print_processor_name
;
6094 WERROR expected_add_result
;
6095 WERROR expected_del_result
;
6098 .environment
= ctx
->environment
,
6100 .print_processor_name
= "winprint",
6101 .expected_add_result
= WERR_PRINT_PROCESSOR_ALREADY_INSTALLED
,
6102 .expected_del_result
= WERR_CAN_NOT_COMPLETE
6104 .environment
= ctx
->environment
,
6106 .print_processor_name
= "unknown",
6107 .expected_add_result
= WERR_MOD_NOT_FOUND
,
6108 .expected_del_result
= WERR_UNKNOWN_PRINTPROCESSOR
6112 for (i
=0; i
< ARRAY_SIZE(tests
); i
++) {
6113 torture_assert(tctx
,
6114 test_AddPrintProcessor(tctx
, b
,
6115 tests
[i
].environment
,
6117 tests
[i
].print_processor_name
,
6118 tests
[i
].expected_add_result
),
6119 "add print processor failed");
6120 torture_assert(tctx
,
6121 test_DeletePrintProcessor(tctx
, b
,
6122 tests
[i
].environment
,
6123 tests
[i
].print_processor_name
,
6124 tests
[i
].expected_del_result
),
6125 "delete print processor failed");
6131 static bool test_AddPerMachineConnection(struct torture_context
*tctx
,
6132 struct dcerpc_binding_handle
*b
,
6133 const char *servername
,
6134 const char *printername
,
6135 const char *printserver
,
6136 const char *provider
,
6137 WERROR expected_error
)
6139 struct spoolss_AddPerMachineConnection r
;
6140 const char *composed_printername
= printername
;
6142 if (servername
!= NULL
) {
6143 composed_printername
= talloc_asprintf(tctx
, "%s\\%s",
6147 r
.in
.server
= servername
;
6148 r
.in
.printername
= composed_printername
;
6149 r
.in
.printserver
= printserver
;
6150 r
.in
.provider
= provider
;
6152 torture_comment(tctx
, "Testing AddPerMachineConnection(%s|%s|%s)\n",
6153 printername
, printserver
, provider
);
6155 torture_assert_ntstatus_ok(tctx
,
6156 dcerpc_spoolss_AddPerMachineConnection_r(b
, tctx
, &r
),
6157 "spoolss_AddPerMachineConnection failed");
6158 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_error
,
6159 "spoolss_AddPerMachineConnection failed");
6164 static bool test_DeletePerMachineConnection(struct torture_context
*tctx
,
6165 struct dcerpc_binding_handle
*b
,
6166 const char *servername
,
6167 const char *printername
,
6168 WERROR expected_error
)
6170 struct spoolss_DeletePerMachineConnection r
;
6171 const char *composed_printername
= printername
;
6173 if (servername
!= NULL
) {
6174 composed_printername
= talloc_asprintf(tctx
, "%s\\%s",
6179 r
.in
.server
= servername
;
6180 r
.in
.printername
= composed_printername
;
6182 torture_comment(tctx
, "Testing DeletePerMachineConnection(%s)\n",
6185 torture_assert_ntstatus_ok(tctx
,
6186 dcerpc_spoolss_DeletePerMachineConnection_r(b
, tctx
, &r
),
6187 "spoolss_DeletePerMachineConnection failed");
6188 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_error
,
6189 "spoolss_DeletePerMachineConnection failed");
6194 static bool test_EnumPerMachineConnections(struct torture_context
*tctx
,
6195 struct dcerpc_binding_handle
*b
,
6196 const char *servername
)
6198 struct spoolss_EnumPerMachineConnections r
;
6199 DATA_BLOB blob
= data_blob_null
;
6200 struct spoolss_PrinterInfo4
*info
;
6204 r
.in
.server
= servername
;
6205 r
.in
.buffer
= &blob
;
6209 r
.out
.needed
= &needed
;
6210 r
.out
.count
= &count
;
6212 torture_comment(tctx
, "Testing EnumPerMachineConnections(%s)\n",
6215 torture_assert_ntstatus_ok(tctx
,
6216 dcerpc_spoolss_EnumPerMachineConnections_r(b
, tctx
, &r
),
6217 "spoolss_EnumPerMachineConnections failed");
6218 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
6219 blob
= data_blob_talloc_zero(tctx
, needed
);
6220 r
.in
.buffer
= &blob
;
6221 r
.in
.offered
= needed
;
6223 torture_assert_ntstatus_ok(tctx
,
6224 dcerpc_spoolss_EnumPerMachineConnections_r(b
, tctx
, &r
),
6225 "spoolss_EnumPerMachineConnections failed");
6227 torture_assert_werr_ok(tctx
, r
.out
.result
,
6228 "spoolss_EnumPerMachineConnections failed");
6233 static bool test_addpermachineconnection(struct torture_context
*tctx
,
6236 struct test_spoolss_context
*ctx
=
6237 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
6238 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
6239 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6240 const char *server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
6244 const char *servername
;
6245 const char *printername
;
6246 const char *printserver
;
6247 const char *provider
;
6248 WERROR expected_add_result
;
6249 WERROR expected_del_result
;
6253 .printername
= "foo",
6255 .provider
= "unknown",
6256 .expected_add_result
= WERR_INVALID_PRINTER_NAME
,
6257 .expected_del_result
= WERR_INVALID_PRINTER_NAME
6260 .printername
= "Microsoft Print to PDF",
6261 .printserver
= "samba.org",
6262 .provider
= "unknown",
6263 .expected_add_result
= WERR_INVALID_PRINTER_NAME
,
6264 .expected_del_result
= WERR_INVALID_PRINTER_NAME
6267 .printername
= "Microsoft Print to PDF",
6268 .printserver
= "samba.org",
6270 .expected_add_result
= WERR_INVALID_PRINTER_NAME
,
6271 .expected_del_result
= WERR_INVALID_PRINTER_NAME
6273 .servername
= server_name_slash
,
6274 .printername
= "foo",
6276 .provider
= "unknown",
6277 .expected_add_result
= WERR_FILE_NOT_FOUND
,
6278 .expected_del_result
= WERR_INVALID_PRINTER_NAME
6280 .servername
= server_name_slash
,
6281 .printername
= "foo",
6284 .expected_add_result
= WERR_OK
,
6285 .expected_del_result
= WERR_OK
6287 .servername
= server_name_slash
,
6288 .printername
= "Microsoft Print to PDF",
6289 .printserver
= "samba.org",
6290 .provider
= "unknown",
6291 .expected_add_result
= WERR_FILE_NOT_FOUND
,
6292 .expected_del_result
= WERR_INVALID_PRINTER_NAME
6294 .servername
= server_name_slash
,
6295 .printername
= "Microsoft Print to PDF",
6296 .printserver
= "samba.org",
6298 .expected_add_result
= WERR_OK
,
6299 .expected_del_result
= WERR_OK
6303 for (i
=0; i
< ARRAY_SIZE(tests
); i
++) {
6304 torture_assert(tctx
,
6305 test_AddPerMachineConnection(tctx
, b
,
6306 tests
[i
].servername
,
6307 tests
[i
].printername
,
6308 tests
[i
].printserver
,
6310 tests
[i
].expected_add_result
),
6311 "add per machine connection failed");
6312 torture_assert(tctx
,
6313 test_EnumPerMachineConnections(tctx
, b
,
6314 tests
[i
].servername
),
6315 "enum per machine connections failed");
6316 torture_assert(tctx
,
6317 test_DeletePerMachineConnection(tctx
, b
,
6318 tests
[i
].servername
,
6319 tests
[i
].printername
,
6320 tests
[i
].expected_del_result
),
6321 "delete per machine connection failed");
6322 torture_assert(tctx
,
6323 test_EnumPerMachineConnections(tctx
, b
,
6324 tests
[i
].servername
),
6325 "enum per machine connections failed");
6331 static bool test_GetChangeID_PrinterData(struct torture_context
*tctx
,
6332 struct dcerpc_binding_handle
*b
,
6333 struct policy_handle
*handle
,
6334 uint32_t *change_id
)
6336 enum winreg_Type type
;
6340 torture_assert(tctx
,
6341 test_GetPrinterData(tctx
, b
, handle
, "ChangeID", &type
, &data
, &needed
),
6342 "failed to call GetPrinterData");
6344 torture_assert(tctx
, type
== REG_DWORD
, "unexpected type");
6345 torture_assert_int_equal(tctx
, needed
, 4, "unexpected size");
6347 *change_id
= IVAL(data
, 0);
6352 static bool test_GetChangeID_PrinterDataEx(struct torture_context
*tctx
,
6353 struct dcerpc_pipe
*p
,
6354 struct policy_handle
*handle
,
6355 uint32_t *change_id
)
6357 enum winreg_Type type
= REG_NONE
;
6358 uint8_t *data
= NULL
;
6359 uint32_t needed
= 0;
6361 torture_assert(tctx
,
6362 test_GetPrinterDataEx(tctx
, p
, handle
, "PrinterDriverData", "ChangeID", &type
, &data
, &needed
),
6363 "failed to call GetPrinterData");
6365 torture_assert(tctx
, type
== REG_DWORD
, "unexpected type");
6366 torture_assert_int_equal(tctx
, needed
, 4, "unexpected size");
6368 *change_id
= IVAL(data
, 0);
6373 static bool test_GetChangeID_PrinterInfo(struct torture_context
*tctx
,
6374 struct dcerpc_binding_handle
*b
,
6375 struct policy_handle
*handle
,
6376 uint32_t *change_id
)
6378 union spoolss_PrinterInfo info
;
6380 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 0, &info
),
6381 "failed to query Printer level 0");
6383 *change_id
= info
.info0
.change_id
;
6388 static bool test_ChangeID(struct torture_context
*tctx
,
6389 struct dcerpc_pipe
*p
,
6390 struct policy_handle
*handle
)
6392 uint32_t change_id
, change_id_ex
, change_id_info
;
6393 uint32_t change_id2
, change_id_ex2
, change_id_info2
;
6394 union spoolss_PrinterInfo info
;
6395 const char *comment
;
6396 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6398 torture_comment(tctx
, "Testing ChangeID: id change test #1\n");
6400 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id
),
6401 "failed to query for ChangeID");
6402 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex
),
6403 "failed to query for ChangeID");
6404 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info
),
6405 "failed to query for ChangeID");
6407 torture_assert_int_equal(tctx
, change_id
, change_id_ex
,
6408 "change_ids should all be equal");
6409 torture_assert_int_equal(tctx
, change_id_ex
, change_id_info
,
6410 "change_ids should all be equal");
6413 torture_comment(tctx
, "Testing ChangeID: id change test #2\n");
6415 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id
),
6416 "failed to query for ChangeID");
6417 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
6418 "failed to query Printer level 2");
6419 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex
),
6420 "failed to query for ChangeID");
6421 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info
),
6422 "failed to query for ChangeID");
6423 torture_assert_int_equal(tctx
, change_id
, change_id_ex
,
6424 "change_id should not have changed");
6425 torture_assert_int_equal(tctx
, change_id_ex
, change_id_info
,
6426 "change_id should not have changed");
6429 torture_comment(tctx
, "Testing ChangeID: id change test #3\n");
6431 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id
),
6432 "failed to query for ChangeID");
6433 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex
),
6434 "failed to query for ChangeID");
6435 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info
),
6436 "failed to query for ChangeID");
6437 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
6438 "failed to query Printer level 2");
6439 comment
= talloc_strdup(tctx
, info
.info2
.comment
);
6442 struct spoolss_SetPrinterInfoCtr info_ctr
;
6443 struct spoolss_DevmodeContainer devmode_ctr
;
6444 struct sec_desc_buf secdesc_ctr
;
6445 union spoolss_SetPrinterInfo sinfo
;
6447 ZERO_STRUCT(info_ctr
);
6448 ZERO_STRUCT(devmode_ctr
);
6449 ZERO_STRUCT(secdesc_ctr
);
6452 torture_assert(tctx
, PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
6453 sinfo
.info2
->comment
= "torture_comment";
6456 info_ctr
.info
= sinfo
;
6458 torture_assert(tctx
, test_SetPrinter(tctx
, b
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0),
6459 "failed to call SetPrinter");
6461 sinfo
.info2
->comment
= comment
;
6463 torture_assert(tctx
, test_SetPrinter(tctx
, b
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0),
6464 "failed to call SetPrinter");
6468 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id2
),
6469 "failed to query for ChangeID");
6470 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex2
),
6471 "failed to query for ChangeID");
6472 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info2
),
6473 "failed to query for ChangeID");
6475 torture_assert_int_equal(tctx
, change_id2
, change_id_ex2
,
6476 "change_ids should all be equal");
6477 torture_assert_int_equal(tctx
, change_id_ex2
, change_id_info2
,
6478 "change_ids should all be equal");
6480 torture_assert(tctx
, (change_id
< change_id2
),
6481 talloc_asprintf(tctx
, "change_id %d needs to be larger than change_id %d",
6482 change_id2
, change_id
));
6483 torture_assert(tctx
, (change_id_ex
< change_id_ex2
),
6484 talloc_asprintf(tctx
, "change_id %d needs to be larger than change_id %d",
6485 change_id_ex2
, change_id_ex
));
6486 torture_assert(tctx
, (change_id_info
< change_id_info2
),
6487 talloc_asprintf(tctx
, "change_id %d needs to be larger than change_id %d",
6488 change_id_info2
, change_id_info
));
6490 torture_comment(tctx
, "ChangeID tests succeeded\n\n");
6495 static bool test_SecondaryClosePrinter(struct torture_context
*tctx
,
6496 struct dcerpc_pipe
*p
,
6497 struct policy_handle
*handle
)
6500 struct cli_credentials
*anon_creds
;
6501 const struct dcerpc_binding
*binding2
;
6502 struct dcerpc_pipe
*p2
;
6503 struct spoolss_ClosePrinter cp
;
6505 /* only makes sense on SMB */
6506 if (dcerpc_binding_handle_get_transport(p
->binding_handle
) != NCACN_NP
) {
6510 torture_comment(tctx
, "Testing close on secondary pipe\n");
6512 anon_creds
= cli_credentials_init_anon(tctx
);
6513 torture_assert(tctx
, anon_creds
!= NULL
, "cli_credentials_init_anon failed");
6515 binding2
= dcerpc_binding_handle_get_binding(p
->binding_handle
);
6516 status
= dcerpc_secondary_auth_connection(p
, binding2
, &ndr_table_spoolss
,
6517 anon_creds
, tctx
->lp_ctx
,
6519 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create secondary connection");
6521 cp
.in
.handle
= handle
;
6522 cp
.out
.handle
= handle
;
6524 status
= dcerpc_spoolss_ClosePrinter_r(p2
->binding_handle
, tctx
, &cp
);
6525 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_RPC_SS_CONTEXT_MISMATCH
,
6526 "ERROR: Allowed close on secondary connection");
6533 static bool test_OpenPrinter_badname(struct torture_context
*tctx
,
6534 struct dcerpc_binding_handle
*b
, const char *name
)
6537 struct spoolss_OpenPrinter op
;
6538 struct spoolss_OpenPrinterEx opEx
;
6539 struct policy_handle handle
;
6542 op
.in
.printername
= name
;
6543 op
.in
.datatype
= NULL
;
6544 op
.in
.devmode_ctr
.devmode
= NULL
;
6545 op
.in
.access_mask
= 0;
6546 op
.out
.handle
= &handle
;
6548 torture_comment(tctx
, "Testing OpenPrinter(%s) with bad name\n", op
.in
.printername
);
6550 status
= dcerpc_spoolss_OpenPrinter_r(b
, tctx
, &op
);
6551 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
6552 torture_assert_werr_equal(tctx
, op
.out
.result
, WERR_INVALID_PRINTER_NAME
,
6553 "unexpected result");
6555 if (W_ERROR_IS_OK(op
.out
.result
)) {
6556 ret
&=test_ClosePrinter(tctx
, b
, &handle
);
6559 opEx
.in
.printername
= name
;
6560 opEx
.in
.datatype
= NULL
;
6561 opEx
.in
.devmode_ctr
.devmode
= NULL
;
6562 opEx
.in
.access_mask
= 0;
6563 opEx
.in
.userlevel_ctr
.level
= 1;
6564 opEx
.in
.userlevel_ctr
.user_info
.level1
= NULL
;
6565 opEx
.out
.handle
= &handle
;
6567 torture_comment(tctx
, "Testing OpenPrinterEx(%s) with bad name\n", opEx
.in
.printername
);
6569 status
= dcerpc_spoolss_OpenPrinterEx_r(b
, tctx
, &opEx
);
6570 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinterEx failed");
6571 torture_assert_werr_equal(tctx
, opEx
.out
.result
, WERR_INVALID_PARAMETER
,
6572 "unexpected result");
6574 if (W_ERROR_IS_OK(opEx
.out
.result
)) {
6575 ret
&=test_ClosePrinter(tctx
, b
, &handle
);
6581 static bool test_OpenPrinter_badname_list(struct torture_context
*tctx
,
6584 struct test_spoolss_context
*ctx
=
6585 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
6587 const char *badnames
[] = {
6588 "__INVALID_PRINTER__",
6589 "\\\\__INVALID_HOST__",
6592 "\\\\\\__INVALID_PRINTER__"
6594 const char *badname
;
6595 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
6596 const char *server_name
= dcerpc_server_name(p
);
6597 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6600 for (i
=0; i
< ARRAY_SIZE(badnames
); i
++) {
6601 torture_assert(tctx
,
6602 test_OpenPrinter_badname(tctx
, b
, badnames
[i
]),
6606 badname
= talloc_asprintf(tctx
, "\\\\%s\\", server_name
);
6607 torture_assert(tctx
,
6608 test_OpenPrinter_badname(tctx
, b
, badname
),
6611 badname
= talloc_asprintf(tctx
, "\\\\%s\\__INVALID_PRINTER__", server_name
);
6612 torture_assert(tctx
,
6613 test_OpenPrinter_badname(tctx
, b
, badname
),
6619 static bool test_OpenPrinter(struct torture_context
*tctx
,
6620 struct dcerpc_pipe
*p
,
6622 const char *environment
,
6626 struct spoolss_OpenPrinter r
;
6627 struct policy_handle handle
;
6629 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6631 r
.in
.printername
= name
;
6632 r
.in
.datatype
= NULL
;
6633 r
.in
.devmode_ctr
.devmode
= NULL
;
6634 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
6635 r
.out
.handle
= &handle
;
6637 torture_comment(tctx
, "Testing OpenPrinter(%s)\n", r
.in
.printername
);
6639 status
= dcerpc_spoolss_OpenPrinter_r(b
, tctx
, &r
);
6641 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
6643 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenPrinter failed");
6649 if (!test_GetPrinter(tctx
, b
, &handle
, environment
)) {
6653 if (!torture_setting_bool(tctx
, "samba3", false)) {
6654 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
6660 if (!test_ClosePrinter(tctx
, b
, &handle
)) {
6667 static bool test_OpenPrinterEx(struct torture_context
*tctx
,
6668 struct dcerpc_binding_handle
*b
,
6669 const char *printername
,
6670 const char *datatype
,
6671 struct spoolss_DeviceMode
*devmode
,
6672 uint32_t access_mask
,
6673 struct spoolss_UserLevelCtr
*userlevel_ctr
,
6674 struct policy_handle
*handle
,
6675 WERROR expected_result
)
6677 struct spoolss_OpenPrinterEx r
;
6679 r
.in
.printername
= printername
;
6680 r
.in
.datatype
= datatype
;
6681 r
.in
.devmode_ctr
.devmode
= devmode
;
6682 r
.in
.access_mask
= access_mask
;
6683 r
.in
.userlevel_ctr
= *userlevel_ctr
;
6684 r
.out
.handle
= handle
;
6686 torture_comment(tctx
, "Testing OpenPrinterEx(%s)\n", r
.in
.printername
);
6688 torture_assert_ntstatus_ok(tctx
,
6689 dcerpc_spoolss_OpenPrinterEx_r(b
, tctx
, &r
),
6690 "OpenPrinterEx failed");
6692 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
6693 "OpenPrinterEx failed");
6698 static bool call_OpenPrinterEx(struct torture_context
*tctx
,
6699 struct dcerpc_pipe
*p
,
6701 struct spoolss_DeviceMode
*devmode
,
6702 struct policy_handle
*handle
)
6704 struct spoolss_UserLevelCtr userlevel_ctr
;
6705 struct spoolss_UserLevel1 userlevel1
;
6706 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6708 userlevel1
.size
= 1234;
6709 userlevel1
.client
= "hello";
6710 userlevel1
.user
= "spottyfoot!";
6711 userlevel1
.build
= 1;
6712 userlevel1
.major
= 2;
6713 userlevel1
.minor
= 3;
6714 userlevel1
.processor
= 4;
6716 userlevel_ctr
.level
= 1;
6717 userlevel_ctr
.user_info
.level1
= &userlevel1
;
6719 return test_OpenPrinterEx(tctx
, b
, name
, NULL
, devmode
,
6720 SEC_FLAG_MAXIMUM_ALLOWED
,
6726 static bool test_printer_rename(struct torture_context
*tctx
,
6729 struct torture_printer_context
*t
=
6730 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
6731 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
6734 union spoolss_PrinterInfo info
;
6735 union spoolss_SetPrinterInfo sinfo
;
6736 struct spoolss_SetPrinterInfoCtr info_ctr
;
6737 struct spoolss_DevmodeContainer devmode_ctr
;
6738 struct sec_desc_buf secdesc_ctr
;
6739 const char *printer_name
;
6740 const char *printer_name_orig
;
6741 const char *printer_name_new
= "SAMBA smbtorture Test Printer (Copy 2)";
6742 struct policy_handle new_handle
;
6744 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6746 ZERO_STRUCT(devmode_ctr
);
6747 ZERO_STRUCT(secdesc_ctr
);
6749 torture_comment(tctx
, "Testing Printer rename operations\n");
6751 torture_assert(tctx
,
6752 test_GetPrinter_level(tctx
, b
, &t
->handle
, 2, &info
),
6753 "failed to call GetPrinter level 2");
6755 printer_name_orig
= talloc_strdup(tctx
, info
.info2
.printername
);
6757 q
= strrchr(info
.info2
.printername
, '\\');
6759 torture_warning(tctx
,
6760 "server returns printername %s incl. servername although we did not set servername", info
.info2
.printername
);
6763 torture_assert(tctx
,
6764 PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
6766 sinfo
.info2
->printername
= printer_name_new
;
6769 info_ctr
.info
= sinfo
;
6771 torture_assert(tctx
,
6772 test_SetPrinter(tctx
, b
, &t
->handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0),
6773 "failed to call SetPrinter level 2");
6775 torture_assert(tctx
,
6776 test_GetPrinter_level(tctx
, b
, &t
->handle
, 2, &info
),
6777 "failed to call GetPrinter level 2");
6779 printer_name
= talloc_strdup(tctx
, info
.info2
.printername
);
6781 q
= strrchr(info
.info2
.printername
, '\\');
6783 torture_warning(tctx
,
6784 "server returns printername %s incl. servername although we did not set servername", info
.info2
.printername
);
6789 torture_assert_str_equal(tctx
, printer_name
, printer_name_new
,
6790 "new printer name was not set");
6792 /* samba currently cannot fully rename printers */
6793 if (!torture_setting_bool(tctx
, "samba3", false)) {
6794 torture_assert(tctx
,
6795 test_OpenPrinter_badname(tctx
, b
, printer_name_orig
),
6796 "still can open printer with oldname after rename");
6798 torture_warning(tctx
, "*not* checking for open with oldname after rename for samba3");
6801 torture_assert(tctx
,
6802 call_OpenPrinterEx(tctx
, p
, printer_name_new
, NULL
, &new_handle
),
6803 "failed to open printer with new name");
6805 torture_assert(tctx
,
6806 test_GetPrinter_level(tctx
, b
, &new_handle
, 2, &info
),
6807 "failed to call GetPrinter level 2");
6809 torture_assert_str_equal(tctx
, info
.info2
.printername
, printer_name_new
,
6810 "new printer name was not set");
6812 torture_assert(tctx
,
6813 test_ClosePrinter(tctx
, b
, &new_handle
),
6814 "failed to close printer");
6816 torture_comment(tctx
, "Printer rename operations test succeeded\n\n");
6821 static bool test_openprinter(struct torture_context
*tctx
,
6822 struct dcerpc_binding_handle
*b
,
6823 const char *real_printername
)
6825 struct spoolss_UserLevelCtr userlevel_ctr
;
6826 struct policy_handle handle
;
6827 struct spoolss_UserLevel1 userlevel1
;
6828 const char *printername
= NULL
;
6833 WERROR expected_result
;
6836 .suffix
= "rubbish",
6837 .expected_result
= WERR_INVALID_PRINTER_NAME
6839 .suffix
= ", LocalOnl",
6840 .expected_result
= WERR_INVALID_PRINTER_NAME
6842 .suffix
= ", localOnly",
6843 .expected_result
= WERR_INVALID_PRINTER_NAME
6845 .suffix
= ", localonl",
6846 .expected_result
= WERR_INVALID_PRINTER_NAME
6848 .suffix
= ",LocalOnl",
6849 .expected_result
= WERR_INVALID_PRINTER_NAME
6851 .suffix
= ",localOnl2",
6852 .expected_result
= WERR_INVALID_PRINTER_NAME
6854 .suffix
= ", DrvConver2t",
6855 .expected_result
= WERR_INVALID_PRINTER_NAME
6857 .suffix
= ", drvconvert",
6858 .expected_result
= WERR_INVALID_PRINTER_NAME
6860 .suffix
= ",drvconvert",
6861 .expected_result
= WERR_INVALID_PRINTER_NAME
6863 .suffix
= ", DrvConvert",
6864 .expected_result
= WERR_OK
6866 .suffix
= " , DrvConvert",
6867 .expected_result
= WERR_INVALID_PRINTER_NAME
6869 .suffix
= ",DrvConvert",
6870 .expected_result
= WERR_OK
6872 .suffix
= ", DrvConvertsadfasdf",
6873 .expected_result
= WERR_OK
6875 .suffix
= ",DrvConvertasdfasd",
6876 .expected_result
= WERR_OK
6878 .suffix
= ", LocalOnly",
6879 .expected_result
= WERR_OK
6881 .suffix
= " , LocalOnly",
6882 .expected_result
= WERR_INVALID_PRINTER_NAME
6884 .suffix
= ",LocalOnly",
6885 .expected_result
= WERR_OK
6887 .suffix
= ", LocalOnlysagi4gjfkd",
6888 .expected_result
= WERR_OK
6890 .suffix
= ",LocalOnlysagi4gjfkd",
6891 .expected_result
= WERR_OK
6895 userlevel1
.size
= 1234;
6896 userlevel1
.client
= "hello";
6897 userlevel1
.user
= "spottyfoot!";
6898 userlevel1
.build
= 1;
6899 userlevel1
.major
= 2;
6900 userlevel1
.minor
= 3;
6901 userlevel1
.processor
= 4;
6903 userlevel_ctr
.level
= 1;
6904 userlevel_ctr
.user_info
.level1
= &userlevel1
;
6906 torture_comment(tctx
, "Testing openprinterex printername pattern\n");
6908 torture_assert(tctx
,
6909 test_OpenPrinterEx(tctx
, b
, real_printername
, NULL
, NULL
, 0,
6910 &userlevel_ctr
, &handle
,
6912 "OpenPrinterEx failed");
6913 test_ClosePrinter(tctx
, b
, &handle
);
6915 for (i
=0; i
< ARRAY_SIZE(tests
); i
++) {
6917 printername
= talloc_asprintf(tctx
, "%s%s",
6921 torture_assert(tctx
,
6922 test_OpenPrinterEx(tctx
, b
, printername
, NULL
, NULL
, 0,
6923 &userlevel_ctr
, &handle
,
6924 tests
[i
].expected_result
),
6925 "OpenPrinterEx failed");
6926 if (W_ERROR_IS_OK(tests
[i
].expected_result
)) {
6927 test_ClosePrinter(tctx
, b
, &handle
);
6935 static bool test_existing_printer_openprinterex(struct torture_context
*tctx
,
6936 struct dcerpc_pipe
*p
,
6938 const char *environment
)
6940 struct policy_handle handle
;
6942 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
6944 if (!test_openprinter(tctx
, b
, name
)) {
6948 if (!call_OpenPrinterEx(tctx
, p
, name
, NULL
, &handle
)) {
6952 if (!test_PrinterInfo_SD(tctx
, b
, &handle
)) {
6956 if (!test_GetPrinter(tctx
, b
, &handle
, environment
)) {
6960 if (!test_EnumForms_all(tctx
, b
, &handle
, false)) {
6964 if (!test_Forms(tctx
, b
, &handle
, false, name
, NULL
, NULL
)) {
6968 if (!test_Forms_winreg(tctx
, b
, &handle
, false, name
)) {
6972 if (!test_EnumPrinterData_all(tctx
, p
, &handle
)) {
6976 if (!test_EnumPrinterDataEx(tctx
, b
, &handle
, "PrinterDriverData", NULL
, NULL
)) {
6980 if (!test_EnumPrinterData_consistency(tctx
, p
, &handle
)) {
6984 if (!test_printer_all_keys(tctx
, b
, &handle
)) {
6988 if (!test_PausePrinter(tctx
, b
, &handle
)) {
6992 if (!test_DoPrintTest(tctx
, b
, &handle
)) {
6996 if (!test_ResumePrinter(tctx
, b
, &handle
)) {
7000 if (!test_SetPrinterData_matrix(tctx
, b
, &handle
, name
, NULL
, NULL
)) {
7004 if (!test_SetPrinterDataEx_matrix(tctx
, p
, &handle
, name
, NULL
, NULL
)) {
7008 if (!torture_setting_bool(tctx
, "samba3", false)) {
7009 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
7014 if (!test_ClosePrinter(tctx
, b
, &handle
)) {
7021 static bool test_EnumPrinters_old(struct torture_context
*tctx
,
7024 struct test_spoolss_context
*ctx
=
7025 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
7026 struct spoolss_EnumPrinters r
;
7028 uint16_t levels
[] = {1, 2, 4, 5};
7031 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
7032 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7034 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
7035 union spoolss_PrinterInfo
*info
;
7040 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
7042 r
.in
.level
= levels
[i
];
7045 r
.out
.needed
= &needed
;
7046 r
.out
.count
= &count
;
7049 torture_comment(tctx
, "Testing EnumPrinters level %u\n", r
.in
.level
);
7051 status
= dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &r
);
7052 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
7054 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
7055 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
7056 r
.in
.buffer
= &blob
;
7057 r
.in
.offered
= needed
;
7058 status
= dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &r
);
7061 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
7063 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
7065 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters
, info
, r
.in
.level
, count
, needed
, 4);
7068 torture_comment(tctx
, "No printers returned\n");
7072 for (j
=0;j
<count
;j
++) {
7073 if (r
.in
.level
== 1) {
7074 char *unc
= talloc_strdup(tctx
, info
[j
].info1
.name
);
7075 char *slash
, *name
, *full_name
;
7077 if (unc
[0] == '\\' && unc
[1] == '\\') {
7080 slash
= strchr(unc
, '\\');
7085 full_name
= talloc_asprintf(tctx
, "\\\\%s\\%s",
7086 dcerpc_server_name(p
), name
);
7087 if (!test_OpenPrinter(tctx
, p
, name
, ctx
->environment
, true)) {
7090 if (!test_OpenPrinter(tctx
, p
, full_name
, ctx
->environment
, true)) {
7093 if (!test_OpenPrinter(tctx
, p
, name
, ctx
->environment
, false)) {
7096 if (!test_existing_printer_openprinterex(tctx
, p
, name
, ctx
->environment
)) {
7106 static bool test_EnumPrinters_level(struct torture_context
*tctx
,
7107 struct dcerpc_binding_handle
*b
,
7109 const char *servername
,
7112 union spoolss_PrinterInfo
**info_p
)
7114 struct spoolss_EnumPrinters r
;
7115 union spoolss_PrinterInfo
*info
;
7120 r
.in
.server
= servername
;
7124 r
.out
.needed
= &needed
;
7125 r
.out
.count
= &count
;
7128 torture_comment(tctx
, "Testing EnumPrinters(%s) level %u\n",
7129 r
.in
.server
, r
.in
.level
);
7131 torture_assert_ntstatus_ok(tctx
,
7132 dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &r
),
7133 "EnumPrinters failed");
7134 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
7135 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
7136 r
.in
.buffer
= &blob
;
7137 r
.in
.offered
= needed
;
7138 torture_assert_ntstatus_ok(tctx
,
7139 dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &r
),
7140 "EnumPrinters failed");
7143 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
7145 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters
, info
, r
.in
.level
, count
, needed
, 4);
7157 static const char *get_short_printername(struct torture_context
*tctx
,
7160 const char *short_name
;
7162 if (name
[0] == '\\' && name
[1] == '\\') {
7164 short_name
= strchr(name
, '\\');
7166 return talloc_strdup(tctx
, short_name
+1);
7173 static const char *get_full_printername(struct torture_context
*tctx
,
7176 const char *full_name
= talloc_strdup(tctx
, name
);
7179 if (name
&& name
[0] == '\\' && name
[1] == '\\') {
7181 p
= strchr(name
, '\\');
7190 static bool test_OnePrinter_servername(struct torture_context
*tctx
,
7191 struct dcerpc_pipe
*p
,
7192 struct dcerpc_binding_handle
*b
,
7193 const char *servername
,
7194 const char *printername
)
7196 union spoolss_PrinterInfo info
;
7197 const char *short_name
= get_short_printername(tctx
, printername
);
7198 const char *full_name
= get_full_printername(tctx
, printername
);
7201 struct policy_handle handle
;
7202 torture_assert(tctx
,
7203 call_OpenPrinterEx(tctx
, p
, short_name
, NULL
, &handle
),
7204 "failed to open printer");
7206 torture_assert(tctx
,
7207 test_GetPrinter_level(tctx
, b
, &handle
, 2, &info
),
7208 "failed to get printer info");
7210 torture_assert_casestr_equal(tctx
, info
.info2
.servername
, NULL
,
7211 "unexpected servername");
7212 torture_assert_casestr_equal(tctx
, info
.info2
.printername
, short_name
,
7213 "unexpected printername");
7215 if (info
.info2
.devmode
) {
7216 const char *expected_devicename
;
7217 expected_devicename
= talloc_strndup(tctx
, short_name
, MIN(strlen(short_name
), 31));
7218 torture_assert_casestr_equal(tctx
, info
.info2
.devmode
->devicename
, expected_devicename
,
7219 "unexpected devicemode devicename");
7222 torture_assert(tctx
,
7223 test_ClosePrinter(tctx
, b
, &handle
),
7224 "failed to close printer");
7228 struct policy_handle handle
;
7230 torture_assert(tctx
,
7231 call_OpenPrinterEx(tctx
, p
, full_name
, NULL
, &handle
),
7232 "failed to open printer");
7234 torture_assert(tctx
,
7235 test_GetPrinter_level(tctx
, b
, &handle
, 2, &info
),
7236 "failed to get printer info");
7238 torture_assert_casestr_equal(tctx
, info
.info2
.servername
, servername
,
7239 "unexpected servername");
7240 torture_assert_casestr_equal(tctx
, info
.info2
.printername
, full_name
,
7241 "unexpected printername");
7243 if (info
.info2
.devmode
) {
7244 const char *expected_devicename
;
7245 expected_devicename
= talloc_strndup(tctx
, full_name
, MIN(strlen(full_name
), 31));
7246 torture_assert_casestr_equal(tctx
, info
.info2
.devmode
->devicename
, expected_devicename
,
7247 "unexpected devicemode devicename");
7250 torture_assert(tctx
,
7251 test_ClosePrinter(tctx
, b
, &handle
),
7252 "failed to close printer");
7258 static bool test_EnumPrinters_servername(struct torture_context
*tctx
,
7261 struct test_spoolss_context
*ctx
=
7262 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
7264 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
7265 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7267 union spoolss_PrinterInfo
*info
;
7268 const char *servername
;
7269 uint32_t flags
= PRINTER_ENUM_NAME
|PRINTER_ENUM_LOCAL
;
7271 torture_comment(tctx
, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
7273 servername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
7275 torture_assert(tctx
,
7276 test_EnumPrinters_level(tctx
, b
, flags
, servername
, 2, &count
, &info
),
7277 "failed to enumerate printers");
7279 for (i
=0; i
< count
; i
++) {
7281 torture_assert_casestr_equal(tctx
, info
[i
].info2
.servername
, servername
,
7282 "unexpected servername");
7284 torture_assert(tctx
,
7285 test_OnePrinter_servername(tctx
, p
, b
, servername
, info
[i
].info2
.printername
),
7286 "failed to check printer");
7291 torture_assert(tctx
,
7292 test_EnumPrinters_level(tctx
, b
, flags
, servername
, 2, &count
, &info
),
7293 "failed to enumerate printers");
7295 for (i
=0; i
< count
; i
++) {
7297 torture_assert_casestr_equal(tctx
, info
[i
].info2
.servername
, NULL
,
7298 "unexpected servername");
7300 torture_assert(tctx
,
7301 test_OnePrinter_servername(tctx
, p
, b
, servername
, info
[i
].info2
.printername
),
7302 "failed to check printer");
7310 static bool test_GetPrinterDriver(struct torture_context
*tctx
,
7311 struct dcerpc_binding_handle
*b
,
7312 struct policy_handle
*handle
,
7313 const char *driver_name
)
7315 struct spoolss_GetPrinterDriver r
;
7318 r
.in
.handle
= handle
;
7319 r
.in
.architecture
= "W32X86";
7323 r
.out
.needed
= &needed
;
7325 torture_comment(tctx
, "Testing GetPrinterDriver level %d\n", r
.in
.level
);
7327 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver_r(b
, tctx
, &r
),
7328 "failed to call GetPrinterDriver");
7329 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
7330 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
7331 r
.in
.buffer
= &blob
;
7332 r
.in
.offered
= needed
;
7333 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver_r(b
, tctx
, &r
),
7334 "failed to call GetPrinterDriver");
7337 torture_assert_werr_ok(tctx
, r
.out
.result
,
7338 "failed to call GetPrinterDriver");
7340 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo
, r
.out
.info
, r
.in
.level
, needed
, 4);
7346 static bool test_GetPrinterDriver2_level(struct torture_context
*tctx
,
7347 struct dcerpc_binding_handle
*b
,
7348 struct policy_handle
*handle
,
7349 const char *driver_name
,
7350 const char *architecture
,
7352 uint32_t client_major_version
,
7353 uint32_t client_minor_version
,
7354 union spoolss_DriverInfo
*info_p
,
7358 struct spoolss_GetPrinterDriver2 r
;
7360 uint32_t server_major_version
;
7361 uint32_t server_minor_version
;
7363 r
.in
.handle
= handle
;
7364 r
.in
.architecture
= architecture
;
7365 r
.in
.client_major_version
= client_major_version
;
7366 r
.in
.client_minor_version
= client_minor_version
;
7370 r
.out
.needed
= &needed
;
7371 r
.out
.server_major_version
= &server_major_version
;
7372 r
.out
.server_minor_version
= &server_minor_version
;
7374 torture_comment(tctx
, "Testing GetPrinterDriver2(%s) level %d\n",
7375 driver_name
, r
.in
.level
);
7377 torture_assert_ntstatus_ok(tctx
,
7378 dcerpc_spoolss_GetPrinterDriver2_r(b
, tctx
, &r
),
7379 "failed to call GetPrinterDriver2");
7380 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
7381 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
7382 r
.in
.buffer
= &blob
;
7383 r
.in
.offered
= needed
;
7384 torture_assert_ntstatus_ok(tctx
,
7385 dcerpc_spoolss_GetPrinterDriver2_r(b
, tctx
, &r
),
7386 "failed to call GetPrinterDriver2");
7390 *result_p
= r
.out
.result
;
7393 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INVALID_LEVEL
)) {
7394 switch (r
.in
.level
) {
7397 torture_comment(tctx
,
7398 "level %d not implemented, not considering as an error\n",
7406 torture_assert_werr_ok(tctx
, r
.out
.result
,
7407 "failed to call GetPrinterDriver2");
7409 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo
, r
.out
.info
, r
.in
.level
, needed
, 4);
7412 *info_p
= *r
.out
.info
;
7418 static bool test_GetPrinterDriver2(struct torture_context
*tctx
,
7419 struct dcerpc_binding_handle
*b
,
7420 struct policy_handle
*handle
,
7421 const char *driver_name
,
7422 const char *architecture
)
7424 uint16_t levels
[] = {1, 2, 3, 4, 5, 6, 8, 101 };
7428 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
7430 torture_assert(tctx
,
7431 test_GetPrinterDriver2_level(tctx
, b
, handle
, driver_name
, architecture
, levels
[i
], 3, 0, NULL
, NULL
),
7438 static bool test_EnumPrinterDrivers_old(struct torture_context
*tctx
,
7441 struct test_spoolss_context
*ctx
=
7442 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
7443 uint16_t levels
[] = {1, 2, 3, 4, 5, 6};
7445 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
7446 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7447 const char *server_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
7449 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
7452 union spoolss_DriverInfo
*info
;
7454 torture_assert(tctx
,
7455 test_EnumPrinterDrivers_args(tctx
, b
, server_name
, ctx
->environment
, levels
[i
], &count
, &info
),
7456 "failed to enumerate drivers");
7459 torture_comment(tctx
, "No printer drivers returned\n");
7467 static bool test_DeletePrinter(struct torture_context
*tctx
,
7468 struct dcerpc_binding_handle
*b
,
7469 struct policy_handle
*handle
)
7471 struct spoolss_DeletePrinter r
;
7473 torture_comment(tctx
, "Testing DeletePrinter\n");
7475 r
.in
.handle
= handle
;
7477 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_DeletePrinter_r(b
, tctx
, &r
),
7478 "failed to delete printer");
7479 torture_assert_werr_ok(tctx
, r
.out
.result
,
7480 "failed to delete printer");
7485 static bool test_EnumPrinters_findname(struct torture_context
*tctx
,
7486 struct dcerpc_binding_handle
*b
,
7492 struct spoolss_EnumPrinters e
;
7494 union spoolss_PrinterInfo
*info
;
7505 e
.out
.count
= &count
;
7507 e
.out
.needed
= &needed
;
7509 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &e
),
7510 "failed to enum printers");
7512 if (W_ERROR_EQUAL(e
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
7513 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
7514 e
.in
.buffer
= &blob
;
7515 e
.in
.offered
= needed
;
7517 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &e
),
7518 "failed to enum printers");
7521 torture_assert_werr_ok(tctx
, e
.out
.result
,
7522 "failed to enum printers");
7524 for (i
=0; i
< count
; i
++) {
7526 const char *current
= NULL
;
7531 current
= info
[i
].info1
.name
;
7535 if (strequal(current
, name
)) {
7540 q
= strrchr(current
, '\\');
7543 torture_warning(tctx
,
7544 "server returns printername %s incl. servername although we did not set servername", current
);
7547 if (strequal(q
, name
)) {
7557 static bool test_AddPrinter_wellknown(struct torture_context
*tctx
,
7558 struct dcerpc_pipe
*p
,
7559 const char *printername
,
7563 struct spoolss_AddPrinter r
;
7564 struct spoolss_AddPrinterEx rex
;
7565 struct spoolss_SetPrinterInfoCtr info_ctr
;
7566 struct spoolss_SetPrinterInfo1 info1
;
7567 struct spoolss_DevmodeContainer devmode_ctr
;
7568 struct sec_desc_buf secdesc_ctr
;
7569 struct spoolss_UserLevelCtr userlevel_ctr
;
7570 struct policy_handle handle
;
7572 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7574 ZERO_STRUCT(devmode_ctr
);
7575 ZERO_STRUCT(secdesc_ctr
);
7576 ZERO_STRUCT(userlevel_ctr
);
7579 torture_comment(tctx
, "Testing AddPrinter%s(%s) level 1\n",
7580 ex
? "Ex":"", printername
);
7582 /* try to add printer to wellknown printer list (level 1) */
7584 userlevel_ctr
.level
= 1;
7586 info_ctr
.info
.info1
= &info1
;
7589 rex
.in
.server
= NULL
;
7590 rex
.in
.info_ctr
= &info_ctr
;
7591 rex
.in
.devmode_ctr
= &devmode_ctr
;
7592 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
7593 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
7594 rex
.out
.handle
= &handle
;
7597 r
.in
.info_ctr
= &info_ctr
;
7598 r
.in
.devmode_ctr
= &devmode_ctr
;
7599 r
.in
.secdesc_ctr
= &secdesc_ctr
;
7600 r
.out
.handle
= &handle
;
7602 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7603 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7604 "failed to add printer");
7605 result
= ex
? rex
.out
.result
: r
.out
.result
;
7606 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
7607 "unexpected result code");
7609 info1
.name
= printername
;
7610 info1
.flags
= PRINTER_ATTRIBUTE_SHARED
;
7612 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7613 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7614 "failed to add printer");
7615 result
= ex
? rex
.out
.result
: r
.out
.result
;
7616 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
7617 "unexpected result code");
7619 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7620 better do a real check to see the printer is really there */
7622 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, b
,
7623 PRINTER_ENUM_NETWORK
, 1,
7626 "failed to enum printers");
7628 torture_assert(tctx
, found
, "failed to find newly added printer");
7632 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7633 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7634 "failed to add printer");
7635 result
= ex
? rex
.out
.result
: r
.out
.result
;
7636 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
7637 "unexpected result code");
7639 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7640 better do a real check to see the printer has really been removed
7641 from the well known printer list */
7645 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, b
,
7646 PRINTER_ENUM_NETWORK
, 1,
7649 "failed to enum printers");
7651 torture_assert(tctx
, !found
, "printer still in well known printer list");
7656 static bool test_AddPrinter_normal(struct torture_context
*tctx
,
7657 struct dcerpc_pipe
*p
,
7658 struct policy_handle
*handle_p
,
7659 const char *printername
,
7660 const char *drivername
,
7661 const char *portname
,
7662 struct spoolss_DeviceMode
*devmode
,
7666 struct spoolss_AddPrinter r
;
7667 struct spoolss_AddPrinterEx rex
;
7668 struct spoolss_SetPrinterInfoCtr info_ctr
;
7669 struct spoolss_SetPrinterInfo2 info2
;
7670 struct spoolss_DevmodeContainer devmode_ctr
;
7671 struct sec_desc_buf secdesc_ctr
;
7672 struct spoolss_UserLevelCtr userlevel_ctr
;
7673 struct policy_handle handle
;
7675 bool existing_printer_deleted
= false;
7676 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7678 ZERO_STRUCT(devmode_ctr
);
7679 ZERO_STRUCT(secdesc_ctr
);
7680 ZERO_STRUCT(userlevel_ctr
);
7682 torture_comment(tctx
, "Testing AddPrinter%s(%s) level 2\n",
7683 ex
? "Ex":"", printername
);
7685 devmode_ctr
.devmode
= devmode
;
7687 userlevel_ctr
.level
= 1;
7689 rex
.in
.server
= NULL
;
7690 rex
.in
.info_ctr
= &info_ctr
;
7691 rex
.in
.devmode_ctr
= &devmode_ctr
;
7692 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
7693 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
7694 rex
.out
.handle
= &handle
;
7697 r
.in
.info_ctr
= &info_ctr
;
7698 r
.in
.devmode_ctr
= &devmode_ctr
;
7699 r
.in
.secdesc_ctr
= &secdesc_ctr
;
7700 r
.out
.handle
= &handle
;
7704 /* try to add printer to printer list (level 2) */
7708 info_ctr
.info
.info2
= &info2
;
7711 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7712 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7713 "failed to add printer");
7714 result
= ex
? rex
.out
.result
: r
.out
.result
;
7715 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
7716 "unexpected result code");
7718 info2
.printername
= printername
;
7720 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7721 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7722 "failed to add printer");
7723 result
= ex
? rex
.out
.result
: r
.out
.result
;
7725 if (W_ERROR_EQUAL(result
, WERR_PRINTER_ALREADY_EXISTS
)) {
7726 struct policy_handle printer_handle
;
7728 if (existing_printer_deleted
) {
7729 torture_fail(tctx
, "already deleted printer still existing?");
7732 torture_assert(tctx
, call_OpenPrinterEx(tctx
, p
, printername
, NULL
, &printer_handle
),
7733 "failed to open printer handle");
7735 torture_assert(tctx
, test_DeletePrinter(tctx
, b
, &printer_handle
),
7736 "failed to delete printer");
7738 torture_assert(tctx
, test_ClosePrinter(tctx
, b
, &printer_handle
),
7739 "failed to close server handle");
7741 existing_printer_deleted
= true;
7746 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PORT
,
7747 "unexpected result code");
7749 info2
.portname
= portname
;
7751 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7752 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7753 "failed to add printer");
7754 result
= ex
? rex
.out
.result
: r
.out
.result
;
7755 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTER_DRIVER
,
7756 "unexpected result code");
7758 info2
.drivername
= drivername
;
7760 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7761 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7762 "failed to add printer");
7763 result
= ex
? rex
.out
.result
: r
.out
.result
;
7765 /* w2k8r2 allows one to add printer w/o defining printprocessor */
7767 if (!W_ERROR_IS_OK(result
)) {
7768 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTPROCESSOR
,
7769 "unexpected result code");
7771 info2
.printprocessor
= "winprint";
7773 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7774 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7775 "failed to add printer");
7776 result
= ex
? rex
.out
.result
: r
.out
.result
;
7777 torture_assert_werr_ok(tctx
, result
,
7778 "failed to add printer");
7783 /* we are paranoid, really check if the printer is there now */
7785 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, b
,
7786 PRINTER_ENUM_LOCAL
, 1,
7789 "failed to enum printers");
7790 torture_assert(tctx
, found
, "failed to find newly added printer");
7792 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
7793 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
7794 "failed to add printer");
7795 result
= ex
? rex
.out
.result
: r
.out
.result
;
7796 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
7797 "unexpected result code");
7802 static bool test_printer_info(struct torture_context
*tctx
,
7805 struct torture_printer_context
*t
=
7806 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
7807 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
7808 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7812 if (torture_setting_bool(tctx
, "samba3", false)) {
7813 torture_skip(tctx
, "skipping printer info cross tests against samba 3");
7816 if (!test_PrinterInfo(tctx
, b
, &t
->handle
)) {
7820 if (!test_SetPrinter_errors(tctx
, b
, &t
->handle
)) {
7827 static bool test_EnumPrinterKey(struct torture_context
*tctx
,
7828 struct dcerpc_binding_handle
*b
,
7829 struct policy_handle
*handle
,
7830 const char *key_name
,
7831 const char ***array
)
7833 struct spoolss_EnumPrinterKey r
;
7834 uint32_t needed
= 0;
7835 union spoolss_KeyNames key_buffer
= {};
7836 int32_t offered
[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7840 r
.in
.handle
= handle
;
7841 r
.in
.key_name
= key_name
;
7842 r
.out
.key_buffer
= &key_buffer
;
7843 r
.out
.needed
= &needed
;
7844 r
.out
._ndr_size
= &_ndr_size
;
7846 for (i
=0; i
< ARRAY_SIZE(offered
); i
++) {
7848 if (offered
[i
] < 0 && needed
) {
7852 r
.in
.offered
= needed
+ offered
[i
];
7854 r
.in
.offered
= offered
[i
];
7857 ZERO_STRUCT(key_buffer
);
7859 torture_comment(tctx
, "Testing EnumPrinterKey(%s) with %d offered\n", r
.in
.key_name
, r
.in
.offered
);
7861 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterKey_r(b
, tctx
, &r
),
7862 "failed to call EnumPrinterKey");
7863 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
7865 torture_assert(tctx
, (_ndr_size
== r
.in
.offered
/2),
7866 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7867 _ndr_size
, r
.in
.offered
/2));
7869 r
.in
.offered
= needed
;
7870 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterKey_r(b
, tctx
, &r
),
7871 "failed to call EnumPrinterKey");
7874 if (offered
[i
] > 0) {
7875 torture_assert_werr_ok(tctx
, r
.out
.result
,
7876 "failed to call EnumPrinterKey");
7879 torture_assert(tctx
, (_ndr_size
== r
.in
.offered
/2),
7880 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7881 _ndr_size
, r
.in
.offered
/2));
7883 torture_assert(tctx
, (*r
.out
.needed
<= r
.in
.offered
),
7884 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r
.out
.needed
, r
.in
.offered
));
7886 torture_assert(tctx
, (*r
.out
.needed
<= _ndr_size
* 2),
7887 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r
.out
.needed
, _ndr_size
));
7889 if (key_buffer
.string_array
) {
7890 uint32_t calc_needed
= 0;
7892 for (s
=0; key_buffer
.string_array
[s
]; s
++) {
7893 calc_needed
+= strlen_m_term(key_buffer
.string_array
[s
])*2;
7895 if (!key_buffer
.string_array
[0]) {
7900 torture_assert_int_equal(tctx
, *r
.out
.needed
, calc_needed
,
7901 "EnumPrinterKey unexpected size");
7906 *array
= key_buffer
.string_array
;
7912 bool test_printer_all_keys(struct torture_context
*tctx
,
7913 struct dcerpc_binding_handle
*b
,
7914 struct policy_handle
*handle
)
7916 const char **key_array
= NULL
;
7919 torture_comment(tctx
, "Testing Printer Keys\n");
7921 torture_assert(tctx
, test_EnumPrinterKey(tctx
, b
, handle
, "", &key_array
),
7922 "failed to call test_EnumPrinterKey");
7924 for (i
=0; key_array
&& key_array
[i
]; i
++) {
7925 torture_assert(tctx
, test_EnumPrinterKey(tctx
, b
, handle
, key_array
[i
], NULL
),
7926 "failed to call test_EnumPrinterKey");
7928 for (i
=0; key_array
&& key_array
[i
]; i
++) {
7929 torture_assert(tctx
, test_EnumPrinterDataEx(tctx
, b
, handle
, key_array
[i
], NULL
, NULL
),
7930 "failed to call test_EnumPrinterDataEx");
7933 torture_comment(tctx
, "Printer Keys test succeeded\n\n");
7938 static bool test_openprinter_wrap(struct torture_context
*tctx
,
7941 struct torture_printer_context
*t
=
7942 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
7943 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
7944 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7945 const char *printername
= t
->info2
.printername
;
7947 return test_openprinter(tctx
, b
, printername
);
7950 static bool test_csetprinter(struct torture_context
*tctx
,
7953 struct torture_printer_context
*t
=
7954 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
7955 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
7957 const char *printername
= talloc_asprintf(tctx
, "%s2", t
->info2
.printername
);
7958 const char *drivername
= t
->added_driver
? t
->driver
.info8
.driver_name
: t
->info2
.drivername
;
7959 const char *portname
= t
->info2
.portname
;
7961 union spoolss_PrinterInfo info
;
7962 struct policy_handle new_handle
, new_handle2
;
7963 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
7965 torture_comment(tctx
, "Testing c_setprinter\n");
7967 torture_assert(tctx
,
7968 test_GetPrinter_level(tctx
, b
, &t
->handle
, 0, &info
),
7969 "failed to get level 0 printer info");
7970 torture_comment(tctx
, "csetprinter on initial printer handle: %d\n",
7971 info
.info0
.c_setprinter
);
7973 /* check if c_setprinter on 1st handle increases after a printer has
7976 torture_assert(tctx
,
7977 test_AddPrinter_normal(tctx
, p
, &new_handle
, printername
, drivername
, portname
, NULL
, false),
7978 "failed to add new printer");
7979 torture_assert(tctx
,
7980 test_GetPrinter_level(tctx
, b
, &t
->handle
, 0, &info
),
7981 "failed to get level 0 printer info");
7982 torture_comment(tctx
, "csetprinter on initial printer handle (after add): %d\n",
7983 info
.info0
.c_setprinter
);
7985 /* check if c_setprinter on new handle increases after a printer has
7988 torture_assert(tctx
,
7989 test_GetPrinter_level(tctx
, b
, &new_handle
, 0, &info
),
7990 "failed to get level 0 printer info");
7991 torture_comment(tctx
, "csetprinter on created handle: %d\n",
7992 info
.info0
.c_setprinter
);
7994 /* open the new printer and check if c_setprinter increases */
7996 torture_assert(tctx
,
7997 call_OpenPrinterEx(tctx
, p
, printername
, NULL
, &new_handle2
),
7998 "failed to open created printer");
7999 torture_assert(tctx
,
8000 test_GetPrinter_level(tctx
, b
, &new_handle2
, 0, &info
),
8001 "failed to get level 0 printer info");
8002 torture_comment(tctx
, "csetprinter on new handle (after openprinter): %d\n",
8003 info
.info0
.c_setprinter
);
8007 torture_assert(tctx
,
8008 test_ClosePrinter(tctx
, b
, &new_handle2
),
8009 "failed to close printer");
8010 torture_assert(tctx
,
8011 test_DeletePrinter(tctx
, b
, &new_handle
),
8012 "failed to delete new printer");
8017 static bool compose_local_driver_directory(struct torture_context
*tctx
,
8018 const char *environment
,
8019 const char *local_dir
,
8024 p
= strrchr(local_dir
, '/');
8030 if (strequal(environment
, SPOOLSS_ARCHITECTURE_x64
)) {
8031 if (!strequal(p
, "x64")) {
8032 *path
= talloc_asprintf(tctx
, "%s/x64", local_dir
);
8034 } else if (strequal(environment
, SPOOLSS_ARCHITECTURE_NT_X86
)) {
8035 if (!strequal(p
, "i386")) {
8036 *path
= talloc_asprintf(tctx
, "%s/i386", local_dir
);
8039 torture_assert(tctx
, "unknown environment: '%s'\n", environment
);
8046 static struct spoolss_DeviceMode
*torture_devicemode(TALLOC_CTX
*mem_ctx
,
8047 const char *devicename
)
8049 struct spoolss_DeviceMode
*r
;
8051 r
= talloc_zero(mem_ctx
, struct spoolss_DeviceMode
);
8056 r
->devicename
= talloc_strdup(r
, devicename
);
8057 r
->specversion
= DMSPEC_NT4_AND_ABOVE
;
8058 r
->driverversion
= 0x0600;
8060 r
->__driverextra_length
= 0;
8061 r
->fields
= DEVMODE_FORMNAME
|
8063 DEVMODE_PRINTQUALITY
|
8064 DEVMODE_DEFAULTSOURCE
|
8068 DEVMODE_ORIENTATION
;
8069 r
->orientation
= DMORIENT_PORTRAIT
;
8070 r
->papersize
= DMPAPER_LETTER
;
8075 r
->defaultsource
= DMBIN_FORMSOURCE
;
8076 r
->printquality
= DMRES_HIGH
;
8077 r
->color
= DMRES_MONOCHROME
;
8078 r
->duplex
= DMDUP_SIMPLEX
;
8080 r
->ttoption
= DMTT_SUBDEV
;
8081 r
->collate
= DMCOLLATE_FALSE
;
8082 r
->formname
= talloc_strdup(r
, "Letter");
8088 static bool test_architecture_buffer(struct torture_context
*tctx
,
8091 struct test_spoolss_context
*ctx
=
8092 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
8094 struct spoolss_OpenPrinterEx r
;
8095 struct spoolss_UserLevel1 u1
;
8096 struct policy_handle handle
;
8097 uint32_t architectures
[] = {
8098 PROCESSOR_ARCHITECTURE_INTEL
,
8099 PROCESSOR_ARCHITECTURE_IA64
,
8100 PROCESSOR_ARCHITECTURE_AMD64
8104 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
8105 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8107 for (i
=0; i
< ARRAY_SIZE(architectures
); i
++) {
8109 torture_comment(tctx
, "Testing OpenPrinterEx with architecture %d\n", architectures
[i
]);
8117 u1
.processor
= architectures
[i
];
8119 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
8120 r
.in
.datatype
= NULL
;
8121 r
.in
.devmode_ctr
.devmode
= NULL
;
8122 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
8123 r
.in
.userlevel_ctr
.level
= 1;
8124 r
.in
.userlevel_ctr
.user_info
.level1
= &u1
;
8125 r
.out
.handle
= &handle
;
8127 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_OpenPrinterEx_r(b
, tctx
, &r
), "");
8128 torture_assert_werr_ok(tctx
, r
.out
.result
, "");
8131 struct spoolss_EnumPrinters e
;
8133 union spoolss_PrinterInfo
*info
;
8135 e
.in
.flags
= PRINTER_ENUM_LOCAL
;
8140 e
.out
.count
= &count
;
8142 e
.out
.needed
= &needed
[i
];
8144 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &e
), "");
8146 torture_comment(tctx
, "needed was %d\n", needed
[i
]);
8150 torture_assert(tctx
, test_ClosePrinter(tctx
, b
, &handle
), "");
8153 for (i
=1; i
< ARRAY_SIZE(architectures
); i
++) {
8154 if (needed
[i
-1] != needed
[i
]) {
8156 talloc_asprintf(tctx
, "needed size %d for architecture %d != needed size %d for architecture %d\n",
8157 needed
[i
-1], architectures
[i
-1], needed
[i
], architectures
[i
]));
8164 static bool test_get_core_printer_drivers_arch_guid(struct torture_context
*tctx
,
8165 struct dcerpc_pipe
*p
,
8166 const char *architecture
,
8167 const char *guid_str
,
8168 const char **package_id
)
8170 struct spoolss_GetCorePrinterDrivers r
;
8171 struct spoolss_CorePrinterDriver core_printer_drivers
;
8172 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, 2);
8174 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8177 s
= talloc_zero_array(tctx
, const char *, 2);
8179 r
.in
.servername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
8180 r
.in
.architecture
= "foobar";
8181 r
.in
.core_driver_size
= 0;
8182 r
.in
.core_driver_dependencies
= (uint16_t *)blob
.data
;
8183 r
.in
.core_printer_driver_count
= 0;
8184 r
.out
.core_printer_drivers
= &core_printer_drivers
;
8186 torture_assert_ntstatus_ok(tctx
,
8187 dcerpc_spoolss_GetCorePrinterDrivers_r(b
, tctx
, &r
),
8188 "spoolss_GetCorePrinterDrivers failed");
8189 torture_assert_hresult_equal(tctx
, r
.out
.result
, HRES_E_INVALIDARG
,
8190 "spoolss_GetCorePrinterDrivers failed");
8192 guid
= GUID_random();
8193 s
[0] = GUID_string2(tctx
, &guid
);
8195 torture_assert(tctx
,
8196 push_reg_multi_sz(tctx
, &blob
, s
),
8197 "push_reg_multi_sz failed");
8199 r
.in
.core_driver_size
= blob
.length
/2;
8200 r
.in
.core_driver_dependencies
= (uint16_t *)blob
.data
;
8201 r
.in
.core_printer_driver_count
= 1;
8202 r
.out
.core_printer_drivers
= talloc_zero_array(tctx
, struct spoolss_CorePrinterDriver
, r
.in
.core_printer_driver_count
);
8204 torture_assert_ntstatus_ok(tctx
,
8205 dcerpc_spoolss_GetCorePrinterDrivers_r(b
, tctx
, &r
),
8206 "spoolss_GetCorePrinterDrivers failed");
8207 torture_assert_werr_equal(tctx
,
8208 W_ERROR(WIN32_FROM_HRESULT(r
.out
.result
)), WERR_INVALID_ENVIRONMENT
,
8209 "spoolss_GetCorePrinterDrivers failed");
8211 r
.in
.architecture
= architecture
;
8213 torture_assert_ntstatus_ok(tctx
,
8214 dcerpc_spoolss_GetCorePrinterDrivers_r(b
, tctx
, &r
),
8215 "spoolss_GetCorePrinterDrivers failed");
8216 torture_assert_werr_equal(tctx
,
8217 W_ERROR(WIN32_FROM_HRESULT(r
.out
.result
)), WERR_NOT_FOUND
,
8218 "spoolss_GetCorePrinterDrivers failed");
8220 s
[0] = talloc_strdup(s
, guid_str
);
8222 torture_assert(tctx
,
8223 push_reg_multi_sz(tctx
, &blob
, s
),
8224 "push_reg_multi_sz failed");
8226 r
.in
.core_driver_size
= blob
.length
/2;
8227 r
.in
.core_driver_dependencies
= (uint16_t *)blob
.data
;
8228 r
.in
.core_printer_driver_count
= 1;
8229 r
.out
.core_printer_drivers
= talloc_zero_array(tctx
, struct spoolss_CorePrinterDriver
, r
.in
.core_printer_driver_count
);
8231 torture_assert_ntstatus_ok(tctx
,
8232 dcerpc_spoolss_GetCorePrinterDrivers_r(b
, tctx
, &r
),
8233 "spoolss_GetCorePrinterDrivers failed");
8234 torture_assert_hresult_ok(tctx
, r
.out
.result
,
8235 "spoolss_GetCorePrinterDrivers failed");
8238 *package_id
= r
.out
.core_printer_drivers
[0].szPackageID
;
8244 static bool test_get_core_printer_drivers(struct torture_context
*tctx
,
8247 struct test_spoolss_context
*ctx
=
8248 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
8250 const char *architectures
[] = {
8251 SPOOLSS_ARCHITECTURE_NT_X86
,
8252 SPOOLSS_ARCHITECTURE_x64
8255 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
8257 for (i
=0; i
< ARRAY_SIZE(architectures
); i
++) {
8259 torture_comment(tctx
, "Testing GetCorePrinterDrivers(\"%s\",\"%s\")\n",
8261 SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV
);
8263 torture_assert(tctx
,
8264 test_get_core_printer_drivers_arch_guid(tctx
, p
,
8266 SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV
,
8274 static bool test_get_printer_driver_package_path(struct torture_context
*tctx
,
8277 struct test_spoolss_context
*ctx
=
8278 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
8280 const char *architectures
[] = {
8281 SPOOLSS_ARCHITECTURE_NT_X86
,
8282 SPOOLSS_ARCHITECTURE_x64
8285 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
8286 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8288 for (i
=0; i
< ARRAY_SIZE(architectures
); i
++) {
8289 struct spoolss_GetPrinterDriverPackagePath r
;
8290 uint32_t required
= 0;
8291 const char *package_id
= NULL
;
8293 test_get_core_printer_drivers_arch_guid(tctx
, p
,
8295 SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV
,
8298 torture_comment(tctx
, "Testing GetPrinterDriverPackagePath(\"%s\",\"%s\")\n",
8299 architectures
[i
], package_id
);
8301 r
.in
.servername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
8302 r
.in
.architecture
= "foobar";
8303 r
.in
.language
= NULL
;
8304 r
.in
.package_id
= "";
8305 r
.in
.driver_package_cab_size
= 0;
8306 r
.in
.driver_package_cab
= NULL
;
8308 r
.out
.required
= &required
;
8309 r
.out
.driver_package_cab
= NULL
;
8311 torture_assert_ntstatus_ok(tctx
,
8312 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b
, tctx
, &r
),
8313 "spoolss_GetPrinterDriverPackagePath failed");
8314 torture_assert_werr_equal(tctx
,
8315 W_ERROR(WIN32_FROM_HRESULT(r
.out
.result
)), WERR_INVALID_ENVIRONMENT
,
8316 "spoolss_GetPrinterDriverPackagePath failed");
8318 r
.in
.architecture
= architectures
[i
];
8320 torture_assert_ntstatus_ok(tctx
,
8321 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b
, tctx
, &r
),
8322 "spoolss_GetPrinterDriverPackagePath failed");
8323 torture_assert_werr_equal(tctx
,
8324 W_ERROR(WIN32_FROM_HRESULT(r
.out
.result
)), WERR_FILE_NOT_FOUND
,
8325 "spoolss_GetPrinterDriverPackagePath failed");
8327 r
.in
.package_id
= package_id
;
8329 torture_assert_ntstatus_ok(tctx
,
8330 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b
, tctx
, &r
),
8331 "spoolss_GetPrinterDriverPackagePath failed");
8332 torture_assert_hresult_ok(tctx
, r
.out
.result
,
8333 "spoolss_GetPrinterDriverPackagePath failed");
8335 r
.in
.driver_package_cab_size
= required
;
8336 r
.in
.driver_package_cab
= talloc_zero_array(tctx
, char, required
);
8337 r
.out
.driver_package_cab
= talloc_zero_array(tctx
, char, required
);
8339 torture_assert_ntstatus_ok(tctx
,
8340 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b
, tctx
, &r
),
8341 "spoolss_GetPrinterDriverPackagePath failed");
8342 torture_assert_hresult_ok(tctx
, r
.out
.result
,
8343 "spoolss_GetPrinterDriverPackagePath failed");
8345 r
.in
.servername
= NULL
;
8347 torture_assert_ntstatus_ok(tctx
,
8348 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b
, tctx
, &r
),
8349 "spoolss_GetPrinterDriverPackagePath failed");
8350 torture_assert_werr_equal(tctx
,
8351 W_ERROR(WIN32_FROM_HRESULT(r
.out
.result
)), WERR_INSUFFICIENT_BUFFER
,
8352 "spoolss_GetPrinterDriverPackagePath failed");
8354 r
.in
.driver_package_cab_size
= required
;
8355 r
.in
.driver_package_cab
= talloc_zero_array(tctx
, char, required
);
8356 r
.out
.driver_package_cab
= talloc_zero_array(tctx
, char, required
);
8358 torture_assert_ntstatus_ok(tctx
,
8359 dcerpc_spoolss_GetPrinterDriverPackagePath_r(b
, tctx
, &r
),
8360 "spoolss_GetPrinterDriverPackagePath failed");
8361 torture_assert_hresult_ok(tctx
, r
.out
.result
,
8362 "spoolss_GetPrinterDriverPackagePath failed");
8369 static bool test_get_printer_printserverhandle(struct torture_context
*tctx
,
8372 struct test_spoolss_context
*ctx
=
8373 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
8375 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
8376 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8377 uint32_t levels
[] = {0, 1, 2, /* 3,*/ 4, 5, 6, 7, 8};
8380 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
8382 torture_assert(tctx
,
8383 test_GetPrinter_level_exp(tctx
, b
, &ctx
->server_handle
,
8384 levels
[i
], WERR_INVALID_LEVEL
,
8386 "failed to call GetPrinter");
8389 torture_assert(tctx
,
8390 test_GetPrinter_level(tctx
, b
, &ctx
->server_handle
, 3, NULL
),
8391 "failed to call GetPrinter");
8396 #define TEST_SID "S-1-5-21-1234567890-1234567890-1234567890-500"
8398 static bool test_set_printer_printserverhandle(struct torture_context
*tctx
,
8401 struct test_spoolss_context
*ctx
=
8402 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
8404 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
8405 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8406 union spoolss_PrinterInfo info
;
8407 struct spoolss_SetPrinterInfoCtr info_ctr
;
8408 struct spoolss_SetPrinterInfo3 info3
;
8409 struct spoolss_DevmodeContainer devmode_ctr
;
8410 struct sec_desc_buf secdesc_ctr
;
8411 struct security_descriptor
*sd
;
8412 struct security_ace
*ace
;
8416 torture_assert(tctx
,
8417 test_GetPrinter_level(tctx
, b
, &ctx
->server_handle
, 3, &info
),
8418 "failed to call GetPrinter");
8420 secdesc_ctr
.sd
= info
.info3
.secdesc
;
8421 secdesc_ctr
.sd
->owner_sid
= NULL
;
8422 secdesc_ctr
.sd
->group_sid
= NULL
;
8424 sd
= security_descriptor_copy(tctx
, secdesc_ctr
.sd
);
8429 ace
= security_ace_create(tctx
,
8431 SEC_ACE_TYPE_ACCESS_ALLOWED
,
8433 SEC_ACE_FLAG_CONTAINER_INHERIT
);
8434 torture_assert(tctx
, ace
, "failed to create ace");
8436 torture_assert_ntstatus_ok(tctx
,
8437 security_descriptor_dacl_add(sd
, ace
),
8438 "failed to add ace");
8440 secdesc_ctr
.sd
= sd
;
8442 info3
.sec_desc_ptr
= 0;
8445 info_ctr
.info
.info3
= &info3
;
8447 ZERO_STRUCT(devmode_ctr
);
8449 torture_assert(tctx
,
8450 test_SetPrinter(tctx
, b
, &ctx
->server_handle
, &info_ctr
,
8451 &devmode_ctr
, &secdesc_ctr
, 0),
8452 "failed to call SetPrinter");
8454 torture_assert(tctx
,
8455 test_GetPrinter_level(tctx
, b
, &ctx
->server_handle
, 3, &info
),
8456 "failed to call GetPrinter");
8458 for (i
= 0; i
< info
.info3
.secdesc
->dacl
->num_aces
; i
++) {
8459 if (security_ace_equal(&info
.info3
.secdesc
->dacl
->aces
[i
], ace
)) {
8464 if (i
== info
.info3
.secdesc
->dacl
->num_aces
) {
8465 torture_fail(tctx
, "ace not present");
8468 torture_assert(tctx
,
8469 dom_sid_parse(TEST_SID
, &sid
),
8470 "failed to parse sid");
8472 torture_assert_ntstatus_ok(tctx
,
8473 security_descriptor_dacl_del(info
.info3
.secdesc
, &sid
),
8474 "failed to remove ace from sd");
8476 secdesc_ctr
.sd
= info
.info3
.secdesc
;
8478 torture_assert(tctx
,
8479 test_SetPrinter(tctx
, b
, &ctx
->server_handle
, &info_ctr
,
8480 &devmode_ctr
, &secdesc_ctr
, 0),
8481 "failed to call SetPrinter");
8483 torture_assert(tctx
,
8484 test_GetPrinter_level(tctx
, b
, &ctx
->server_handle
, 3, &info
),
8485 "failed to call GetPrinter");
8487 for (i
= 0; i
< info
.info3
.secdesc
->dacl
->num_aces
; i
++) {
8488 if (security_ace_equal(&info
.info3
.secdesc
->dacl
->aces
[i
], ace
)) {
8489 torture_fail(tctx
, "ace still present");
8497 static bool test_PrintServer_Forms_Winreg(struct torture_context
*tctx
,
8500 struct test_spoolss_context
*ctx
=
8501 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
8502 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
8503 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8505 return test_Forms_winreg(tctx
, b
, &ctx
->server_handle
, true, NULL
);
8508 static bool test_PrintServer_Forms(struct torture_context
*tctx
,
8511 struct test_spoolss_context
*ctx
=
8512 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
8513 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
8514 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8516 return test_Forms(tctx
, b
, &ctx
->server_handle
, true, NULL
, NULL
, NULL
);
8519 static bool test_PrintServer_EnumForms(struct torture_context
*tctx
,
8522 struct test_spoolss_context
*ctx
=
8523 talloc_get_type_abort(private_data
, struct test_spoolss_context
);
8524 struct dcerpc_pipe
*p
= ctx
->spoolss_pipe
;
8525 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8527 return test_EnumForms_all(tctx
, b
, &ctx
->server_handle
, true);
8530 static bool torture_rpc_spoolss_setup_common(struct torture_context
*tctx
, struct test_spoolss_context
*t
)
8534 status
= torture_rpc_connection(tctx
, &t
->spoolss_pipe
, &ndr_table_spoolss
);
8536 torture_assert_ntstatus_ok(tctx
, status
, "Error connecting to server");
8538 torture_assert(tctx
,
8539 test_OpenPrinter_server(tctx
, t
->spoolss_pipe
, &t
->server_handle
),
8540 "failed to open printserver");
8541 torture_assert(tctx
,
8542 test_get_environment(tctx
, t
->spoolss_pipe
->binding_handle
, &t
->server_handle
, &t
->environment
),
8543 "failed to get environment");
8548 static bool torture_rpc_spoolss_setup(struct torture_context
*tctx
, void **data
)
8550 struct test_spoolss_context
*t
;
8552 *data
= t
= talloc_zero(tctx
, struct test_spoolss_context
);
8554 return torture_rpc_spoolss_setup_common(tctx
, t
);
8557 static bool torture_rpc_spoolss_teardown_common(struct torture_context
*tctx
, struct test_spoolss_context
*t
)
8559 test_ClosePrinter(tctx
, t
->spoolss_pipe
->binding_handle
, &t
->server_handle
);
8564 static bool torture_rpc_spoolss_teardown(struct torture_context
*tctx
, void *data
)
8566 struct test_spoolss_context
*t
= talloc_get_type(data
, struct test_spoolss_context
);
8569 ret
= torture_rpc_spoolss_teardown_common(tctx
, t
);
8575 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context
*tctx
, struct torture_printer_context
*t
)
8577 struct dcerpc_pipe
*p
;
8578 struct dcerpc_binding_handle
*b
;
8579 const char *server_name_slash
;
8580 const char *driver_name
;
8581 const char *printer_name
;
8582 const char *port_name
;
8584 torture_assert_ntstatus_ok(tctx
,
8585 torture_rpc_connection(tctx
, &t
->spoolss_pipe
, &ndr_table_spoolss
),
8586 "Error connecting to server");
8588 p
= t
->spoolss_pipe
;
8589 b
= p
->binding_handle
;
8590 server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
8592 t
->driver
.info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
8593 t
->driver
.info8
.driver_name
= TORTURE_DRIVER
;
8594 t
->driver
.info8
.driver_path
= "pscript5.dll";
8595 t
->driver
.info8
.data_file
= "cups6.ppd";
8596 t
->driver
.info8
.config_file
= "ps5ui.dll";
8597 t
->driver
.info8
.help_file
= "pscript.hlp";
8598 t
->driver
.info8
.default_datatype
= "RAW";
8599 t
->driver
.info8
.dependent_files
= talloc_zero(t
, struct spoolss_StringArray
);
8600 t
->driver
.info8
.dependent_files
->string
= talloc_zero_array(t
, const char *, 8 + 1);
8601 t
->driver
.info8
.dependent_files
->string
[0] = "pscript5.dll";
8602 t
->driver
.info8
.dependent_files
->string
[1] = "cups6.ppd";
8603 t
->driver
.info8
.dependent_files
->string
[2] = "ps5ui.dll";
8604 t
->driver
.info8
.dependent_files
->string
[3] = "pscript.hlp";
8605 t
->driver
.info8
.dependent_files
->string
[4] = "pscript.ntf";
8606 t
->driver
.info8
.dependent_files
->string
[5] = "cups6.ini";
8607 t
->driver
.info8
.dependent_files
->string
[6] = "cupsps6.dll";
8608 t
->driver
.info8
.dependent_files
->string
[7] = "cupsui6.dll";
8610 t
->driver
.local
.driver_directory
= "/usr/share/cups/drivers";
8612 t
->info2
.portname
= "LPT1:";
8614 printer_name
= t
->info2
.printername
;
8615 port_name
= t
->info2
.portname
;
8617 torture_assert(tctx
,
8618 fillup_printserver_info(tctx
, p
, &t
->driver
),
8619 "failed to fillup printserver info");
8621 t
->driver
.info8
.architecture
= talloc_strdup(t
, t
->driver
.remote
.environment
);
8623 torture_assert(tctx
,
8624 compose_local_driver_directory(tctx
, t
->driver
.remote
.environment
,
8625 t
->driver
.local
.driver_directory
,
8626 &t
->driver
.local
.driver_directory
),
8627 "failed to compose local driver directory");
8629 t
->info2
.drivername
= "Microsoft XPS Document Writer";
8631 if (test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, t
->driver
.remote
.environment
, 3, t
->info2
.drivername
, NULL
)) {
8632 torture_comment(tctx
, "driver '%s' (architecture: %s, version: 3) is present on server\n",
8633 t
->info2
.drivername
, t
->driver
.remote
.environment
);
8634 t
->have_driver
= true;
8638 torture_comment(tctx
, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
8639 t
->info2
.drivername
, t
->driver
.remote
.environment
);
8641 t
->info2
.drivername
= "Microsoft XPS Document Writer v4";
8643 if (test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, t
->driver
.remote
.environment
, 3, t
->info2
.drivername
, NULL
)) {
8644 torture_comment(tctx
, "driver '%s' (architecture: %s, version: 4) is present on server\n",
8645 t
->info2
.drivername
, t
->driver
.remote
.environment
);
8646 t
->have_driver
= true;
8650 torture_comment(tctx
, "trying to upload own driver\n");
8652 if (!directory_exist(t
->driver
.local
.driver_directory
)) {
8653 torture_warning(tctx
, "no local driver is available!");
8654 t
->have_driver
= false;
8658 torture_assert(tctx
,
8659 upload_printer_driver(tctx
, dcerpc_server_name(p
), &t
->driver
),
8660 "failed to upload printer driver");
8662 torture_assert(tctx
,
8663 test_AddPrinterDriver_args_level_3(tctx
, b
, server_name_slash
, &t
->driver
.info8
, 0, false, NULL
),
8664 "failed to add driver");
8666 t
->added_driver
= true;
8667 t
->have_driver
= true;
8670 driver_name
= t
->added_driver
? t
->driver
.info8
.driver_name
: t
->info2
.drivername
;
8673 torture_assert(tctx
,
8674 test_AddPrinter_wellknown(tctx
, p
, printer_name
, t
->ex
),
8675 "failed to add wellknown printer");
8677 torture_assert(tctx
,
8678 test_AddPrinter_normal(tctx
, p
, &t
->handle
, printer_name
, driver_name
, port_name
, t
->devmode
, t
->ex
),
8679 "failed to add printer");
8685 static bool torture_rpc_spoolss_printer_setup(struct torture_context
*tctx
, void **data
)
8687 struct torture_printer_context
*t
;
8689 *data
= t
= talloc_zero(tctx
, struct torture_printer_context
);
8692 t
->wellknown
= false;
8693 t
->info2
.printername
= TORTURE_PRINTER
;
8696 return torture_rpc_spoolss_printer_setup_common(tctx
, t
);
8699 static bool torture_rpc_spoolss_printerex_setup(struct torture_context
*tctx
, void **data
)
8701 struct torture_printer_context
*t
;
8703 *data
= t
= talloc_zero(tctx
, struct torture_printer_context
);
8706 t
->wellknown
= false;
8707 t
->info2
.printername
= TORTURE_PRINTER_EX
;
8710 return torture_rpc_spoolss_printer_setup_common(tctx
, t
);
8713 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context
*tctx
, void **data
)
8715 struct torture_printer_context
*t
;
8717 *data
= t
= talloc_zero(tctx
, struct torture_printer_context
);
8720 t
->wellknown
= true;
8721 t
->info2
.printername
= TORTURE_WELLKNOWN_PRINTER
;
8726 torture_skip(tctx
, "skipping AddPrinter level 1");
8729 return torture_rpc_spoolss_printer_setup_common(tctx
, t
);
8732 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context
*tctx
, void **data
)
8734 struct torture_printer_context
*t
;
8736 *data
= t
= talloc_zero(tctx
, struct torture_printer_context
);
8739 t
->wellknown
= true;
8740 t
->info2
.printername
= TORTURE_WELLKNOWN_PRINTER_EX
;
8745 torture_skip(tctx
, "skipping AddPrinterEx level 1");
8748 return torture_rpc_spoolss_printer_setup_common(tctx
, t
);
8752 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context
*tctx
, void **data
)
8754 struct torture_printer_context
*t
;
8756 *data
= t
= talloc_zero(tctx
, struct torture_printer_context
);
8759 t
->wellknown
= false;
8760 t
->info2
.printername
= TORTURE_PRINTER_EX
;
8761 t
->devmode
= torture_devicemode(t
, TORTURE_PRINTER_EX
);
8763 return torture_rpc_spoolss_printer_setup_common(tctx
, t
);
8767 static bool test_DeletePrinterDriverEx_exp(struct torture_context
*tctx
,
8768 struct dcerpc_binding_handle
*b
,
8771 const char *environment
,
8772 uint32_t delete_flags
,
8774 WERROR expected_result
);
8776 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context
*tctx
, struct torture_printer_context
*t
)
8779 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8780 struct dcerpc_binding_handle
*b
= NULL
;
8781 const char *server_name_slash
;
8787 b
= p
->binding_handle
;
8789 server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
8791 if (!t
->wellknown
) {
8792 const char *printer_name
= t
->info2
.printername
;
8794 torture_assert_goto(tctx
,
8795 test_DeletePrinter(tctx
, b
, &t
->handle
),
8798 "failed to delete printer");
8800 torture_assert_goto(tctx
,
8801 test_EnumPrinters_findname(tctx
, b
, PRINTER_ENUM_LOCAL
, 1,
8802 printer_name
, &found
),
8805 "failed to enumerate printers");
8807 torture_assert_goto(tctx
,
8811 "deleted printer still there");
8816 if (t
->added_driver
) {
8817 ok
= remove_printer_driver(tctx
,
8818 dcerpc_server_name(p
),
8821 torture_warning(tctx
,
8822 "failed to remove printer driver\n");
8825 ok
= test_DeletePrinterDriverEx_exp(tctx
, b
,
8827 t
->driver
.info8
.driver_name
,
8828 t
->driver
.info8
.architecture
,
8829 DPD_DELETE_ALL_FILES
,
8830 t
->driver
.info8
.version
,
8833 torture_warning(tctx
,
8834 "failed to delete printer driver via "
8842 static bool torture_rpc_spoolss_printer_teardown(struct torture_context
*tctx
, void *data
)
8844 struct torture_printer_context
*t
= talloc_get_type(data
, struct torture_printer_context
);
8847 ret
= torture_rpc_spoolss_printer_teardown_common(tctx
, t
);
8853 static bool test_print_test(struct torture_context
*tctx
,
8856 struct torture_printer_context
*t
=
8857 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8858 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8859 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8861 torture_assert(tctx
,
8862 test_PausePrinter(tctx
, b
, &t
->handle
),
8863 "failed to pause printer");
8865 torture_assert(tctx
,
8866 test_DoPrintTest(tctx
, b
, &t
->handle
),
8867 "failed to do print test");
8869 torture_assert(tctx
,
8870 test_ResumePrinter(tctx
, b
, &t
->handle
),
8871 "failed to resume printer");
8876 static bool test_print_test_extended(struct torture_context
*tctx
,
8879 struct torture_printer_context
*t
=
8880 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8881 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8882 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8885 torture_assert(tctx
,
8886 test_PausePrinter(tctx
, b
, &t
->handle
),
8887 "failed to pause printer");
8889 ret
= test_DoPrintTest_extended(tctx
, b
, &t
->handle
);
8891 torture_comment(tctx
, "WARNING! failed to do extended print test\n");
8892 if (torture_setting_bool(tctx
, "samba3", false)) {
8893 torture_comment(tctx
, "non-critical for samba3\n");
8895 tctx
->last_result
= TORTURE_SKIP
;
8899 torture_assert(tctx
,
8900 test_ResumePrinter(tctx
, b
, &t
->handle
),
8901 "failed to resume printer");
8906 static bool test_print_test_properties(struct torture_context
*tctx
,
8909 struct torture_printer_context
*t
=
8910 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8911 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8912 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8914 if (torture_setting_bool(tctx
, "samba3", false)) {
8915 torture_skip(tctx
, "skip printer job property tests against samba");
8918 torture_assert(tctx
,
8919 test_PausePrinter(tctx
, b
, &t
->handle
),
8920 "failed to pause printer");
8922 torture_assert(tctx
,
8923 test_DoPrintTest_properties(tctx
, b
, &t
->handle
),
8924 "failed to test print job properties");
8926 torture_assert(tctx
,
8927 test_ResumePrinter(tctx
, b
, &t
->handle
),
8928 "failed to resume printer");
8933 /* use smbd file IO to spool a print job */
8934 static bool test_print_test_smbd(struct torture_context
*tctx
,
8937 struct torture_printer_context
*t
=
8938 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
8939 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
8940 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
8943 union spoolss_JobInfo
*info
= NULL
;
8946 struct smb2_tree
*tree
;
8947 struct smb2_handle job_h
;
8948 struct smbcli_options options
;
8949 TALLOC_CTX
*mem_ctx
= talloc_new(tctx
);
8951 * Do not test against the dynamically added printers, printing via
8952 * smbd means that a different spoolss process may handle the
8953 * OpenPrinter request to the one that handled the AddPrinter request.
8954 * This currently leads to an ugly race condition where one process
8955 * sees the new printer and one doesn't.
8957 const char *share
= TORTURE_PRINTER_STATIC1
;
8959 torture_comment(tctx
, "Testing smbd job spooling\n");
8960 lpcfg_smbcli_options(tctx
->lp_ctx
, &options
);
8962 status
= smb2_connect(mem_ctx
,
8963 torture_setting_string(tctx
, "host", NULL
),
8964 lpcfg_smb_ports(tctx
->lp_ctx
),
8966 lpcfg_resolve_context(tctx
->lp_ctx
),
8967 samba_cmdline_get_creds(),
8971 lpcfg_socket_options(tctx
->lp_ctx
),
8972 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
));
8973 if (!NT_STATUS_IS_OK(status
)) {
8974 printf("Failed to connect to SMB2 printer %s - %s\n",
8975 share
, nt_errstr(status
));
8979 status
= torture_smb2_testfile(tree
, "smbd_spooler_job", &job_h
);
8980 torture_assert_ntstatus_ok(tctx
, status
, "smbd spool job create");
8982 status
= smb2_util_write(tree
, job_h
, "exciting print job data", 0,
8983 sizeof("exciting print job data"));
8984 torture_assert_ntstatus_ok(tctx
, status
, "smbd spool job write");
8986 /* check back end spoolss job was created */
8987 torture_assert(tctx
,
8988 test_EnumJobs_args(tctx
, b
, &t
->handle
, 1, WERR_OK
,
8990 "EnumJobs level 1 failed");
8992 for (i
= 0; i
< count
; i
++) {
8993 if (!strcmp(info
[i
].info1
.document_name
, "smbd_spooler_job")) {
8997 torture_assert(tctx
, (i
!= count
), "smbd_spooler_job not found");
8999 status
= smb2_util_close(tree
, job_h
);
9000 torture_assert_ntstatus_ok(tctx
, status
, "smbd spool job close");
9002 /* disconnect from printer share */
9003 talloc_free(mem_ctx
);
9008 static bool test_print_test_purge(struct torture_context
*tctx
,
9011 struct torture_printer_context
*t
=
9012 (struct torture_printer_context
*)talloc_get_type_abort(private_data
,
9013 struct torture_printer_context
);
9014 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9015 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
9016 uint32_t num_jobs
= 8;
9021 union spoolss_JobInfo
*info
;
9023 torture_assert(tctx
,
9024 test_PausePrinter(tctx
, b
, &t
->handle
),
9025 "failed to pause printer");
9027 job_ids
= talloc_zero_array(tctx
, uint32_t, num_jobs
);
9028 for (i
=0; i
< num_jobs
; i
++) {
9029 ret
= test_DoPrintTest_add_one_job(tctx
, b
, &t
->handle
,
9032 torture_assert(tctx
, ret
, "failed to add print job");
9035 torture_assert(tctx
,
9036 test_EnumJobs_args(tctx
, b
, &t
->handle
, 1, WERR_OK
,
9038 "EnumJobs level 1 failed");
9040 torture_assert_int_equal(tctx
, count
, num_jobs
,
9041 "unexpected number of jobs in queue");
9043 torture_assert(tctx
,
9044 test_printer_purge(tctx
, b
, &t
->handle
),
9045 "failed to purge printer");
9047 torture_assert(tctx
,
9048 test_EnumJobs_args(tctx
, b
, &t
->handle
, 1, WERR_OK
,
9050 "EnumJobs level 1 failed");
9052 torture_assert_int_equal(tctx
, count
, 0,
9053 "unexpected number of jobs in queue");
9055 torture_assert(tctx
,
9056 test_ResumePrinter(tctx
, b
, &t
->handle
),
9057 "failed to resume printer");
9062 static bool test_printer_sd(struct torture_context
*tctx
,
9065 struct torture_printer_context
*t
=
9066 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
9067 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9068 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
9070 torture_assert(tctx
,
9071 test_PrinterInfo_SD(tctx
, b
, &t
->handle
),
9072 "failed to test security descriptors");
9077 static bool test_printer_dm(struct torture_context
*tctx
,
9080 struct torture_printer_context
*t
=
9081 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
9082 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9084 torture_assert(tctx
,
9085 test_PrinterInfo_DevMode(tctx
, p
, &t
->handle
, t
->info2
.printername
, t
->devmode
),
9086 "failed to test devicemodes");
9091 static bool test_printer_info_winreg(struct torture_context
*tctx
,
9094 struct torture_printer_context
*t
=
9095 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
9096 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9098 torture_assert(tctx
,
9099 test_PrinterInfo_winreg(tctx
, p
, &t
->handle
, t
->info2
.printername
),
9100 "failed to test printer info winreg");
9105 static bool test_printserver_info_winreg(struct torture_context
*tctx
,
9108 struct test_spoolss_context
*t
=
9109 (struct test_spoolss_context
*)talloc_get_type_abort(private_data
, struct test_spoolss_context
);
9110 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9112 torture_assert(tctx
,
9113 test_PrintserverInfo_winreg(tctx
, p
, &t
->server_handle
),
9114 "failed to test printserver info winreg");
9120 static bool test_printer_change_id(struct torture_context
*tctx
,
9123 struct torture_printer_context
*t
=
9124 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
9125 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9127 torture_assert(tctx
,
9128 test_ChangeID(tctx
, p
, &t
->handle
),
9129 "failed to test change id");
9134 static bool test_printer_keys(struct torture_context
*tctx
,
9137 struct torture_printer_context
*t
=
9138 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
9139 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9140 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
9142 torture_assert(tctx
,
9143 test_printer_all_keys(tctx
, b
, &t
->handle
),
9144 "failed to test printer keys");
9149 static bool test_printer_data_consistency(struct torture_context
*tctx
,
9152 struct torture_printer_context
*t
=
9153 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
9154 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9156 torture_assert(tctx
,
9157 test_EnumPrinterData_consistency(tctx
, p
, &t
->handle
),
9158 "failed to test printer data consistency");
9163 static bool test_printer_data_keys(struct torture_context
*tctx
,
9166 struct torture_printer_context
*t
=
9167 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
9168 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9170 torture_assert(tctx
,
9171 test_SetPrinterDataEx_keys(tctx
, p
, &t
->handle
),
9172 "failed to test printer data keys");
9177 static bool test_printer_data_values(struct torture_context
*tctx
,
9180 struct torture_printer_context
*t
=
9181 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
9182 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9184 torture_assert(tctx
,
9185 test_SetPrinterDataEx_values(tctx
, p
, &t
->handle
),
9186 "failed to test printer data values");
9191 static bool test_printer_data_set(struct torture_context
*tctx
,
9194 struct torture_printer_context
*t
=
9195 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
9196 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9198 torture_assert(tctx
,
9199 test_SetPrinterDataEx_matrix(tctx
, p
, &t
->handle
, t
->info2
.printername
, NULL
, NULL
),
9200 "failed to test printer data set");
9205 static bool test_printer_data_winreg(struct torture_context
*tctx
,
9208 struct torture_printer_context
*t
=
9209 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
9210 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9212 torture_assert(tctx
,
9213 test_PrinterData_winreg(tctx
, p
, &t
->handle
, t
->info2
.printername
),
9214 "failed to test printer data winreg");
9219 static bool test_printer_data_dsspooler(struct torture_context
*tctx
,
9222 struct torture_printer_context
*t
=
9223 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
9224 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9226 torture_assert(tctx
,
9227 test_PrinterData_DsSpooler(tctx
, p
, &t
->handle
, t
->info2
.printername
),
9228 "failed to test printer data winreg dsspooler");
9233 static bool test_printer_ic(struct torture_context
*tctx
,
9236 struct torture_printer_context
*t
=
9237 talloc_get_type_abort(private_data
,
9238 struct torture_printer_context
);
9239 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9240 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
9241 struct policy_handle gdi_handle
;
9243 if (torture_setting_bool(tctx
, "samba3", false)) {
9244 torture_skip(tctx
, "skip printer information context tests against samba");
9248 struct spoolss_CreatePrinterIC r
;
9249 struct spoolss_DevmodeContainer devmode_ctr
;
9251 ZERO_STRUCT(devmode_ctr
);
9253 r
.in
.handle
= &t
->handle
;
9254 r
.in
.devmode_ctr
= &devmode_ctr
;
9255 r
.out
.gdi_handle
= &gdi_handle
;
9257 torture_assert_ntstatus_ok(tctx
,
9258 dcerpc_spoolss_CreatePrinterIC_r(b
, tctx
, &r
),
9259 "CreatePrinterIC failed");
9260 torture_assert_werr_ok(tctx
, r
.out
.result
,
9261 "CreatePrinterIC failed");
9265 struct spoolss_PlayGDIScriptOnPrinterIC r
;
9268 uint32_t num_fonts
= 0;
9270 in
= data_blob_string_const("");
9272 r
.in
.gdi_handle
= &gdi_handle
;
9274 r
.in
.cIn
= in
.length
;
9277 for (i
= 0; i
< 4; i
++) {
9279 out
= data_blob_talloc_zero(tctx
, i
);
9281 r
.in
.cOut
= out
.length
;
9282 r
.out
.pOut
= out
.data
;
9284 torture_assert_ntstatus_ok(tctx
,
9285 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b
, tctx
, &r
),
9286 "PlayGDIScriptOnPrinterIC failed");
9287 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_NOT_ENOUGH_MEMORY
,
9288 "PlayGDIScriptOnPrinterIC failed");
9291 out
= data_blob_talloc_zero(tctx
, 4);
9293 r
.in
.cOut
= out
.length
;
9294 r
.out
.pOut
= out
.data
;
9296 torture_assert_ntstatus_ok(tctx
,
9297 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b
, tctx
, &r
),
9298 "PlayGDIScriptOnPrinterIC failed");
9299 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_OK
,
9300 "PlayGDIScriptOnPrinterIC failed");
9302 /* now we should have the required length, so retry with a
9303 * buffer which is large enough to carry all font ids */
9305 num_fonts
= IVAL(r
.out
.pOut
, 0);
9307 torture_comment(tctx
, "PlayGDIScriptOnPrinterIC gave font count of %d\n", num_fonts
);
9309 out
= data_blob_talloc_zero(tctx
,
9310 num_fonts
* sizeof(struct UNIVERSAL_FONT_ID
) + 4);
9312 r
.in
.cOut
= out
.length
;
9313 r
.out
.pOut
= out
.data
;
9315 torture_assert_ntstatus_ok(tctx
,
9316 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b
, tctx
, &r
),
9317 "PlayGDIScriptOnPrinterIC failed");
9318 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_OK
,
9319 "PlayGDIScriptOnPrinterIC failed");
9324 struct spoolss_DeletePrinterIC r
;
9326 r
.in
.gdi_handle
= &gdi_handle
;
9327 r
.out
.gdi_handle
= &gdi_handle
;
9329 torture_assert_ntstatus_ok(tctx
,
9330 dcerpc_spoolss_DeletePrinterIC_r(b
, tctx
, &r
),
9331 "DeletePrinterIC failed");
9332 torture_assert_werr_ok(tctx
, r
.out
.result
,
9333 "DeletePrinterIC failed");
9340 static bool test_printer_bidi(struct torture_context
*tctx
,
9343 struct torture_printer_context
*t
=
9344 talloc_get_type_abort(private_data
,
9345 struct torture_printer_context
);
9346 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9347 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
9348 struct spoolss_SendRecvBidiData r
;
9349 struct RPC_BIDI_REQUEST_CONTAINER bidi_req
;
9350 struct RPC_BIDI_RESPONSE_CONTAINER
*bidi_rep
= NULL
;
9352 if (torture_setting_bool(tctx
, "samba3", false)) {
9353 torture_skip(tctx
, "skip printer bidirectional tests against samba");
9356 ZERO_STRUCT(bidi_req
);
9358 r
.in
.hPrinter
= t
->handle
;
9359 r
.in
.pAction
= "foobar";
9360 r
.in
.pReqData
= &bidi_req
;
9361 r
.out
.ppRespData
= &bidi_rep
;
9363 torture_assert_ntstatus_ok(tctx
,
9364 dcerpc_spoolss_SendRecvBidiData_r(b
, tctx
, &r
),
9365 "SendRecvBidiData failed");
9366 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_NOT_SUPPORTED
,
9367 "SendRecvBidiData failed");
9369 if (!(t
->info2
.attributes
& PRINTER_ATTRIBUTE_ENABLE_BIDI
)) {
9370 torture_skip(tctx
, "skipping further tests as printer is not BIDI enabled");
9373 r
.in
.pAction
= BIDI_ACTION_ENUM_SCHEMA
;
9375 torture_assert_ntstatus_ok(tctx
,
9376 dcerpc_spoolss_SendRecvBidiData_r(b
, tctx
, &r
),
9377 "SendRecvBidiData failed");
9378 torture_assert_werr_ok(tctx
, r
.out
.result
,
9379 "SendRecvBidiData failed");
9384 static bool test_printer_set_publish(struct torture_context
*tctx
,
9385 struct dcerpc_binding_handle
*b
,
9386 struct policy_handle
*handle
)
9388 union spoolss_PrinterInfo info
;
9389 struct spoolss_SetPrinterInfo7 info7
;
9390 struct spoolss_SetPrinterInfoCtr info_ctr
;
9391 struct spoolss_DevmodeContainer devmode_ctr
;
9392 struct sec_desc_buf secdesc_ctr
;
9395 info7
.action
= DSPRINT_PUBLISH
;
9397 ZERO_STRUCT(info_ctr
);
9398 ZERO_STRUCT(devmode_ctr
);
9399 ZERO_STRUCT(secdesc_ctr
);
9401 info_ctr
.info
.info7
= &info7
;
9403 torture_assert(tctx
,
9404 test_SetPrinter(tctx
, b
, handle
, &info_ctr
,
9405 &devmode_ctr
, &secdesc_ctr
, 0), "");
9407 torture_assert(tctx
,
9408 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
9410 torture_assert(tctx
,
9411 (info
.info2
.attributes
& PRINTER_ATTRIBUTE_PUBLISHED
),
9412 "info2 publish flag not set");
9413 torture_assert(tctx
,
9414 test_GetPrinter_level(tctx
, b
, handle
, 7, &info
),
9416 if (info
.info7
.action
& DSPRINT_PENDING
) {
9417 torture_comment(tctx
, "publish is pending\n");
9418 torture_assert_int_equal(tctx
,
9420 (DSPRINT_PENDING
| DSPRINT_PUBLISH
),
9421 "info7 publish flag not set");
9425 torture_assert_int_equal(tctx
,
9428 "info7 publish flag not set");
9430 /* GUID_from_string is able to parse both plain and
9431 * curly-braced guids */
9432 torture_assert_ntstatus_ok(tctx
,
9433 GUID_from_string(info
.info7
.guid
,
9435 "invalid published printer GUID");
9437 /* Build reference GUID string */
9438 ref_guid
= GUID_string2(tctx
, &guid
);
9439 torture_assert_not_null(tctx
, ref_guid
, "ENOMEM");
9440 ref_guid
= talloc_strdup_upper(tctx
, ref_guid
);
9441 torture_assert_not_null(tctx
, ref_guid
, "ENOMEM");
9442 torture_assert_str_equal(tctx
, info
.info7
.guid
, ref_guid
,
9443 "invalid GUID format");
9449 static bool test_printer_set_unpublish(struct torture_context
*tctx
,
9450 struct dcerpc_binding_handle
*b
,
9451 struct policy_handle
*handle
)
9453 union spoolss_PrinterInfo info
;
9454 struct spoolss_SetPrinterInfo7 info7
;
9455 struct spoolss_SetPrinterInfoCtr info_ctr
;
9456 struct spoolss_DevmodeContainer devmode_ctr
;
9457 struct sec_desc_buf secdesc_ctr
;
9459 info7
.action
= DSPRINT_UNPUBLISH
;
9462 ZERO_STRUCT(info_ctr
);
9463 ZERO_STRUCT(devmode_ctr
);
9464 ZERO_STRUCT(secdesc_ctr
);
9466 info_ctr
.info
.info7
= &info7
;
9468 torture_assert(tctx
,
9469 test_SetPrinter(tctx
, b
, handle
, &info_ctr
,
9470 &devmode_ctr
, &secdesc_ctr
, 0), "");
9472 torture_assert(tctx
,
9473 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
9475 torture_assert(tctx
,
9476 !(info
.info2
.attributes
& PRINTER_ATTRIBUTE_PUBLISHED
),
9477 "info2 publish flag still set");
9478 torture_assert(tctx
,
9479 test_GetPrinter_level(tctx
, b
, handle
, 7, &info
),
9482 if (info
.info7
.action
& DSPRINT_PENDING
) {
9484 torture_comment(tctx
, "unpublish is pending\n");
9485 torture_assert_int_equal(tctx
,
9487 (DSPRINT_PENDING
| DSPRINT_UNPUBLISH
),
9488 "info7 unpublish flag not set");
9489 torture_assert_ntstatus_ok(tctx
,
9490 GUID_from_string(info
.info7
.guid
,
9492 "invalid printer GUID");
9494 torture_assert_int_equal(tctx
,
9495 info
.info7
.action
, DSPRINT_UNPUBLISH
,
9496 "info7 unpublish flag not set");
9502 static bool test_printer_publish_toggle(struct torture_context
*tctx
,
9505 struct torture_printer_context
*t
=
9506 talloc_get_type_abort(private_data
,
9507 struct torture_printer_context
);
9508 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9509 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
9510 struct policy_handle
*handle
= &t
->handle
;
9511 union spoolss_PrinterInfo info7
;
9512 union spoolss_PrinterInfo info2
;
9514 /* check publish status via level 7 and level 2 */
9515 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 7, &info7
),
9517 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info2
),
9520 if (info2
.info2
.attributes
& PRINTER_ATTRIBUTE_PUBLISHED
) {
9521 torture_assert_int_equal(tctx
,
9522 info7
.info7
.action
, DSPRINT_PUBLISH
,
9523 "info7 publish flag not set");
9524 torture_assert(tctx
, test_printer_set_unpublish(tctx
, b
, handle
), "");
9525 torture_assert(tctx
, test_printer_set_publish(tctx
, b
, handle
), "");
9527 torture_assert_int_equal(tctx
,
9528 info7
.info7
.action
, DSPRINT_UNPUBLISH
,
9529 "info7 unpublish flag not set");
9530 torture_assert(tctx
, test_printer_set_publish(tctx
, b
, handle
), "");
9531 torture_assert(tctx
, test_printer_set_unpublish(tctx
, b
, handle
), "");
9537 static bool test_driver_info_winreg(struct torture_context
*tctx
,
9540 struct torture_printer_context
*t
=
9541 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
9542 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9543 const char *driver_name
= t
->added_driver
? t
->driver
.info8
.driver_name
: t
->info2
.drivername
;
9545 if (!t
->have_driver
) {
9546 torture_skip(tctx
, "skipping driver info winreg test as we don't have a driver");
9549 torture_assert(tctx
,
9550 test_DriverInfo_winreg(tctx
, p
, &t
->handle
, t
->info2
.printername
, driver_name
, t
->driver
.remote
.environment
, 3),
9551 "failed to test driver info winreg");
9556 static bool test_print_job_enum(struct torture_context
*tctx
,
9559 struct torture_printer_context
*t
=
9560 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
9561 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9562 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
9564 uint32_t num_jobs
= 8;
9567 union spoolss_JobInfo
*info
= NULL
;
9570 torture_assert(tctx
,
9571 test_PausePrinter(tctx
, b
, &t
->handle
),
9572 "failed to pause printer");
9574 /* purge in case of any jobs from previous tests */
9575 torture_assert(tctx
,
9576 test_printer_purge(tctx
, b
, &t
->handle
),
9577 "failed to purge printer");
9579 /* enum before jobs, valid level */
9580 torture_assert(tctx
,
9581 test_EnumJobs_args(tctx
, b
, &t
->handle
, 1, WERR_OK
,
9583 "EnumJobs with valid level");
9584 torture_assert_int_equal(tctx
, count
, 0, "EnumJobs count");
9585 torture_assert(tctx
,
9586 test_EnumJobs_args(tctx
, b
, &t
->handle
, 2, WERR_OK
,
9588 "EnumJobs with valid level");
9589 torture_assert_int_equal(tctx
, count
, 0, "EnumJobs count");
9590 /* enum before jobs, invalid level - expect failure */
9591 torture_assert(tctx
,
9592 test_EnumJobs_args(tctx
, b
, &t
->handle
, 100,
9595 "EnumJobs with invalid level");
9597 job_ids
= talloc_zero_array(tctx
, uint32_t, num_jobs
);
9599 for (i
= 0; i
< num_jobs
; i
++) {
9600 ret
= test_DoPrintTest_add_one_job(tctx
, b
, &t
->handle
,
9603 torture_assert(tctx
, ret
, "failed to add print job");
9606 /* enum after jobs, valid level */
9607 torture_assert(tctx
,
9608 test_EnumJobs_args(tctx
, b
, &t
->handle
, 1, WERR_OK
,
9610 "EnumJobs with valid level");
9611 torture_assert_int_equal(tctx
, count
, num_jobs
, "EnumJobs count");
9612 torture_assert(tctx
,
9613 test_EnumJobs_args(tctx
, b
, &t
->handle
, 2, WERR_OK
,
9615 "EnumJobs with valid level");
9616 torture_assert_int_equal(tctx
, count
, num_jobs
, "EnumJobs count");
9617 /* enum after jobs, invalid level - expect failure */
9618 torture_assert(tctx
,
9619 test_EnumJobs_args(tctx
, b
, &t
->handle
, 100,
9622 "EnumJobs with invalid level");
9624 for (i
= 0; i
< num_jobs
; i
++) {
9625 test_SetJob(tctx
, b
, &t
->handle
, job_ids
[i
], NULL
,
9626 SPOOLSS_JOB_CONTROL_DELETE
);
9629 torture_assert(tctx
,
9630 test_ResumePrinter(tctx
, b
, &t
->handle
),
9631 "failed to resume printer");
9636 static bool test_printer_log_jobinfo(struct torture_context
*tctx
,
9639 struct torture_printer_context
*t
=
9640 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
9641 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9642 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
9643 struct spoolss_BranchOfficeJobDataContainer info
;
9646 struct spoolss_LogJobInfoForBranchOffice r
;
9648 torture_comment(tctx
, "Testing LogJobInfoForBranchOffice\n");
9650 info
.cJobDataEntries
= 0;
9651 info
.JobData
= NULL
;
9653 r
.in
.hPrinter
= &t
->handle
;
9654 r
.in
.pBranchOfficeJobDataContainer
= &info
;
9656 torture_assert_ntstatus_ok(tctx
,
9657 dcerpc_spoolss_LogJobInfoForBranchOffice_r(b
, tctx
, &r
),
9658 "LogJobInfoForBranchOffice failed");
9659 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAMETER
,
9660 "LogJobInfoForBranchOffice failed");
9662 info
.cJobDataEntries
= 1;
9663 info
.JobData
= talloc_zero_array(tctx
, struct spoolss_BranchOfficeJobData
, info
.cJobDataEntries
);
9665 info
.JobData
[0].eEventType
= kLogOfflineFileFull
;
9666 info
.JobData
[0].JobId
= 42;
9667 info
.JobData
[0].JobInfo
.LogOfflineFileFull
.pMachineName
= talloc_strdup(tctx
, "mthelena");
9669 torture_assert_ntstatus_ok(tctx
,
9670 dcerpc_spoolss_LogJobInfoForBranchOffice_r(b
, tctx
, &r
),
9671 "LogJobInfoForBranchOffice failed");
9672 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_OK
,
9673 "LogJobInfoForBranchOffice failed");
9675 info
.cJobDataEntries
= 42;
9676 info
.JobData
= talloc_zero_array(tctx
, struct spoolss_BranchOfficeJobData
, info
.cJobDataEntries
);
9678 for (i
=0; i
< info
.cJobDataEntries
; i
++) {
9679 info
.JobData
[i
].eEventType
= kLogOfflineFileFull
;
9680 info
.JobData
[i
].JobId
= i
;
9681 info
.JobData
[i
].JobInfo
.LogOfflineFileFull
.pMachineName
= talloc_asprintf(tctx
, "torture_%d", i
);
9684 torture_assert_ntstatus_ok(tctx
,
9685 dcerpc_spoolss_LogJobInfoForBranchOffice_r(b
, tctx
, &r
),
9686 "LogJobInfoForBranchOffice failed");
9687 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_OK
,
9688 "LogJobInfoForBranchOffice failed");
9693 static bool test_printer_os_versions(struct torture_context
*tctx
,
9696 struct torture_printer_context
*t
=
9697 (struct torture_printer_context
*)talloc_get_type_abort(private_data
, struct torture_printer_context
);
9698 struct dcerpc_pipe
*p
= t
->spoolss_pipe
;
9699 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
9700 union spoolss_PrinterInfo info
;
9704 struct spoolss_OSVersion osversion
;
9705 uint8_t os_major
, os_minor
;
9707 struct policy_handle server_handle
;
9709 torture_comment(tctx
, "Testing OSVersion vs. PRINTER_INFO_STRESS\n");
9711 torture_assert(tctx
,
9712 test_GetPrinter_level(tctx
, b
, &t
->handle
, 0, &info
),
9713 "failed to get level 0 printer info");
9715 torture_assert(tctx
,
9716 test_OpenPrinter_server(tctx
, p
, &server_handle
),
9717 "failed to open printserver");
9719 torture_assert(tctx
,
9720 test_GetPrinterData_checktype(tctx
, b
, &server_handle
, "OSVersion",
9721 NULL
, NULL
, &data
, &length
),
9722 "failed to fetch OSVersion printer data");
9724 test_ClosePrinter(tctx
, b
, &server_handle
);
9726 blob
= data_blob_const(data
, length
);
9728 torture_assert_ndr_success(tctx
,
9729 ndr_pull_struct_blob(&blob
, tctx
, &osversion
,
9730 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_OSVersion
),
9731 "failed to pull OSVersion");
9733 os_major
= CVAL(&info
.info0
.version
, 0);
9734 os_minor
= CVAL(&info
.info0
.version
, 1);
9735 os_build
= SVAL(&info
.info0
.version
, 2);
9737 torture_assert_int_equal(tctx
, os_major
, osversion
.major
, "major");
9738 torture_assert_int_equal(tctx
, os_minor
, osversion
.minor
, "minor");
9739 torture_assert_int_equal(tctx
, os_build
, osversion
.build
, "build");
9745 void torture_tcase_printer(struct torture_tcase
*tcase
)
9747 torture_tcase_add_simple_test(tcase
, "openprinter", test_openprinter_wrap
);
9748 torture_tcase_add_simple_test(tcase
, "csetprinter", test_csetprinter
);
9749 torture_tcase_add_simple_test(tcase
, "print_test", test_print_test
);
9750 torture_tcase_add_simple_test(tcase
, "print_test_extended", test_print_test_extended
);
9751 torture_tcase_add_simple_test(tcase
, "print_test_smbd", test_print_test_smbd
);
9752 torture_tcase_add_simple_test(tcase
, "print_test_properties", test_print_test_properties
);
9753 torture_tcase_add_simple_test(tcase
, "print_test_purge", test_print_test_purge
);
9754 torture_tcase_add_simple_test(tcase
, "printer_info", test_printer_info
);
9755 torture_tcase_add_simple_test(tcase
, "sd", test_printer_sd
);
9756 torture_tcase_add_simple_test(tcase
, "dm", test_printer_dm
);
9757 torture_tcase_add_simple_test(tcase
, "printer_info_winreg", test_printer_info_winreg
);
9758 torture_tcase_add_simple_test(tcase
, "change_id", test_printer_change_id
);
9759 torture_tcase_add_simple_test(tcase
, "keys", test_printer_keys
);
9760 torture_tcase_add_simple_test(tcase
, "printerdata_consistency", test_printer_data_consistency
);
9761 torture_tcase_add_simple_test(tcase
, "printerdata_keys", test_printer_data_keys
);
9762 torture_tcase_add_simple_test(tcase
, "printerdata_values", test_printer_data_values
);
9763 torture_tcase_add_simple_test(tcase
, "printerdata_set", test_printer_data_set
);
9764 torture_tcase_add_simple_test(tcase
, "printerdata_winreg", test_printer_data_winreg
);
9765 torture_tcase_add_simple_test(tcase
, "printerdata_dsspooler", test_printer_data_dsspooler
);
9766 torture_tcase_add_simple_test(tcase
, "driver_info_winreg", test_driver_info_winreg
);
9767 torture_tcase_add_simple_test(tcase
, "printer_rename", test_printer_rename
);
9768 torture_tcase_add_simple_test(tcase
, "printer_ic", test_printer_ic
);
9769 torture_tcase_add_simple_test(tcase
, "bidi", test_printer_bidi
);
9770 torture_tcase_add_simple_test(tcase
, "publish_toggle",
9771 test_printer_publish_toggle
);
9772 torture_tcase_add_simple_test(tcase
, "print_job_enum", test_print_job_enum
);
9773 torture_tcase_add_simple_test(tcase
, "log_jobinfo", test_printer_log_jobinfo
);
9774 torture_tcase_add_simple_test(tcase
, "os_versions", test_printer_os_versions
);
9777 struct torture_suite
*torture_rpc_spoolss_printer(TALLOC_CTX
*mem_ctx
)
9779 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "printer");
9780 struct torture_tcase
*tcase
;
9782 tcase
= torture_suite_add_tcase(suite
, "addprinter");
9784 torture_tcase_set_fixture(tcase
,
9785 torture_rpc_spoolss_printer_setup
,
9786 torture_rpc_spoolss_printer_teardown
);
9788 torture_tcase_printer(tcase
);
9790 tcase
= torture_suite_add_tcase(suite
, "addprinterex");
9792 torture_tcase_set_fixture(tcase
,
9793 torture_rpc_spoolss_printerex_setup
,
9794 torture_rpc_spoolss_printer_teardown
);
9796 torture_tcase_printer(tcase
);
9798 tcase
= torture_suite_add_tcase(suite
, "addprinterwkn");
9800 torture_tcase_set_fixture(tcase
,
9801 torture_rpc_spoolss_printerwkn_setup
,
9802 torture_rpc_spoolss_printer_teardown
);
9804 tcase
= torture_suite_add_tcase(suite
, "addprinterexwkn");
9806 torture_tcase_set_fixture(tcase
,
9807 torture_rpc_spoolss_printerexwkn_setup
,
9808 torture_rpc_spoolss_printer_teardown
);
9811 /* test is not correct */
9812 tcase
= torture_suite_add_tcase(suite
, "addprinterdm");
9814 torture_tcase_set_fixture(tcase
,
9815 torture_rpc_spoolss_printerdm_setup
,
9816 torture_rpc_spoolss_printer_teardown
);
9818 torture_tcase_printer(tcase
);
9823 struct torture_suite
*torture_rpc_spoolss(TALLOC_CTX
*mem_ctx
)
9825 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "spoolss");
9826 struct torture_tcase
*tcase
= torture_suite_add_tcase(suite
, "printserver");
9828 torture_tcase_set_fixture(tcase
,
9829 torture_rpc_spoolss_setup
,
9830 torture_rpc_spoolss_teardown
);
9832 torture_tcase_add_simple_test(tcase
, "openprinter_badnamelist", test_OpenPrinter_badname_list
);
9833 torture_tcase_add_simple_test(tcase
, "printer_data_list", test_GetPrinterData_list
);
9834 torture_tcase_add_simple_test(tcase
, "enum_forms", test_PrintServer_EnumForms
);
9835 torture_tcase_add_simple_test(tcase
, "forms", test_PrintServer_Forms
);
9836 torture_tcase_add_simple_test(tcase
, "forms_winreg", test_PrintServer_Forms_Winreg
);
9837 torture_tcase_add_simple_test(tcase
, "enum_ports", test_EnumPorts
);
9838 torture_tcase_add_simple_test(tcase
, "add_port", test_AddPort
);
9839 torture_tcase_add_simple_test(tcase
, "get_printer_driver_directory", test_GetPrinterDriverDirectory
);
9840 torture_tcase_add_simple_test(tcase
, "get_print_processor_directory", test_GetPrintProcessorDirectory
);
9841 torture_tcase_add_simple_test(tcase
, "enum_printer_drivers", test_EnumPrinterDrivers
);
9842 torture_tcase_add_simple_test(tcase
, "enum_monitors", test_EnumMonitors
);
9843 torture_tcase_add_simple_test(tcase
, "enum_print_processors", test_EnumPrintProcessors
);
9844 torture_tcase_add_simple_test(tcase
, "print_processors_winreg", test_print_processors_winreg
);
9845 torture_tcase_add_simple_test(tcase
, "add_processor", test_add_print_processor
);
9846 torture_tcase_add_simple_test(tcase
, "enum_printprocdata", test_EnumPrintProcessorDataTypes
);
9847 torture_tcase_add_simple_test(tcase
, "enum_printers", test_EnumPrinters
);
9848 torture_tcase_add_simple_test(tcase
, "enum_ports_old", test_EnumPorts_old
);
9849 torture_tcase_add_simple_test(tcase
, "enum_printers_old", test_EnumPrinters_old
);
9850 torture_tcase_add_simple_test(tcase
, "enum_printers_servername", test_EnumPrinters_servername
);
9851 torture_tcase_add_simple_test(tcase
, "enum_printer_drivers_old", test_EnumPrinterDrivers_old
);
9852 torture_tcase_add_simple_test(tcase
, "architecture_buffer", test_architecture_buffer
);
9853 torture_tcase_add_simple_test(tcase
, "get_core_printer_drivers", test_get_core_printer_drivers
);
9854 torture_tcase_add_simple_test(tcase
, "get_printer_driver_package_path", test_get_printer_driver_package_path
);
9855 torture_tcase_add_simple_test(tcase
, "get_printer", test_get_printer_printserverhandle
);
9856 torture_tcase_add_simple_test(tcase
, "set_printer", test_set_printer_printserverhandle
);
9857 torture_tcase_add_simple_test(tcase
, "printserver_info_winreg", test_printserver_info_winreg
);
9858 torture_tcase_add_simple_test(tcase
, "addpermachineconnection", test_addpermachineconnection
);
9860 torture_suite_add_suite(suite
, torture_rpc_spoolss_printer(suite
));
9865 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context
*tctx
,
9866 struct dcerpc_binding_handle
*b
,
9868 const char *environment
,
9871 struct spoolss_GetPrinterDriverDirectory r
;
9874 r
.in
.server
= server
;
9875 r
.in
.environment
= environment
;
9879 r
.out
.needed
= &needed
;
9881 torture_assert_ntstatus_ok(tctx
,
9882 dcerpc_spoolss_GetPrinterDriverDirectory_r(b
, tctx
, &r
),
9883 "failed to query driver directory");
9885 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
9886 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, needed
);
9887 r
.in
.buffer
= &blob
;
9888 r
.in
.offered
= needed
;
9890 torture_assert_ntstatus_ok(tctx
,
9891 dcerpc_spoolss_GetPrinterDriverDirectory_r(b
, tctx
, &r
),
9892 "failed to query driver directory");
9895 torture_assert_werr_ok(tctx
, r
.out
.result
,
9896 "failed to query driver directory");
9899 *dir_p
= r
.out
.info
->info1
.directory_name
;
9905 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr
*info_ctr
)
9907 if (info_ctr
== NULL
) {
9911 switch (info_ctr
->level
) {
9913 return info_ctr
->info
.info1
->driver_name
;
9915 return info_ctr
->info
.info2
->driver_name
;
9917 return info_ctr
->info
.info3
->driver_name
;
9919 return info_ctr
->info
.info4
->driver_name
;
9921 return info_ctr
->info
.info6
->driver_name
;
9923 return info_ctr
->info
.info8
->driver_name
;
9929 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr
*info_ctr
)
9931 if (info_ctr
== NULL
) {
9935 switch (info_ctr
->level
) {
9937 return info_ctr
->info
.info2
->architecture
;
9939 return info_ctr
->info
.info3
->architecture
;
9941 return info_ctr
->info
.info4
->architecture
;
9943 return info_ctr
->info
.info6
->architecture
;
9945 return info_ctr
->info
.info8
->architecture
;
9952 static bool test_AddPrinterDriver_exp(struct torture_context
*tctx
,
9953 struct dcerpc_binding_handle
*b
,
9954 const char *servername
,
9955 struct spoolss_AddDriverInfoCtr
*info_ctr
,
9956 WERROR expected_result
)
9958 struct spoolss_AddPrinterDriver r
;
9959 const char *drivername
= get_driver_from_info(info_ctr
);
9960 const char *environment
= get_environment_from_info(info_ctr
);
9962 r
.in
.servername
= servername
;
9963 r
.in
.info_ctr
= info_ctr
;
9965 torture_comment(tctx
, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
9966 drivername
, info_ctr
->level
, environment
);
9968 torture_assert_ntstatus_ok(tctx
,
9969 dcerpc_spoolss_AddPrinterDriver_r(b
, tctx
, &r
),
9970 "spoolss_AddPrinterDriver failed");
9971 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
9972 "spoolss_AddPrinterDriver failed with unexpected result");
9978 static bool test_AddPrinterDriverEx_exp(struct torture_context
*tctx
,
9979 struct dcerpc_binding_handle
*b
,
9980 const char *servername
,
9981 struct spoolss_AddDriverInfoCtr
*info_ctr
,
9983 WERROR expected_result
)
9985 struct spoolss_AddPrinterDriverEx r
;
9986 const char *drivername
= get_driver_from_info(info_ctr
);
9987 const char *environment
= get_environment_from_info(info_ctr
);
9989 r
.in
.servername
= servername
;
9990 r
.in
.info_ctr
= info_ctr
;
9993 torture_comment(tctx
, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
9994 drivername
, info_ctr
->level
, environment
);
9996 torture_assert_ntstatus_ok(tctx
,
9997 dcerpc_spoolss_AddPrinterDriverEx_r(b
, tctx
, &r
),
9998 "AddPrinterDriverEx failed");
9999 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
10000 "AddPrinterDriverEx failed with unexpected result");
10005 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
10006 if (path && strlen(path)) {\
10007 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
10010 static bool test_AddPrinterDriver_args_level_1(struct torture_context
*tctx
,
10011 struct dcerpc_binding_handle
*b
,
10012 const char *server_name
,
10013 struct spoolss_AddDriverInfo8
*r
,
10016 const char *remote_driver_dir
)
10018 struct spoolss_AddDriverInfoCtr info_ctr
;
10019 struct spoolss_AddDriverInfo1 info1
;
10021 ZERO_STRUCT(info1
);
10023 info_ctr
.level
= 1;
10024 info_ctr
.info
.info1
= &info1
;
10027 torture_assert(tctx
,
10028 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_LEVEL
),
10029 "failed to test AddPrinterDriverEx level 1");
10031 torture_assert(tctx
,
10032 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_LEVEL
),
10033 "failed to test AddPrinterDriver level 1");
10036 info1
.driver_name
= r
->driver_name
;
10039 torture_assert(tctx
,
10040 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_LEVEL
),
10041 "failed to test AddPrinterDriverEx level 1");
10043 torture_assert(tctx
,
10044 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_LEVEL
),
10045 "failed to test AddPrinterDriver level 1");
10051 static bool test_AddPrinterDriver_args_level_2(struct torture_context
*tctx
,
10052 struct dcerpc_binding_handle
*b
,
10053 const char *server_name
,
10054 struct spoolss_AddDriverInfo8
*r
,
10057 const char *remote_driver_dir
)
10059 struct spoolss_AddDriverInfoCtr info_ctr
;
10060 struct spoolss_AddDriverInfo2 info2
;
10061 union spoolss_DriverInfo info
;
10063 ZERO_STRUCT(info2
);
10065 info_ctr
.level
= 2;
10066 info_ctr
.info
.info2
= &info2
;
10069 torture_assert(tctx
,
10070 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAMETER
),
10071 "failed to test AddPrinterDriverEx level 2");
10073 torture_assert(tctx
,
10074 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAMETER
),
10075 "failed to test AddPrinterDriver level 2");
10078 info2
.driver_name
= r
->driver_name
;
10081 torture_assert(tctx
,
10082 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAMETER
),
10083 "failed to test AddPrinterDriverEx level 2");
10085 torture_assert(tctx
,
10086 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAMETER
),
10087 "failed to test AddPrinterDriver level 2");
10090 info2
.version
= r
->version
;
10093 torture_assert(tctx
,
10094 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAMETER
),
10095 "failed to test AddPrinterDriverEx level 2");
10097 torture_assert(tctx
,
10098 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAMETER
),
10099 "failed to test AddPrinterDriver level 2");
10102 info2
.architecture
= r
->architecture
;
10105 torture_assert(tctx
,
10106 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAMETER
),
10107 "failed to test AddPrinterDriverEx level 2");
10109 torture_assert(tctx
,
10110 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAMETER
),
10111 "failed to test AddPrinterDriver level 2");
10114 info2
.driver_path
= r
->driver_path
;
10117 torture_assert(tctx
,
10118 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAMETER
),
10119 "failed to test AddPrinterDriverEx level 2");
10121 torture_assert(tctx
,
10122 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAMETER
),
10123 "failed to test AddPrinterDriver level 2");
10126 info2
.data_file
= r
->data_file
;
10129 torture_assert(tctx
,
10130 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_INVALID_PARAMETER
),
10131 "failed to test AddPrinterDriverEx level 2");
10133 torture_assert(tctx
,
10134 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_PARAMETER
),
10135 "failed to test AddPrinterDriver level 2");
10138 info2
.config_file
= r
->config_file
;
10141 torture_assert(tctx
,
10142 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, 0, WERR_INVALID_PARAMETER
),
10143 "failed to test AddPrinterDriverEx");
10147 torture_assert(tctx
,
10148 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_OK
),
10149 "failed to test AddPrinterDriverEx level 2");
10151 torture_assert(tctx
,
10152 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_OK
),
10153 "failed to test AddPrinterDriver level 2");
10156 torture_assert(tctx
,
10157 test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, r
->architecture
, 2, r
->driver_name
, &info
),
10158 "failed to find added printer driver");
10160 if (remote_driver_dir
) {
10161 ASSERT_DRIVER_PATH(tctx
, info
.info2
.driver_path
, remote_driver_dir
, "unexpected path");
10162 ASSERT_DRIVER_PATH(tctx
, info
.info2
.data_file
, remote_driver_dir
, "unexpected path");
10163 ASSERT_DRIVER_PATH(tctx
, info
.info2
.config_file
, remote_driver_dir
, "unexpected path");
10169 static bool test_AddPrinterDriver_args_level_3(struct torture_context
*tctx
,
10170 struct dcerpc_binding_handle
*b
,
10171 const char *server_name
,
10172 struct spoolss_AddDriverInfo8
*r
,
10175 const char *remote_driver_dir
)
10177 struct spoolss_AddDriverInfoCtr info_ctr
;
10178 struct spoolss_AddDriverInfo3 info3
;
10179 union spoolss_DriverInfo info
;
10181 info3
.driver_name
= r
->driver_name
;
10182 info3
.version
= r
->version
;
10183 info3
.architecture
= r
->architecture
;
10184 info3
.driver_path
= r
->driver_path
;
10185 info3
.data_file
= r
->data_file
;
10186 info3
.config_file
= r
->config_file
;
10187 info3
.help_file
= r
->help_file
;
10188 info3
.monitor_name
= r
->monitor_name
;
10189 info3
.default_datatype
= r
->default_datatype
;
10190 info3
._ndr_size_dependent_files
= r
->_ndr_size_dependent_files
;
10191 info3
.dependent_files
= r
->dependent_files
;
10193 info_ctr
.level
= 3;
10194 info_ctr
.info
.info3
= &info3
;
10197 torture_assert(tctx
,
10198 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_OK
),
10199 "failed to test AddPrinterDriverEx level 3");
10201 torture_assert(tctx
,
10202 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_OK
),
10203 "failed to test AddPrinterDriver level 3");
10206 torture_assert(tctx
,
10207 test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, r
->architecture
, 3, r
->driver_name
, &info
),
10208 "failed to find added printer driver");
10210 if (remote_driver_dir
) {
10212 ASSERT_DRIVER_PATH(tctx
, info
.info3
.driver_path
, remote_driver_dir
, "unexpected path");
10213 ASSERT_DRIVER_PATH(tctx
, info
.info3
.data_file
, remote_driver_dir
, "unexpected path");
10214 ASSERT_DRIVER_PATH(tctx
, info
.info3
.config_file
, remote_driver_dir
, "unexpected path");
10215 ASSERT_DRIVER_PATH(tctx
, info
.info3
.help_file
, remote_driver_dir
, "unexpected path");
10216 for (i
=0; info
.info3
.dependent_files
&& info
.info3
.dependent_files
[i
] != NULL
; i
++) {
10217 ASSERT_DRIVER_PATH(tctx
, info
.info3
.dependent_files
[i
], remote_driver_dir
, "unexpected path");
10224 static bool test_AddPrinterDriver_args_level_4(struct torture_context
*tctx
,
10225 struct dcerpc_binding_handle
*b
,
10226 const char *server_name
,
10227 struct spoolss_AddDriverInfo8
*r
,
10230 const char *remote_driver_dir
)
10232 struct spoolss_AddDriverInfoCtr info_ctr
;
10233 struct spoolss_AddDriverInfo4 info4
;
10234 union spoolss_DriverInfo info
;
10236 info4
.version
= r
->version
;
10237 info4
.driver_name
= r
->driver_name
;
10238 info4
.architecture
= r
->architecture
;
10239 info4
.driver_path
= r
->driver_path
;
10240 info4
.data_file
= r
->data_file
;
10241 info4
.config_file
= r
->config_file
;
10242 info4
.help_file
= r
->help_file
;
10243 info4
.monitor_name
= r
->monitor_name
;
10244 info4
.default_datatype
= r
->default_datatype
;
10245 info4
._ndr_size_dependent_files
= r
->_ndr_size_dependent_files
;
10246 info4
.dependent_files
= r
->dependent_files
;
10247 info4
._ndr_size_previous_names
= r
->_ndr_size_previous_names
;
10248 info4
.previous_names
= r
->previous_names
;
10250 info_ctr
.level
= 4;
10251 info_ctr
.info
.info4
= &info4
;
10254 torture_assert(tctx
,
10255 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_OK
),
10256 "failed to test AddPrinterDriverEx level 4");
10258 torture_assert(tctx
,
10259 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_OK
),
10260 "failed to test AddPrinterDriver level 4");
10263 torture_assert(tctx
,
10264 test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, r
->architecture
, 4, r
->driver_name
, &info
),
10265 "failed to find added printer driver");
10267 if (remote_driver_dir
) {
10269 ASSERT_DRIVER_PATH(tctx
, info
.info4
.driver_path
, remote_driver_dir
, "unexpected path");
10270 ASSERT_DRIVER_PATH(tctx
, info
.info4
.data_file
, remote_driver_dir
, "unexpected path");
10271 ASSERT_DRIVER_PATH(tctx
, info
.info4
.config_file
, remote_driver_dir
, "unexpected path");
10272 ASSERT_DRIVER_PATH(tctx
, info
.info4
.help_file
, remote_driver_dir
, "unexpected path");
10273 for (i
=0; info
.info4
.dependent_files
&& info
.info4
.dependent_files
[i
] != NULL
; i
++) {
10274 ASSERT_DRIVER_PATH(tctx
, info
.info4
.dependent_files
[i
], remote_driver_dir
, "unexpected path");
10281 static bool test_AddPrinterDriver_args_level_6(struct torture_context
*tctx
,
10282 struct dcerpc_binding_handle
*b
,
10283 const char *server_name
,
10284 struct spoolss_AddDriverInfo8
*r
,
10287 const char *remote_driver_dir
)
10289 struct spoolss_AddDriverInfoCtr info_ctr
;
10290 struct spoolss_AddDriverInfo6 info6
;
10291 union spoolss_DriverInfo info
;
10293 info6
.version
= r
->version
;
10294 info6
.driver_name
= r
->driver_name
;
10295 info6
.architecture
= r
->architecture
;
10296 info6
.driver_path
= r
->driver_path
;
10297 info6
.data_file
= r
->data_file
;
10298 info6
.config_file
= r
->config_file
;
10299 info6
.help_file
= r
->help_file
;
10300 info6
.monitor_name
= r
->monitor_name
;
10301 info6
.default_datatype
= r
->default_datatype
;
10302 info6
._ndr_size_dependent_files
= r
->_ndr_size_dependent_files
;
10303 info6
.dependent_files
= r
->dependent_files
;
10304 info6
._ndr_size_previous_names
= r
->_ndr_size_previous_names
;
10305 info6
.previous_names
= r
->previous_names
;
10306 info6
.driver_date
= r
->driver_date
;
10307 info6
.driver_version
= r
->driver_version
;
10308 info6
.manufacturer_name
= r
->manufacturer_name
;
10309 info6
.manufacturer_url
= r
->manufacturer_url
;
10310 info6
.hardware_id
= r
->hardware_id
;
10311 info6
.provider
= r
->provider
;
10313 info_ctr
.level
= 6;
10314 info_ctr
.info
.info6
= &info6
;
10317 torture_assert(tctx
,
10318 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_OK
),
10319 "failed to test AddPrinterDriverEx level 6");
10321 torture_assert(tctx
,
10322 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_LEVEL
),
10323 "failed to test AddPrinterDriver level 6");
10326 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
10332 torture_assert(tctx
,
10333 test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, r
->architecture
, 6, r
->driver_name
, &info
),
10334 "failed to find added printer driver");
10336 if (remote_driver_dir
) {
10338 ASSERT_DRIVER_PATH(tctx
, info
.info6
.driver_path
, remote_driver_dir
, "unexpected path");
10339 ASSERT_DRIVER_PATH(tctx
, info
.info6
.data_file
, remote_driver_dir
, "unexpected path");
10340 ASSERT_DRIVER_PATH(tctx
, info
.info6
.config_file
, remote_driver_dir
, "unexpected path");
10341 ASSERT_DRIVER_PATH(tctx
, info
.info6
.help_file
, remote_driver_dir
, "unexpected path");
10342 for (i
=0; info
.info6
.dependent_files
&& info
.info6
.dependent_files
[i
] != NULL
; i
++) {
10343 ASSERT_DRIVER_PATH(tctx
, info
.info6
.dependent_files
[i
], remote_driver_dir
, "unexpected path");
10347 torture_assert_nttime_equal(tctx
, info
.info6
.driver_date
, info6
.driver_date
, "driverdate mismatch");
10348 torture_assert_u64_equal(tctx
, info
.info6
.driver_version
, info6
.driver_version
, "driverversion mismatch");
10353 static bool test_AddPrinterDriver_args_level_8(struct torture_context
*tctx
,
10354 struct dcerpc_binding_handle
*b
,
10355 const char *server_name
,
10356 struct spoolss_AddDriverInfo8
*r
,
10359 const char *remote_driver_dir
)
10361 struct spoolss_AddDriverInfoCtr info_ctr
;
10362 union spoolss_DriverInfo info
;
10364 info_ctr
.level
= 8;
10365 info_ctr
.info
.info8
= r
;
10368 torture_assert(tctx
,
10369 test_AddPrinterDriverEx_exp(tctx
, b
, server_name
, &info_ctr
, flags
, WERR_OK
),
10370 "failed to test AddPrinterDriverEx level 8");
10372 torture_assert(tctx
,
10373 test_AddPrinterDriver_exp(tctx
, b
, server_name
, &info_ctr
, WERR_INVALID_LEVEL
),
10374 "failed to test AddPrinterDriver level 8");
10377 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
10383 torture_assert(tctx
,
10384 test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, r
->architecture
, 8, r
->driver_name
, &info
),
10385 "failed to find added printer driver");
10387 if (remote_driver_dir
) {
10389 ASSERT_DRIVER_PATH(tctx
, info
.info8
.driver_path
, remote_driver_dir
, "unexpected path");
10390 ASSERT_DRIVER_PATH(tctx
, info
.info8
.data_file
, remote_driver_dir
, "unexpected path");
10391 ASSERT_DRIVER_PATH(tctx
, info
.info8
.config_file
, remote_driver_dir
, "unexpected path");
10392 ASSERT_DRIVER_PATH(tctx
, info
.info8
.help_file
, remote_driver_dir
, "unexpected path");
10393 for (i
=0; info
.info8
.dependent_files
&& info
.info8
.dependent_files
[i
] != NULL
; i
++) {
10394 ASSERT_DRIVER_PATH(tctx
, info
.info8
.dependent_files
[i
], remote_driver_dir
, "unexpected path");
10398 torture_assert_nttime_equal(tctx
, info
.info8
.driver_date
, r
->driver_date
, "driverdate mismatch");
10399 torture_assert_u64_equal(tctx
, info
.info8
.driver_version
, r
->driver_version
, "driverversion mismatch");
10404 #undef ASSERT_DRIVER_PATH
10406 static bool test_DeletePrinterDriver_exp(struct torture_context
*tctx
,
10407 struct dcerpc_binding_handle
*b
,
10408 const char *server
,
10409 const char *driver
,
10410 const char *environment
,
10411 WERROR expected_result
)
10413 struct spoolss_DeletePrinterDriver r
;
10415 r
.in
.server
= server
;
10416 r
.in
.architecture
= environment
;
10417 r
.in
.driver
= driver
;
10419 torture_comment(tctx
, "Testing DeletePrinterDriver(%s)\n", driver
);
10421 torture_assert_ntstatus_ok(tctx
,
10422 dcerpc_spoolss_DeletePrinterDriver_r(b
, tctx
, &r
),
10423 "DeletePrinterDriver failed");
10424 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
10425 "DeletePrinterDriver failed with unexpected result");
10430 static bool test_DeletePrinterDriverEx_exp(struct torture_context
*tctx
,
10431 struct dcerpc_binding_handle
*b
,
10432 const char *server
,
10433 const char *driver
,
10434 const char *environment
,
10435 uint32_t delete_flags
,
10437 WERROR expected_result
)
10439 struct spoolss_DeletePrinterDriverEx r
;
10441 r
.in
.server
= server
;
10442 r
.in
.architecture
= environment
;
10443 r
.in
.driver
= driver
;
10444 r
.in
.delete_flags
= delete_flags
;
10445 r
.in
.version
= version
;
10447 torture_comment(tctx
, "Testing DeletePrinterDriverEx(%s)\n", driver
);
10449 torture_assert_ntstatus_ok(tctx
,
10450 dcerpc_spoolss_DeletePrinterDriverEx_r(b
, tctx
, &r
),
10451 "DeletePrinterDriverEx failed");
10452 torture_assert_werr_equal(tctx
, r
.out
.result
, expected_result
,
10453 "DeletePrinterDriverEx failed with unexpected result");
10458 static bool test_DeletePrinterDriver(struct torture_context
*tctx
,
10459 struct dcerpc_binding_handle
*b
,
10460 const char *server_name
,
10461 const char *driver
,
10462 const char *environment
)
10464 torture_assert(tctx
,
10465 test_DeletePrinterDriver_exp(tctx
, b
, server_name
, driver
, "FOOBAR", WERR_INVALID_ENVIRONMENT
),
10466 "failed to delete driver");
10468 torture_assert(tctx
,
10469 test_DeletePrinterDriver_exp(tctx
, b
, server_name
, driver
, environment
, WERR_OK
),
10470 "failed to delete driver");
10472 if (test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, environment
, 1, driver
, NULL
)) {
10473 torture_fail(tctx
, "deleted driver still enumerated");
10476 torture_assert(tctx
,
10477 test_DeletePrinterDriver_exp(tctx
, b
, server_name
, driver
, environment
, WERR_UNKNOWN_PRINTER_DRIVER
),
10478 "2nd delete failed");
10483 static bool test_DeletePrinterDriverEx(struct torture_context
*tctx
,
10484 struct dcerpc_binding_handle
*b
,
10485 const char *server_name
,
10486 const char *driver
,
10487 const char *environment
,
10488 uint32_t delete_flags
,
10491 torture_assert(tctx
,
10492 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name
, driver
, "FOOBAR", delete_flags
, version
, WERR_INVALID_ENVIRONMENT
),
10493 "failed to delete driver");
10495 torture_assert(tctx
,
10496 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name
, driver
, environment
, delete_flags
, version
, WERR_OK
),
10497 "failed to delete driver");
10499 if (test_EnumPrinterDrivers_findone(tctx
, b
, server_name
, environment
, 1, driver
, NULL
)) {
10500 torture_fail(tctx
, "deleted driver still enumerated");
10503 torture_assert(tctx
,
10504 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name
, driver
, environment
, delete_flags
, version
, WERR_UNKNOWN_PRINTER_DRIVER
),
10505 "2nd delete failed");
10510 static bool test_PrinterDriver_args(struct torture_context
*tctx
,
10511 struct dcerpc_binding_handle
*b
,
10512 const char *server_name
,
10514 struct spoolss_AddDriverInfo8
*r
,
10515 uint32_t add_flags
,
10516 uint32_t delete_flags
,
10517 uint32_t delete_version
,
10519 const char *remote_driver_dir
)
10525 ret
= test_AddPrinterDriver_args_level_1(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
10528 ret
= test_AddPrinterDriver_args_level_2(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
10531 ret
= test_AddPrinterDriver_args_level_3(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
10534 ret
= test_AddPrinterDriver_args_level_4(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
10537 ret
= test_AddPrinterDriver_args_level_6(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
10540 ret
= test_AddPrinterDriver_args_level_8(tctx
, b
, server_name
, r
, add_flags
, ex
, remote_driver_dir
);
10546 if (ret
== false) {
10554 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
10556 if (!ex
&& (level
== 6 || level
== 8)) {
10561 struct dcerpc_pipe
*p2
;
10562 struct policy_handle hive_handle
;
10563 struct dcerpc_binding_handle
*b2
;
10565 torture_assert_ntstatus_ok(tctx
,
10566 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
10567 "could not open winreg pipe");
10568 b2
= p2
->binding_handle
;
10570 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
10572 ret
= test_GetDriverInfo_winreg(tctx
, b
, NULL
, NULL
, r
->driver_name
, r
->architecture
, r
->version
, b2
, &hive_handle
, server_name
);
10574 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
10580 return test_DeletePrinterDriverEx(tctx
, b
, server_name
, r
->driver_name
, r
->architecture
, delete_flags
, r
->version
);
10582 return test_DeletePrinterDriver(tctx
, b
, server_name
, r
->driver_name
, r
->architecture
);
10586 static bool fillup_printserver_info(struct torture_context
*tctx
,
10587 struct dcerpc_pipe
*p
,
10588 struct torture_driver_context
*d
)
10590 struct policy_handle server_handle
;
10591 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
10592 const char *server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
10594 torture_assert(tctx
,
10595 test_OpenPrinter_server(tctx
, p
, &server_handle
),
10596 "failed to open printserver");
10597 torture_assert(tctx
,
10598 test_get_environment(tctx
, b
, &server_handle
, &d
->remote
.environment
),
10599 "failed to get environment");
10600 torture_assert(tctx
,
10601 test_ClosePrinter(tctx
, b
, &server_handle
),
10602 "failed to close printserver");
10604 torture_assert(tctx
,
10605 test_GetPrinterDriverDirectory_getdir(tctx
, b
, server_name_slash
,
10606 d
->local
.environment
? d
->local
.environment
: d
->remote
.environment
,
10607 &d
->remote
.driver_directory
),
10608 "failed to get driver directory");
10613 static const char *driver_directory_dir(const char *driver_directory
)
10617 p
= strrchr(driver_directory
, '\\');
10625 static const char *driver_directory_share(struct torture_context
*tctx
,
10626 const char *driver_directory
)
10631 if (driver_directory
[0] == '\\' && driver_directory
[1] == '\\') {
10632 driver_directory
+= 2;
10635 p
= talloc_strdup(tctx
, driver_directory
);
10637 torture_assert(tctx
,
10638 next_token_talloc(tctx
, &p
, &tok
, "\\"),
10639 "cannot explode uri");
10640 torture_assert(tctx
,
10641 next_token_talloc(tctx
, &p
, &tok
, "\\"),
10642 "cannot explode uri");
10647 #define CREATE_PRINTER_DRIVER_PATH(_d, _file) \
10648 talloc_asprintf((_d), "%s\\%s\\%s", (_d)->remote.driver_directory, (_d)->remote.driver_upload_directory, (_file))
10651 static bool create_printer_driver_directory(struct torture_context
*tctx
,
10652 struct smbcli_state
*cli
,
10653 struct torture_driver_context
*d
)
10657 if (d
->remote
.driver_upload_directory
== NULL
) {
10661 driver_dir
= talloc_asprintf(tctx
,
10663 driver_directory_dir(d
->remote
.driver_directory
),
10664 d
->remote
.driver_upload_directory
);
10665 torture_assert_not_null(tctx
, driver_dir
, "ENOMEM");
10667 torture_comment(tctx
,
10668 "Create remote driver directory: %s\n",
10671 torture_assert_ntstatus_ok(tctx
,
10672 smbcli_mkdir(cli
->tree
,
10674 "Failed to create driver directory");
10679 static bool upload_printer_driver_file(struct torture_context
*tctx
,
10680 struct smbcli_state
*cli
,
10681 struct torture_driver_context
*d
,
10682 const char *file_name
)
10687 int maxwrite
= 64512;
10690 const char *remote_dir
= driver_directory_dir(d
->remote
.driver_directory
);
10691 const char *remote_name
;
10692 const char *local_name
;
10695 if (!file_name
|| strlen(file_name
) == 0) {
10699 p
= strrchr(file_name
, '\\');
10706 local_name
= talloc_asprintf(tctx
, "%s/%s", d
->local
.driver_directory
, p
);
10707 torture_assert_not_null(tctx
, local_name
, "ENOMEM");
10708 if (d
->remote
.driver_upload_directory
!= NULL
) {
10709 remote_name
= talloc_asprintf(tctx
,
10712 d
->remote
.driver_upload_directory
,
10715 remote_name
= talloc_asprintf(tctx
, "%s\\%s", remote_dir
, p
);
10717 torture_assert_not_null(tctx
, remote_name
, "ENOMEM");
10719 torture_comment(tctx
, "Uploading %s to %s\n", local_name
, remote_name
);
10721 fnum
= smbcli_open(cli
->tree
, remote_name
, O_RDWR
|O_CREAT
|O_TRUNC
, DENY_NONE
);
10723 torture_fail(tctx
, talloc_asprintf(tctx
, "failed to open remote file: %s\n", remote_name
));
10726 f
= fopen(local_name
, "r");
10728 torture_fail(tctx
, talloc_asprintf(tctx
, "failed to open local file: %s\n", local_name
));
10731 buf
= talloc_array(tctx
, uint8_t, maxwrite
);
10741 if ((n
= fread(buf
, 1, n
, f
)) < 1) {
10742 if((n
== 0) && feof(f
))
10743 break; /* Empty local file. */
10745 torture_warning(tctx
,
10746 "failed to read file: %s\n", strerror(errno
));
10750 ret
= smbcli_write(cli
->tree
, fnum
, 0, buf
, nread
+ start
, n
);
10753 torture_warning(tctx
,
10754 "failed to write file: %s\n", smbcli_errstr(cli
->tree
));
10763 torture_assert_ntstatus_ok(tctx
,
10764 smbcli_close(cli
->tree
, fnum
),
10765 "failed to close file");
10770 static bool connect_printer_driver_share(struct torture_context
*tctx
,
10771 const char *server_name
,
10772 const char *share_name
,
10773 struct smbcli_state
**cli
)
10775 struct smbcli_options smb_options
;
10776 struct smbcli_session_options smb_session_options
;
10778 torture_comment(tctx
, "Connecting printer driver share '%s' on '%s'\n",
10779 share_name
, server_name
);
10781 lpcfg_smbcli_options(tctx
->lp_ctx
, &smb_options
);
10782 lpcfg_smbcli_session_options(tctx
->lp_ctx
, &smb_session_options
);
10784 torture_assert_ntstatus_ok(tctx
,
10785 smbcli_full_connection(tctx
, cli
, server_name
,
10786 lpcfg_smb_ports(tctx
->lp_ctx
),
10788 lpcfg_socket_options(tctx
->lp_ctx
),
10789 samba_cmdline_get_creds(),
10790 lpcfg_resolve_context(tctx
->lp_ctx
),
10793 &smb_session_options
,
10794 lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
)),
10795 "failed to open driver share");
10800 static bool upload_printer_driver(struct torture_context
*tctx
,
10801 const char *server_name
,
10802 struct torture_driver_context
*d
)
10804 struct smbcli_state
*cli
;
10805 const char *share_name
= driver_directory_share(tctx
, d
->remote
.driver_directory
);
10808 torture_assert(tctx
,
10809 connect_printer_driver_share(tctx
, server_name
, share_name
, &cli
),
10810 "failed to connect to driver share");
10812 torture_comment(tctx
, "Uploading printer driver files to \\\\%s\\%s\n",
10813 server_name
, share_name
);
10815 torture_assert(tctx
,
10816 create_printer_driver_directory(tctx
, cli
, d
),
10817 "failed to create driver directory");
10819 torture_assert(tctx
,
10820 upload_printer_driver_file(tctx
, cli
, d
, d
->info8
.driver_path
),
10821 "failed to upload driver_path");
10822 torture_assert(tctx
,
10823 upload_printer_driver_file(tctx
, cli
, d
, d
->info8
.data_file
),
10824 "failed to upload data_file");
10825 torture_assert(tctx
,
10826 upload_printer_driver_file(tctx
, cli
, d
, d
->info8
.config_file
),
10827 "failed to upload config_file");
10828 torture_assert(tctx
,
10829 upload_printer_driver_file(tctx
, cli
, d
, d
->info8
.help_file
),
10830 "failed to upload help_file");
10831 if (d
->info8
.dependent_files
) {
10832 for (i
=0; d
->info8
.dependent_files
->string
&& d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
10833 torture_assert(tctx
,
10834 upload_printer_driver_file(tctx
, cli
, d
, d
->info8
.dependent_files
->string
[i
]),
10835 "failed to upload dependent_files");
10844 static bool check_printer_driver_file(struct torture_context
*tctx
,
10845 struct smbcli_state
*cli
,
10846 struct torture_driver_context
*d
,
10847 const char *file_name
)
10849 const char *remote_arch_dir
= NULL
;
10850 const char *remote_name
= NULL
;
10853 torture_assert(tctx
, (file_name
&& strlen(file_name
) != 0), "invalid filename");
10855 remote_arch_dir
= driver_directory_dir(d
->remote
.driver_directory
);
10856 torture_assert_not_null(tctx
, remote_arch_dir
, "remote_arch_dir is null");
10858 remote_name
= talloc_asprintf(tctx
,
10863 torture_assert_not_null(tctx
, remote_name
, "renote_name is null");
10865 torture_comment(tctx
, "checking for driver file at %s\n", remote_name
);
10867 fnum
= smbcli_open(cli
->tree
, remote_name
, O_RDONLY
, DENY_NONE
);
10872 torture_assert_ntstatus_ok(tctx
,
10873 smbcli_close(cli
->tree
, fnum
),
10874 "failed to close driver file");
10879 static bool check_printer_driver_files(struct torture_context
*tctx
,
10880 const char *server_name
,
10881 struct torture_driver_context
*d
,
10884 struct smbcli_state
*cli
;
10885 const char *share_name
= driver_directory_share(tctx
, d
->remote
.driver_directory
);
10888 torture_assert(tctx
,
10889 connect_printer_driver_share(tctx
, server_name
, share_name
, &cli
),
10890 "failed to connect to driver share");
10892 torture_comment(tctx
, "checking %sexistent driver files at \\\\%s\\%s\n",
10893 (expect_exist
? "": "non-"),
10894 server_name
, share_name
);
10896 if (d
->info8
.driver_path
&& d
->info8
.driver_path
[0]) {
10897 torture_assert(tctx
,
10898 check_printer_driver_file(tctx
, cli
, d
, d
->info8
.driver_path
) == expect_exist
,
10899 "failed driver_path check");
10901 if (d
->info8
.data_file
&& d
->info8
.data_file
[0]) {
10902 torture_assert(tctx
,
10903 check_printer_driver_file(tctx
, cli
, d
, d
->info8
.data_file
) == expect_exist
,
10904 "failed data_file check");
10906 if (d
->info8
.config_file
&& d
->info8
.config_file
[0]) {
10907 torture_assert(tctx
,
10908 check_printer_driver_file(tctx
, cli
, d
, d
->info8
.config_file
) == expect_exist
,
10909 "failed config_file check");
10911 if (d
->info8
.help_file
&& d
->info8
.help_file
[0]) {
10912 torture_assert(tctx
,
10913 check_printer_driver_file(tctx
, cli
, d
, d
->info8
.help_file
) == expect_exist
,
10914 "failed help_file check");
10916 if (d
->info8
.dependent_files
) {
10917 for (i
=0; d
->info8
.dependent_files
->string
&& d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
10918 torture_assert(tctx
,
10919 check_printer_driver_file(tctx
, cli
, d
, d
->info8
.dependent_files
->string
[i
]) == expect_exist
,
10920 "failed dependent_files check");
10929 static bool remove_printer_driver_file(struct torture_context
*tctx
,
10930 struct smbcli_state
*cli
,
10931 struct torture_driver_context
*d
,
10932 const char *file_name
)
10934 const char *remote_name
;
10935 const char *remote_dir
= driver_directory_dir(d
->remote
.driver_directory
);
10937 if (!file_name
|| strlen(file_name
) == 0) {
10941 remote_name
= talloc_asprintf(tctx
, "%s\\%s", remote_dir
, file_name
);
10943 torture_comment(tctx
, "Removing %s\n", remote_name
);
10945 torture_assert_ntstatus_ok(tctx
,
10946 smbcli_unlink(cli
->tree
, remote_name
),
10947 "failed to unlink");
10952 static bool remove_printer_driver(struct torture_context
*tctx
,
10953 const char *server_name
,
10954 struct torture_driver_context
*d
)
10956 struct smbcli_state
*cli
;
10957 const char *share_name
= driver_directory_share(tctx
, d
->remote
.driver_directory
);
10960 torture_assert(tctx
,
10961 connect_printer_driver_share(tctx
, server_name
, share_name
, &cli
),
10962 "failed to connect to driver share");
10964 torture_comment(tctx
, "Removing printer driver files from \\\\%s\\%s\n",
10965 server_name
, share_name
);
10967 torture_assert(tctx
,
10968 remove_printer_driver_file(tctx
, cli
, d
, d
->info8
.driver_path
),
10969 "failed to remove driver_path");
10970 torture_assert(tctx
,
10971 remove_printer_driver_file(tctx
, cli
, d
, d
->info8
.data_file
),
10972 "failed to remove data_file");
10973 if (!strequal(d
->info8
.config_file
, d
->info8
.driver_path
)) {
10974 torture_assert(tctx
,
10975 remove_printer_driver_file(tctx
, cli
, d
, d
->info8
.config_file
),
10976 "failed to remove config_file");
10978 torture_assert(tctx
,
10979 remove_printer_driver_file(tctx
, cli
, d
, d
->info8
.help_file
),
10980 "failed to remove help_file");
10981 if (d
->info8
.dependent_files
) {
10982 for (i
=0; d
->info8
.dependent_files
->string
&& d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
10983 if (strequal(d
->info8
.dependent_files
->string
[i
], d
->info8
.driver_path
) ||
10984 strequal(d
->info8
.dependent_files
->string
[i
], d
->info8
.data_file
) ||
10985 strequal(d
->info8
.dependent_files
->string
[i
], d
->info8
.config_file
) ||
10986 strequal(d
->info8
.dependent_files
->string
[i
], d
->info8
.help_file
)) {
10989 torture_assert(tctx
,
10990 remove_printer_driver_file(tctx
, cli
, d
, d
->info8
.dependent_files
->string
[i
]),
10991 "failed to remove dependent_files");
11001 static bool test_add_driver_arg(struct torture_context
*tctx
,
11002 struct dcerpc_pipe
*p
,
11003 struct torture_driver_context
*d
)
11006 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
11007 const char *server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
11008 uint32_t levels
[] = { 1, 2, 3, 4, 6, 8 };
11010 struct spoolss_AddDriverInfo8 info8
;
11011 uint32_t add_flags
= APD_COPY_NEW_FILES
;
11012 uint32_t delete_flags
= 0;
11014 ZERO_STRUCT(info8
);
11016 torture_comment(tctx
, "Testing PrinterDriver%s '%s' for environment '%s'\n",
11017 d
->ex
? "Ex" : "", d
->info8
.driver_name
, d
->local
.environment
);
11019 torture_assert(tctx
,
11020 fillup_printserver_info(tctx
, p
, d
),
11021 "failed to fillup printserver info");
11023 if (!directory_exist(d
->local
.driver_directory
)) {
11024 torture_skip(tctx
, "Skipping Printer Driver test as no local driver is available");
11027 torture_assert(tctx
,
11028 upload_printer_driver(tctx
, dcerpc_server_name(p
), d
),
11029 "failed to upload printer driver");
11032 if (d
->info8
.dependent_files
) {
11033 info8
.dependent_files
= talloc_zero(tctx
, struct spoolss_StringArray
);
11034 if (d
->info8
.dependent_files
->string
) {
11035 for (i
=0; d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
11037 info8
.dependent_files
->string
= talloc_zero_array(info8
.dependent_files
, const char *, i
+1);
11038 for (i
=0; d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
11039 info8
.dependent_files
->string
[i
] = talloc_strdup(info8
.dependent_files
->string
, d
->info8
.dependent_files
->string
[i
]);
11044 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
11046 if (torture_setting_bool(tctx
, "samba3", false)) {
11047 switch (levels
[i
]) {
11050 torture_comment(tctx
, "skipping level %d against samba\n", levels
[i
]);
11056 if (torture_setting_bool(tctx
, "w2k3", false)) {
11057 switch (levels
[i
]) {
11059 torture_comment(tctx
, "skipping level %d against w2k3\n", levels
[i
]);
11066 torture_comment(tctx
,
11067 "Testing PrinterDriver%s '%s' add & delete level %d\n",
11068 d
->ex
? "Ex" : "", info8
.driver_name
, levels
[i
]);
11070 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
);
11073 info8
.driver_path
= talloc_asprintf(tctx
, "%s\\%s", d
->remote
.driver_directory
, d
->info8
.driver_path
);
11074 info8
.data_file
= talloc_asprintf(tctx
, "%s\\%s", d
->remote
.driver_directory
, d
->info8
.data_file
);
11075 if (d
->info8
.config_file
) {
11076 info8
.config_file
= talloc_asprintf(tctx
, "%s\\%s", d
->remote
.driver_directory
, d
->info8
.config_file
);
11078 if (d
->info8
.help_file
) {
11079 info8
.help_file
= talloc_asprintf(tctx
, "%s\\%s", d
->remote
.driver_directory
, d
->info8
.help_file
);
11081 if (d
->info8
.dependent_files
&& d
->info8
.dependent_files
->string
) {
11082 for (i
=0; d
->info8
.dependent_files
->string
[i
] != NULL
; i
++) {
11083 info8
.dependent_files
->string
[i
] = talloc_asprintf(tctx
, "%s\\%s", d
->remote
.driver_directory
, d
->info8
.dependent_files
->string
[i
]);
11087 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
11089 if (torture_setting_bool(tctx
, "samba3", false)) {
11090 switch (levels
[i
]) {
11098 if (torture_setting_bool(tctx
, "w2k3", false)) {
11099 switch (levels
[i
]) {
11101 torture_comment(tctx
, "skipping level %d against w2k3\n", levels
[i
]);
11108 torture_comment(tctx
,
11109 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
11110 d
->ex
? "Ex" : "", info8
.driver_name
, levels
[i
]);
11112 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
);
11115 torture_assert(tctx
,
11116 remove_printer_driver(tctx
, dcerpc_server_name(p
), d
),
11117 "failed to remove printer driver");
11119 torture_comment(tctx
, "\n");
11124 static bool test_add_driver_ex_64(struct torture_context
*tctx
,
11125 struct dcerpc_pipe
*p
)
11127 struct torture_driver_context
*d
;
11129 d
= talloc_zero(tctx
, struct torture_driver_context
);
11131 d
->local
.environment
= talloc_strdup(d
, SPOOLSS_ARCHITECTURE_x64
);
11132 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/x64");
11134 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
11135 d
->info8
.driver_name
= TORTURE_DRIVER_EX
;
11136 d
->info8
.architecture
= d
->local
.environment
;
11137 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
11138 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
11139 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
11142 return test_add_driver_arg(tctx
, p
, d
);
11145 static bool test_add_driver_ex_32(struct torture_context
*tctx
,
11146 struct dcerpc_pipe
*p
)
11148 struct torture_driver_context
*d
;
11150 d
= talloc_zero(tctx
, struct torture_driver_context
);
11152 d
->local
.environment
= talloc_strdup(d
, SPOOLSS_ARCHITECTURE_NT_X86
);
11153 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/i386");
11155 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
11156 d
->info8
.driver_name
= TORTURE_DRIVER_EX
;
11157 d
->info8
.architecture
= d
->local
.environment
;
11158 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
11159 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
11160 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
11163 return test_add_driver_arg(tctx
, p
, d
);
11166 static bool test_add_driver_64(struct torture_context
*tctx
,
11167 struct dcerpc_pipe
*p
)
11169 struct torture_driver_context
*d
;
11171 d
= talloc_zero(tctx
, struct torture_driver_context
);
11173 d
->local
.environment
= talloc_strdup(d
, SPOOLSS_ARCHITECTURE_x64
);
11174 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/x64");
11176 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
11177 d
->info8
.driver_name
= TORTURE_DRIVER_ADD
;
11178 d
->info8
.architecture
= d
->local
.environment
;
11179 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
11180 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
11181 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
11184 return test_add_driver_arg(tctx
, p
, d
);
11187 static bool test_add_driver_32(struct torture_context
*tctx
,
11188 struct dcerpc_pipe
*p
)
11190 struct torture_driver_context
*d
;
11192 d
= talloc_zero(tctx
, struct torture_driver_context
);
11194 d
->local
.environment
= talloc_strdup(d
, SPOOLSS_ARCHITECTURE_NT_X86
);
11195 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/i386");
11197 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
11198 d
->info8
.driver_name
= TORTURE_DRIVER_ADD
;
11199 d
->info8
.architecture
= d
->local
.environment
;
11200 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
11201 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
11202 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
11205 return test_add_driver_arg(tctx
, p
, d
);
11208 static bool test_add_driver_adobe(struct torture_context
*tctx
,
11209 struct dcerpc_pipe
*p
)
11211 struct torture_driver_context
*d
;
11213 if (!torture_setting_bool(tctx
, "samba3", false)) {
11214 torture_skip(tctx
, "skipping adobe test which only works against samba3");
11217 d
= talloc_zero(tctx
, struct torture_driver_context
);
11219 d
->local
.environment
= talloc_strdup(d
, "Windows 4.0");
11220 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/adobe/");
11222 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_9X
;
11223 d
->info8
.driver_name
= TORTURE_DRIVER_ADOBE
;
11224 d
->info8
.architecture
= d
->local
.environment
;
11225 d
->info8
.driver_path
= talloc_strdup(d
, "ADOBEPS4.DRV");
11226 d
->info8
.data_file
= talloc_strdup(d
, "DEFPRTR2.PPD");
11227 d
->info8
.config_file
= talloc_strdup(d
, "ADOBEPS4.DRV");
11229 d
->info8
.help_file
= talloc_strdup(d
, "ADOBEPS4.HLP");
11230 d
->info8
.monitor_name
= talloc_strdup(d
, "PSMON.DLL");
11234 return test_add_driver_arg(tctx
, p
, d
);
11237 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context
*tctx
,
11238 struct dcerpc_pipe
*p
)
11240 struct torture_driver_context
*d
;
11241 struct spoolss_StringArray
*a
;
11243 if (!torture_setting_bool(tctx
, "samba3", false)) {
11244 torture_skip(tctx
, "skipping cupsaddsmb test which only works against samba3");
11247 d
= talloc_zero(tctx
, struct torture_driver_context
);
11249 d
->local
.environment
= talloc_strdup(d
, "Windows 4.0");
11250 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/adobe/");
11252 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_9X
;
11253 d
->info8
.driver_name
= TORTURE_DRIVER_ADOBE_CUPSADDSMB
;
11254 d
->info8
.architecture
= d
->local
.environment
;
11255 d
->info8
.driver_path
= talloc_strdup(d
, "ADOBEPS4.DRV");
11256 d
->info8
.data_file
= talloc_strdup(d
, "DEFPRTR2.PPD");
11257 d
->info8
.config_file
= NULL
;
11258 d
->info8
.help_file
= talloc_strdup(d
, "ADOBEPS4.HLP");
11259 d
->info8
.monitor_name
= talloc_strdup(d
, "PSMON.DLL");
11260 d
->info8
.default_datatype
= talloc_strdup(d
, "RAW");
11262 a
= talloc_zero(d
, struct spoolss_StringArray
);
11263 a
->string
= talloc_zero_array(a
, const char *, 7);
11264 a
->string
[0] = talloc_strdup(a
->string
, "ADOBEPS4.DRV");
11265 a
->string
[1] = talloc_strdup(a
->string
, "DEFPRTR2.PPD");
11266 a
->string
[2] = talloc_strdup(a
->string
, "ADOBEPS4.HLP");
11267 a
->string
[3] = talloc_strdup(a
->string
, "PSMON.DLL");
11268 a
->string
[4] = talloc_strdup(a
->string
, "ADFONTS.MFM");
11269 a
->string
[5] = talloc_strdup(a
->string
, "ICONLIB.DLL");
11271 d
->info8
.dependent_files
= a
;
11274 return test_add_driver_arg(tctx
, p
, d
);
11277 static bool test_add_driver_timestamps(struct torture_context
*tctx
,
11278 struct dcerpc_pipe
*p
)
11280 struct torture_driver_context
*d
;
11281 struct timeval t
= timeval_current();
11283 d
= talloc_zero(tctx
, struct torture_driver_context
);
11285 d
->local
.environment
= talloc_strdup(d
, SPOOLSS_ARCHITECTURE_NT_X86
);
11286 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/i386");
11288 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
11289 d
->info8
.driver_name
= TORTURE_DRIVER_TIMESTAMPS
;
11290 d
->info8
.architecture
= d
->local
.environment
;
11291 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
11292 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
11293 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
11294 d
->info8
.driver_date
= timeval_to_nttime(&t
);
11297 torture_assert(tctx
,
11298 test_add_driver_arg(tctx
, p
, d
),
11301 unix_to_nt_time(&d
->info8
.driver_date
, 1);
11303 torture_assert(tctx
,
11304 test_add_driver_arg(tctx
, p
, d
),
11310 static bool test_multiple_drivers(struct torture_context
*tctx
,
11311 struct dcerpc_pipe
*p
)
11313 struct torture_driver_context
*d
;
11314 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
11315 const char *server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
11317 struct spoolss_AddDriverInfo8 info8
;
11318 uint32_t add_flags
= APD_COPY_NEW_FILES
;
11319 uint32_t delete_flags
= 0;
11321 d
= talloc_zero(tctx
, struct torture_driver_context
);
11323 d
->local
.environment
= talloc_strdup(d
, SPOOLSS_ARCHITECTURE_NT_X86
);
11324 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/i386");
11326 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
11327 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
11328 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
11329 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
11330 d
->info8
.architecture
= d
->local
.environment
;
11333 torture_assert(tctx
,
11334 fillup_printserver_info(tctx
, p
, d
),
11335 "failed to fillup printserver info");
11337 if (!directory_exist(d
->local
.driver_directory
)) {
11338 torture_skip(tctx
, "Skipping Printer Driver test as no local driver is available");
11341 torture_assert(tctx
,
11342 upload_printer_driver(tctx
, dcerpc_server_name(p
), d
),
11343 "failed to upload printer driver");
11347 for (i
=0; i
< 3; i
++) {
11348 info8
.driver_name
= talloc_asprintf(d
, "torture_test_driver_%d", i
);
11350 torture_assert(tctx
,
11351 test_AddPrinterDriver_args_level_3(tctx
, b
, server_name_slash
, &info8
, add_flags
, true, NULL
),
11352 "failed to add driver");
11355 torture_assert(tctx
,
11356 test_DeletePrinterDriverEx(tctx
, b
, server_name_slash
, "torture_test_driver_0", info8
.architecture
, delete_flags
, info8
.version
),
11357 "failed to delete driver");
11359 torture_assert(tctx
,
11360 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, info8
.architecture
, 3, "torture_test_driver_1", NULL
),
11361 "torture_test_driver_1 no longer on the server");
11363 torture_assert(tctx
,
11364 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, info8
.architecture
, 3, "torture_test_driver_2", NULL
),
11365 "torture_test_driver_2 no longer on the server");
11367 torture_assert(tctx
,
11368 test_DeletePrinterDriverEx(tctx
, b
, server_name_slash
, "torture_test_driver_1", info8
.architecture
, delete_flags
, info8
.version
),
11369 "failed to delete driver");
11371 torture_assert(tctx
,
11372 test_EnumPrinterDrivers_findone(tctx
, b
, server_name_slash
, info8
.architecture
, 3, "torture_test_driver_2", NULL
),
11373 "torture_test_driver_2 no longer on the server");
11375 torture_assert(tctx
,
11376 test_DeletePrinterDriverEx(tctx
, b
, server_name_slash
, "torture_test_driver_2", info8
.architecture
, delete_flags
, info8
.version
),
11377 "failed to delete driver");
11379 torture_assert(tctx
,
11380 remove_printer_driver(tctx
, dcerpc_server_name(p
), d
),
11381 "failed to remove printer driver");
11386 static bool test_driver_copy_from_directory(struct torture_context
*tctx
,
11387 struct dcerpc_pipe
*p
,
11388 const char *architecture
)
11390 struct torture_driver_context
*d
;
11391 struct spoolss_StringArray
*a
;
11392 uint32_t add_flags
= APD_COPY_NEW_FILES
|APD_COPY_FROM_DIRECTORY
|APD_RETURN_BLOCKING_STATUS_CODE
;
11393 uint32_t delete_flags
= DPD_DELETE_ALL_FILES
;
11394 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
11395 const char *server_name_slash
= talloc_asprintf(tctx
,
11397 dcerpc_server_name(p
));
11398 struct GUID guid
= GUID_random();
11401 d
= talloc_zero(tctx
, struct torture_driver_context
);
11402 torture_assert_not_null(tctx
, d
, "ENOMEM");
11404 d
->local
.environment
= talloc_strdup(d
, architecture
);
11405 torture_assert_not_null_goto(tctx
, d
->local
.environment
, ok
, done
, "ENOMEM");
11407 if (strequal(architecture
, SPOOLSS_ARCHITECTURE_x64
)) {
11408 d
->local
.driver_directory
=
11409 talloc_strdup(d
, "/usr/share/cups/drivers/x64");
11411 d
->local
.driver_directory
=
11412 talloc_strdup(d
, "/usr/share/cups/drivers/i386");
11414 torture_assert_not_null_goto(tctx
, d
->local
.driver_directory
, ok
, done
, "ENOMEM");
11416 d
->remote
.driver_upload_directory
= GUID_string2(d
, &guid
);
11417 torture_assert_not_null_goto(tctx
, d
->remote
.driver_upload_directory
, ok
, done
, "ENOMEM");
11419 torture_assert(tctx
,
11420 fillup_printserver_info(tctx
, p
, d
),
11421 "failed to fillup printserver info");
11424 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
11425 d
->info8
.driver_name
= TORTURE_DRIVER_COPY_DIR
;
11426 d
->info8
.architecture
= d
->local
.environment
;
11428 d
->info8
.driver_path
= CREATE_PRINTER_DRIVER_PATH(d
, "pscript5.dll");
11429 torture_assert_not_null_goto(tctx
, d
->info8
.driver_path
, ok
, done
, "ENOMEM");
11430 d
->info8
.data_file
= CREATE_PRINTER_DRIVER_PATH(d
, "cups6.ppd");
11431 torture_assert_not_null_goto(tctx
, d
->info8
.data_file
, ok
, done
, "ENOMEM");
11432 d
->info8
.config_file
= CREATE_PRINTER_DRIVER_PATH(d
, "cupsui6.dll");
11433 torture_assert_not_null_goto(tctx
, d
->info8
.config_file
, ok
, done
, "ENOMEM");
11434 d
->info8
.help_file
= CREATE_PRINTER_DRIVER_PATH(d
, "pscript.hlp");
11435 torture_assert_not_null_goto(tctx
, d
->info8
.help_file
, ok
, done
, "ENOMEM");
11437 a
= talloc_zero(d
, struct spoolss_StringArray
);
11438 torture_assert_not_null_goto(tctx
, a
, ok
, done
, "ENOMEM");
11439 a
->string
= talloc_zero_array(a
, const char *, 3);
11440 torture_assert_not_null_goto(tctx
, a
->string
, ok
, done
, "ENOMEM");
11441 a
->string
[0] = CREATE_PRINTER_DRIVER_PATH(d
, "cups6.inf");
11442 torture_assert_not_null_goto(tctx
, a
->string
[0], ok
, done
, "ENOMEM");
11443 a
->string
[1] = CREATE_PRINTER_DRIVER_PATH(d
, "cups6.ini");
11444 torture_assert_not_null_goto(tctx
, a
->string
[1], ok
, done
, "ENOMEM");
11446 d
->info8
.dependent_files
= a
;
11448 if (!directory_exist(d
->local
.driver_directory
)) {
11450 "Skipping Printer Driver test as no local drivers "
11454 torture_assert(tctx
,
11455 upload_printer_driver(tctx
, dcerpc_server_name(p
), d
),
11456 "failed to upload printer driver");
11458 torture_assert(tctx
,
11459 test_AddPrinterDriver_args_level_3(tctx
,
11466 "failed to add driver");
11468 torture_assert(tctx
,
11469 test_DeletePrinterDriverEx(tctx
,
11472 d
->info8
.driver_name
,
11473 d
->local
.environment
,
11476 "failed to delete driver");
11478 torture_assert(tctx
,
11479 check_printer_driver_files(tctx
,
11480 dcerpc_server_name(p
),
11483 "printer driver file check failed");
11491 static bool test_driver_copy_from_directory_64(struct torture_context
*tctx
,
11492 struct dcerpc_pipe
*p
)
11494 return test_driver_copy_from_directory(tctx
, p
, SPOOLSS_ARCHITECTURE_x64
);
11497 static bool test_driver_copy_from_directory_32(struct torture_context
*tctx
,
11498 struct dcerpc_pipe
*p
)
11500 return test_driver_copy_from_directory(tctx
, p
, SPOOLSS_ARCHITECTURE_NT_X86
);
11503 static bool test_del_driver_all_files(struct torture_context
*tctx
,
11504 struct dcerpc_pipe
*p
)
11506 struct torture_driver_context
*d
;
11507 struct spoolss_StringArray
*a
;
11508 uint32_t add_flags
= APD_COPY_NEW_FILES
;
11509 uint32_t delete_flags
= DPD_DELETE_ALL_FILES
;
11510 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
11511 const char *server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
11513 d
= talloc_zero(tctx
, struct torture_driver_context
);
11515 d
->local
.environment
= talloc_strdup(d
, SPOOLSS_ARCHITECTURE_x64
);
11516 d
->local
.driver_directory
= talloc_strdup(d
, "/usr/share/cups/drivers/x64");
11519 d
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
11520 d
->info8
.driver_name
= TORTURE_DRIVER_DELETER
;
11521 d
->info8
.architecture
= d
->local
.environment
;
11522 d
->info8
.driver_path
= talloc_strdup(d
, "pscript5.dll");
11523 d
->info8
.data_file
= talloc_strdup(d
, "cups6.ppd");
11524 d
->info8
.config_file
= talloc_strdup(d
, "cupsui6.dll");
11525 d
->info8
.help_file
= talloc_strdup(d
, "pscript.hlp");
11527 a
= talloc_zero(d
, struct spoolss_StringArray
);
11528 a
->string
= talloc_zero_array(a
, const char *, 3);
11529 a
->string
[0] = talloc_strdup(a
->string
, "cups6.inf");
11530 a
->string
[1] = talloc_strdup(a
->string
, "cups6.ini");
11532 d
->info8
.dependent_files
= a
;
11534 torture_assert(tctx
,
11535 fillup_printserver_info(tctx
, p
, d
),
11536 "failed to fillup printserver info");
11538 if (!directory_exist(d
->local
.driver_directory
)) {
11539 torture_skip(tctx
, "Skipping Printer Driver test as no local driver is available");
11542 torture_assert(tctx
,
11543 upload_printer_driver(tctx
, dcerpc_server_name(p
), d
),
11544 "failed to upload printer driver");
11546 torture_assert(tctx
,
11547 test_AddPrinterDriver_args_level_3(tctx
, b
, server_name_slash
, &d
->info8
, add_flags
, true, NULL
),
11548 "failed to add driver");
11550 torture_assert(tctx
,
11551 test_DeletePrinterDriverEx(tctx
, b
, server_name_slash
,
11552 d
->info8
.driver_name
,
11553 d
->info8
.architecture
,
11556 "failed to delete driver");
11558 torture_assert(tctx
,
11559 check_printer_driver_files(tctx
, dcerpc_server_name(p
), d
, false),
11560 "printer driver file check failed");
11566 static bool test_del_driver_unused_files(struct torture_context
*tctx
,
11567 struct dcerpc_pipe
*p
)
11569 struct torture_driver_context
*d1
;
11570 struct torture_driver_context
*d2
;
11571 uint32_t add_flags
= APD_COPY_NEW_FILES
;
11572 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
11573 const char *server_name_slash
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
11575 d1
= talloc_zero(tctx
, struct torture_driver_context
);
11578 d1
->local
.environment
= talloc_strdup(d1
, SPOOLSS_ARCHITECTURE_x64
);
11579 d1
->local
.driver_directory
= talloc_strdup(d1
, "/usr/share/cups/drivers/x64");
11581 d1
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
11582 d1
->info8
.driver_name
= TORTURE_DRIVER_DELETER
;
11583 d1
->info8
.architecture
= NULL
;
11584 d1
->info8
.driver_path
= talloc_strdup(d1
, "pscript5.dll");
11585 d1
->info8
.data_file
= talloc_strdup(d1
, "cups6.ppd");
11586 d1
->info8
.config_file
= talloc_strdup(d1
, "cupsui6.dll");
11587 d1
->info8
.help_file
= talloc_strdup(d1
, "pscript.hlp");
11588 d1
->info8
.architecture
= d1
->local
.environment
;
11590 d2
= talloc_zero(tctx
, struct torture_driver_context
);
11593 d2
->local
.environment
= talloc_strdup(d2
, SPOOLSS_ARCHITECTURE_x64
);
11594 d2
->local
.driver_directory
= talloc_strdup(d2
, "/usr/share/cups/drivers/x64");
11596 d2
->info8
.version
= SPOOLSS_DRIVER_VERSION_200X
;
11597 d2
->info8
.driver_name
= TORTURE_DRIVER_DELETERIN
;
11598 d2
->info8
.architecture
= NULL
;
11599 d2
->info8
.driver_path
= talloc_strdup(d2
, "pscript5.dll"); /* overlapping */
11600 d2
->info8
.data_file
= talloc_strdup(d2
, "cupsps6.dll");
11601 d2
->info8
.config_file
= talloc_strdup(d2
, "cups6.ini");
11602 d2
->info8
.help_file
= talloc_strdup(d2
, "pscript.hlp"); /* overlapping */
11603 d2
->info8
.architecture
= d2
->local
.environment
;
11605 torture_assert(tctx
,
11606 fillup_printserver_info(tctx
, p
, d1
),
11607 "failed to fillup printserver info");
11608 torture_assert(tctx
,
11609 fillup_printserver_info(tctx
, p
, d2
),
11610 "failed to fillup printserver info");
11612 if (!directory_exist(d1
->local
.driver_directory
)) {
11613 torture_skip(tctx
, "Skipping Printer Driver test as no local driver is available");
11616 torture_assert(tctx
,
11617 upload_printer_driver(tctx
, dcerpc_server_name(p
), d1
),
11618 "failed to upload printer driver");
11619 torture_assert(tctx
,
11620 test_AddPrinterDriver_args_level_3(tctx
, b
, server_name_slash
, &d1
->info8
, add_flags
, true, NULL
),
11621 "failed to add driver");
11623 torture_assert(tctx
,
11624 upload_printer_driver(tctx
, dcerpc_server_name(p
), d2
),
11625 "failed to upload printer driver");
11626 torture_assert(tctx
,
11627 test_AddPrinterDriver_args_level_3(tctx
, b
, server_name_slash
, &d2
->info8
, add_flags
, true, NULL
),
11628 "failed to add driver");
11630 /* some files are in use by a separate driver, should fail */
11631 torture_assert(tctx
,
11632 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name_slash
,
11633 d1
->info8
.driver_name
,
11634 d1
->info8
.architecture
,
11635 DPD_DELETE_ALL_FILES
,
11637 WERR_PRINTER_DRIVER_IN_USE
),
11638 "invalid delete driver response");
11640 /* should only delete files not in use by other driver */
11641 torture_assert(tctx
,
11642 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name_slash
,
11643 d1
->info8
.driver_name
,
11644 d1
->info8
.architecture
,
11645 DPD_DELETE_UNUSED_FILES
,
11648 "failed to delete driver (unused files)");
11650 /* check non-overlapping were deleted */
11651 d1
->info8
.driver_path
= NULL
;
11652 d1
->info8
.help_file
= NULL
;
11653 torture_assert(tctx
,
11654 check_printer_driver_files(tctx
, dcerpc_server_name(p
), d1
, false),
11655 "printer driver file check failed");
11656 /* d2 files should be uneffected */
11657 torture_assert(tctx
,
11658 check_printer_driver_files(tctx
, dcerpc_server_name(p
), d2
, true),
11659 "printer driver file check failed");
11661 torture_assert(tctx
,
11662 test_DeletePrinterDriverEx_exp(tctx
, b
, server_name_slash
,
11663 d2
->info8
.driver_name
,
11664 d2
->info8
.architecture
,
11665 DPD_DELETE_ALL_FILES
,
11668 "failed to delete driver");
11670 torture_assert(tctx
,
11671 check_printer_driver_files(tctx
, dcerpc_server_name(p
), d2
, false),
11672 "printer driver file check failed");
11679 struct torture_suite
*torture_rpc_spoolss_driver(TALLOC_CTX
*mem_ctx
)
11681 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "spoolss.driver");
11683 struct torture_rpc_tcase
*tcase
= torture_suite_add_rpc_iface_tcase(suite
,
11684 "driver", &ndr_table_spoolss
);
11685 torture_rpc_tcase_add_test(tcase
, "add_driver_64", test_add_driver_64
);
11686 torture_rpc_tcase_add_test(tcase
, "add_driver_ex_64", test_add_driver_ex_64
);
11688 torture_rpc_tcase_add_test(tcase
, "add_driver_32", test_add_driver_32
);
11689 torture_rpc_tcase_add_test(tcase
, "add_driver_ex_32", test_add_driver_ex_32
);
11691 torture_rpc_tcase_add_test(tcase
, "add_driver_adobe", test_add_driver_adobe
);
11693 torture_rpc_tcase_add_test(tcase
, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb
);
11695 torture_rpc_tcase_add_test(tcase
, "add_driver_timestamps", test_add_driver_timestamps
);
11697 torture_rpc_tcase_add_test(tcase
, "multiple_drivers", test_multiple_drivers
);
11699 torture_rpc_tcase_add_test(tcase
,
11700 "test_driver_copy_from_directory_64",
11701 test_driver_copy_from_directory_64
);
11703 torture_rpc_tcase_add_test(tcase
,
11704 "test_driver_copy_from_directory_32",
11705 test_driver_copy_from_directory_32
);
11707 torture_rpc_tcase_add_test(tcase
, "del_driver_all_files", test_del_driver_all_files
);
11709 torture_rpc_tcase_add_test(tcase
, "del_driver_unused_files", test_del_driver_unused_files
);