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-2010
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/rpc.h"
33 #include "param/param.h"
34 #include "lib/registry/registry.h"
36 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
37 #define TORTURE_PRINTER "torture_printer"
38 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
39 #define TORTURE_PRINTER_EX "torture_printer_ex"
41 #define TOP_LEVEL_PRINTER_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"
43 struct test_spoolss_context
{
44 /* print server handle */
45 struct policy_handle server_handle
;
48 uint32_t port_count
[3];
49 union spoolss_PortInfo
*ports
[3];
51 /* for EnumPrinterDrivers */
52 uint32_t driver_count
[8];
53 union spoolss_DriverInfo
*drivers
[8];
55 /* for EnumMonitors */
56 uint32_t monitor_count
[3];
57 union spoolss_MonitorInfo
*monitors
[3];
59 /* for EnumPrintProcessors */
60 uint32_t print_processor_count
[2];
61 union spoolss_PrintProcessorInfo
*print_processors
[2];
63 /* for EnumPrinters */
64 uint32_t printer_count
[6];
65 union spoolss_PrinterInfo
*printers
[6];
68 #define COMPARE_STRING(tctx, c,r,e) \
69 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
71 /* not every compiler supports __typeof__() */
73 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
74 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
75 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
77 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
78 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
82 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
85 #define COMPARE_UINT32(tctx, c, r, e) do {\
86 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
87 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
90 #define COMPARE_UINT64(tctx, c, r, e) do {\
91 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
92 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
96 #define COMPARE_NTTIME(tctx, c, r, e) do {\
97 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
98 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
101 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
103 if (!c.e && !r.e) { \
107 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
110 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
112 for (__i=0;c.e[__i] != NULL; __i++) { \
113 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
117 #define CHECK_ALIGN(size, n) do {\
119 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
120 size, n, size + n - (size % n));\
124 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
126 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, ic, needed, align) do { \
127 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
128 uint32_t size = ndr_size_##fn##_info(tctx, ic, level, count, info);\
129 uint32_t round_size = DO_ROUND(size, align);\
130 if (round_size != needed) {\
131 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
132 CHECK_ALIGN(size, align);\
137 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, ic, needed, align) do { \
138 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
139 uint32_t size = ndr_size_##fn##_info(tctx, ic, count, info);\
140 uint32_t round_size = DO_ROUND(size, align);\
141 if (round_size != needed) {\
142 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
143 CHECK_ALIGN(size, align);\
148 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, ic, needed, align) do { \
149 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
150 uint32_t size = ndr_size_##fn(info, level, ic, 0);\
151 uint32_t round_size = DO_ROUND(size, align);\
152 if (round_size != needed) {\
153 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
154 CHECK_ALIGN(size, align);\
159 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context
*tctx
,
160 const union spoolss_PrinterInfo
*i
,
162 union spoolss_SetPrinterInfo
*s
)
166 s
->info0
= talloc(tctx
, struct spoolss_SetPrinterInfo0
);
169 s
->info2
= talloc(tctx
, struct spoolss_SetPrinterInfo2
);
170 s
->info2
->servername
= i
->info2
.servername
;
171 s
->info2
->printername
= i
->info2
.printername
;
172 s
->info2
->sharename
= i
->info2
.sharename
;
173 s
->info2
->portname
= i
->info2
.portname
;
174 s
->info2
->drivername
= i
->info2
.drivername
;
175 s
->info2
->comment
= i
->info2
.comment
;
176 s
->info2
->location
= i
->info2
.location
;
177 s
->info2
->devmode_ptr
= 0;
178 s
->info2
->sepfile
= i
->info2
.sepfile
;
179 s
->info2
->printprocessor
= i
->info2
.printprocessor
;
180 s
->info2
->datatype
= i
->info2
.datatype
;
181 s
->info2
->parameters
= i
->info2
.parameters
;
182 s
->info2
->secdesc_ptr
= 0;
183 s
->info2
->attributes
= i
->info2
.attributes
;
184 s
->info2
->priority
= i
->info2
.priority
;
185 s
->info2
->defaultpriority
= i
->info2
.defaultpriority
;
186 s
->info2
->starttime
= i
->info2
.starttime
;
187 s
->info2
->untiltime
= i
->info2
.untiltime
;
188 s
->info2
->status
= i
->info2
.status
;
189 s
->info2
->cjobs
= i
->info2
.cjobs
;
190 s
->info2
->averageppm
= i
->info2
.averageppm
;
206 static bool test_OpenPrinter_server(struct torture_context
*tctx
,
207 struct dcerpc_pipe
*p
,
208 struct policy_handle
*server_handle
)
211 struct spoolss_OpenPrinter op
;
213 op
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
214 op
.in
.datatype
= NULL
;
215 op
.in
.devmode_ctr
.devmode
= NULL
;
216 op
.in
.access_mask
= 0;
217 op
.out
.handle
= server_handle
;
219 torture_comment(tctx
, "Testing OpenPrinter(%s)\n", op
.in
.printername
);
221 status
= dcerpc_spoolss_OpenPrinter(p
, tctx
, &op
);
222 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_OpenPrinter failed");
223 torture_assert_werr_ok(tctx
, op
.out
.result
, "dcerpc_spoolss_OpenPrinter failed");
228 static bool test_EnumPorts(struct torture_context
*tctx
,
229 struct dcerpc_pipe
*p
,
230 struct test_spoolss_context
*ctx
)
233 struct spoolss_EnumPorts r
;
234 uint16_t levels
[] = { 1, 2 };
237 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
238 int level
= levels
[i
];
242 union spoolss_PortInfo
*info
;
244 r
.in
.servername
= "";
248 r
.out
.needed
= &needed
;
249 r
.out
.count
= &count
;
252 torture_comment(tctx
, "Testing EnumPorts level %u\n", r
.in
.level
);
254 status
= dcerpc_spoolss_EnumPorts(p
, ctx
, &r
);
255 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPorts failed");
256 if (W_ERROR_IS_OK(r
.out
.result
)) {
257 /* TODO: do some more checks here */
260 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
261 "EnumPorts unexpected return code");
263 blob
= data_blob_talloc(ctx
, NULL
, needed
);
264 data_blob_clear(&blob
);
266 r
.in
.offered
= needed
;
268 status
= dcerpc_spoolss_EnumPorts(p
, ctx
, &r
);
269 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPorts failed");
271 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
273 torture_assert(tctx
, info
, "EnumPorts returned no info");
275 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
277 ctx
->port_count
[level
] = count
;
278 ctx
->ports
[level
] = info
;
281 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
282 int level
= levels
[i
];
283 int old_level
= levels
[i
-1];
284 torture_assert_int_equal(tctx
, ctx
->port_count
[level
], ctx
->port_count
[old_level
],
285 "EnumPorts invalid value");
287 /* if the array sizes are not the same we would maybe segfault in the following code */
289 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
290 int level
= levels
[i
];
291 for (j
=0;j
<ctx
->port_count
[level
];j
++) {
292 union spoolss_PortInfo
*cur
= &ctx
->ports
[level
][j
];
293 union spoolss_PortInfo
*ref
= &ctx
->ports
[2][j
];
296 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, port_name
);
299 /* level 2 is our reference, and it makes no sense to compare it to itself */
308 static bool test_GetPrintProcessorDirectory(struct torture_context
*tctx
,
309 struct dcerpc_pipe
*p
,
310 struct test_spoolss_context
*ctx
,
311 const char *environment
)
314 struct spoolss_GetPrintProcessorDirectory r
;
329 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
332 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
338 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
339 int level
= levels
[i
].level
;
342 r
.in
.server
= levels
[i
].server
;
343 r
.in
.environment
= environment
;
347 r
.out
.needed
= &needed
;
349 torture_comment(tctx
, "Testing GetPrintProcessorDirectory level %u\n", r
.in
.level
);
351 status
= dcerpc_spoolss_GetPrintProcessorDirectory(p
, ctx
, &r
);
352 torture_assert_ntstatus_ok(tctx
, status
,
353 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
354 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
355 "GetPrintProcessorDirectory unexpected return code");
357 blob
= data_blob_talloc(ctx
, NULL
, needed
);
358 data_blob_clear(&blob
);
360 r
.in
.offered
= needed
;
362 status
= dcerpc_spoolss_GetPrintProcessorDirectory(p
, ctx
, &r
);
363 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
365 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrintProcessorDirectory failed");
367 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 2);
374 static bool test_GetPrinterDriverDirectory(struct torture_context
*tctx
,
375 struct dcerpc_pipe
*p
,
376 struct test_spoolss_context
*ctx
,
377 const char *environment
)
380 struct spoolss_GetPrinterDriverDirectory r
;
395 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
398 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
404 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
405 int level
= levels
[i
].level
;
408 r
.in
.server
= levels
[i
].server
;
409 r
.in
.environment
= environment
;
413 r
.out
.needed
= &needed
;
415 torture_comment(tctx
, "Testing GetPrinterDriverDirectory level %u\n", r
.in
.level
);
417 status
= dcerpc_spoolss_GetPrinterDriverDirectory(p
, ctx
, &r
);
418 torture_assert_ntstatus_ok(tctx
, status
,
419 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
420 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
421 "GetPrinterDriverDirectory unexpected return code");
423 blob
= data_blob_talloc(ctx
, NULL
, needed
);
424 data_blob_clear(&blob
);
426 r
.in
.offered
= needed
;
428 status
= dcerpc_spoolss_GetPrinterDriverDirectory(p
, ctx
, &r
);
429 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
431 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrinterDriverDirectory failed");
433 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 2);
439 static bool test_EnumPrinterDrivers(struct torture_context
*tctx
,
440 struct dcerpc_pipe
*p
,
441 struct test_spoolss_context
*ctx
,
442 const char *architecture
)
445 struct spoolss_EnumPrinterDrivers r
;
446 uint16_t levels
[] = { 1, 2, 3, 4, 5, 6, 8 };
449 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
450 int level
= levels
[i
];
454 union spoolss_DriverInfo
*info
;
456 /* FIXME: gd, come back and fix "" as server, and handle
457 * priority of returned error codes in torture test and samba 3
460 r
.in
.server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
461 r
.in
.environment
= architecture
;
465 r
.out
.needed
= &needed
;
466 r
.out
.count
= &count
;
469 torture_comment(tctx
, "Testing EnumPrinterDrivers level %u (%s)\n", r
.in
.level
, r
.in
.environment
);
471 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, ctx
, &r
);
472 torture_assert_ntstatus_ok(tctx
, status
,
473 "dcerpc_spoolss_EnumPrinterDrivers failed");
474 if (W_ERROR_IS_OK(r
.out
.result
)) {
475 /* TODO: do some more checks here */
478 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
479 blob
= data_blob_talloc(ctx
, NULL
, needed
);
480 data_blob_clear(&blob
);
482 r
.in
.offered
= needed
;
484 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, ctx
, &r
);
485 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinterDrivers failed");
488 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDrivers failed");
490 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
492 ctx
->driver_count
[level
] = count
;
493 ctx
->drivers
[level
] = info
;
496 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
497 int level
= levels
[i
];
498 int old_level
= levels
[i
-1];
500 torture_assert_int_equal(tctx
, ctx
->driver_count
[level
], ctx
->driver_count
[old_level
],
501 "EnumPrinterDrivers invalid value");
504 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
505 int level
= levels
[i
];
507 for (j
=0;j
<ctx
->driver_count
[level
];j
++) {
508 union spoolss_DriverInfo
*cur
= &ctx
->drivers
[level
][j
];
509 union spoolss_DriverInfo
*ref
= &ctx
->drivers
[8][j
];
513 COMPARE_STRING(tctx
, cur
->info1
, ref
->info8
, driver_name
);
516 COMPARE_UINT32(tctx
, cur
->info2
, ref
->info8
, version
);
517 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, driver_name
);
518 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, architecture
);
519 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, driver_path
);
520 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, data_file
);
521 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, config_file
);
524 COMPARE_UINT32(tctx
, cur
->info3
, ref
->info8
, version
);
525 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, driver_name
);
526 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, architecture
);
527 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, driver_path
);
528 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, data_file
);
529 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, config_file
);
530 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, help_file
);
531 COMPARE_STRING_ARRAY(tctx
, cur
->info3
, ref
->info8
, dependent_files
);
532 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, monitor_name
);
533 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, default_datatype
);
536 COMPARE_UINT32(tctx
, cur
->info4
, ref
->info8
, version
);
537 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, driver_name
);
538 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, architecture
);
539 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, driver_path
);
540 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, data_file
);
541 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, config_file
);
542 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, help_file
);
543 COMPARE_STRING_ARRAY(tctx
, cur
->info4
, ref
->info8
, dependent_files
);
544 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, monitor_name
);
545 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, default_datatype
);
546 COMPARE_STRING_ARRAY(tctx
, cur
->info4
, ref
->info8
, previous_names
);
549 COMPARE_UINT32(tctx
, cur
->info5
, ref
->info8
, version
);
550 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, driver_name
);
551 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, architecture
);
552 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, driver_path
);
553 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, data_file
);
554 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, config_file
);
555 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
556 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
557 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
560 COMPARE_UINT32(tctx
, cur
->info6
, ref
->info8
, version
);
561 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, driver_name
);
562 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, architecture
);
563 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, driver_path
);
564 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, data_file
);
565 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, config_file
);
566 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, help_file
);
567 COMPARE_STRING_ARRAY(tctx
, cur
->info6
, ref
->info8
, dependent_files
);
568 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, monitor_name
);
569 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, default_datatype
);
570 COMPARE_STRING_ARRAY(tctx
, cur
->info6
, ref
->info8
, previous_names
);
571 COMPARE_NTTIME(tctx
, cur
->info6
, ref
->info8
, driver_date
);
572 COMPARE_UINT64(tctx
, cur
->info6
, ref
->info8
, driver_version
);
573 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, manufacturer_name
);
574 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, manufacturer_url
);
575 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, hardware_id
);
576 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, provider
);
579 /* level 8 is our reference, and it makes no sense to compare it to itself */
588 static bool test_EnumMonitors(struct torture_context
*tctx
,
589 struct dcerpc_pipe
*p
,
590 struct test_spoolss_context
*ctx
)
593 struct spoolss_EnumMonitors r
;
594 uint16_t levels
[] = { 1, 2 };
597 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
598 int level
= levels
[i
];
602 union spoolss_MonitorInfo
*info
;
604 r
.in
.servername
= "";
608 r
.out
.needed
= &needed
;
609 r
.out
.count
= &count
;
612 torture_comment(tctx
, "Testing EnumMonitors level %u\n", r
.in
.level
);
614 status
= dcerpc_spoolss_EnumMonitors(p
, ctx
, &r
);
615 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumMonitors failed");
616 if (W_ERROR_IS_OK(r
.out
.result
)) {
617 /* TODO: do some more checks here */
620 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
621 "EnumMonitors failed");
623 blob
= data_blob_talloc(ctx
, NULL
, needed
);
624 data_blob_clear(&blob
);
626 r
.in
.offered
= needed
;
628 status
= dcerpc_spoolss_EnumMonitors(p
, ctx
, &r
);
629 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumMonitors failed");
631 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumMonitors failed");
633 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
635 ctx
->monitor_count
[level
] = count
;
636 ctx
->monitors
[level
] = info
;
639 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
640 int level
= levels
[i
];
641 int old_level
= levels
[i
-1];
642 torture_assert_int_equal(tctx
, ctx
->monitor_count
[level
], ctx
->monitor_count
[old_level
],
643 "EnumMonitors invalid value");
646 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
647 int level
= levels
[i
];
648 for (j
=0;j
<ctx
->monitor_count
[level
];j
++) {
649 union spoolss_MonitorInfo
*cur
= &ctx
->monitors
[level
][j
];
650 union spoolss_MonitorInfo
*ref
= &ctx
->monitors
[2][j
];
653 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, monitor_name
);
656 /* level 2 is our reference, and it makes no sense to compare it to itself */
665 static bool test_EnumPrintProcessors(struct torture_context
*tctx
,
666 struct dcerpc_pipe
*p
,
667 struct test_spoolss_context
*ctx
,
668 const char *environment
)
671 struct spoolss_EnumPrintProcessors r
;
672 uint16_t levels
[] = { 1 };
675 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
676 int level
= levels
[i
];
680 union spoolss_PrintProcessorInfo
*info
;
682 r
.in
.servername
= "";
683 r
.in
.environment
= environment
;
687 r
.out
.needed
= &needed
;
688 r
.out
.count
= &count
;
691 torture_comment(tctx
, "Testing EnumPrintProcessors level %u\n", r
.in
.level
);
693 status
= dcerpc_spoolss_EnumPrintProcessors(p
, ctx
, &r
);
694 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcessors failed");
695 if (W_ERROR_IS_OK(r
.out
.result
)) {
696 /* TODO: do some more checks here */
699 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
700 "EnumPrintProcessors unexpected return code");
702 blob
= data_blob_talloc(ctx
, NULL
, needed
);
703 data_blob_clear(&blob
);
705 r
.in
.offered
= needed
;
707 status
= dcerpc_spoolss_EnumPrintProcessors(p
, ctx
, &r
);
708 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcessors failed");
710 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrintProcessors failed");
712 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
714 ctx
->print_processor_count
[level
] = count
;
715 ctx
->print_processors
[level
] = info
;
718 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
719 int level
= levels
[i
];
720 int old_level
= levels
[i
-1];
721 torture_assert_int_equal(tctx
, ctx
->print_processor_count
[level
], ctx
->print_processor_count
[old_level
],
722 "EnumPrintProcessors failed");
725 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
726 int level
= levels
[i
];
727 for (j
=0;j
<ctx
->print_processor_count
[level
];j
++) {
729 union spoolss_PrintProcessorInfo
*cur
= &ctx
->print_processors
[level
][j
];
730 union spoolss_PrintProcessorInfo
*ref
= &ctx
->print_processors
[1][j
];
734 /* level 1 is our reference, and it makes no sense to compare it to itself */
743 static bool test_EnumPrintProcDataTypes(struct torture_context
*tctx
,
744 struct dcerpc_pipe
*p
,
745 struct test_spoolss_context
*ctx
)
748 struct spoolss_EnumPrintProcDataTypes r
;
749 uint16_t levels
[] = { 1 };
752 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
753 int level
= levels
[i
];
757 union spoolss_PrintProcDataTypesInfo
*info
;
759 r
.in
.servername
= "";
760 r
.in
.print_processor_name
= "winprint";
764 r
.out
.needed
= &needed
;
765 r
.out
.count
= &count
;
768 torture_comment(tctx
, "Testing EnumPrintProcDataTypes level %u\n", r
.in
.level
);
770 status
= dcerpc_spoolss_EnumPrintProcDataTypes(p
, ctx
, &r
);
771 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcDataType failed");
772 if (W_ERROR_IS_OK(r
.out
.result
)) {
773 /* TODO: do some more checks here */
776 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
777 "EnumPrintProcDataTypes unexpected return code");
779 blob
= data_blob_talloc(ctx
, NULL
, needed
);
780 data_blob_clear(&blob
);
782 r
.in
.offered
= needed
;
784 status
= dcerpc_spoolss_EnumPrintProcDataTypes(p
, ctx
, &r
);
785 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
787 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrintProcDataTypes failed");
789 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
797 static bool test_EnumPrinters(struct torture_context
*tctx
,
798 struct dcerpc_pipe
*p
,
799 struct test_spoolss_context
*ctx
)
801 struct spoolss_EnumPrinters r
;
803 uint16_t levels
[] = { 0, 1, 2, 4, 5 };
806 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
807 int level
= levels
[i
];
811 union spoolss_PrinterInfo
*info
;
813 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
818 r
.out
.needed
= &needed
;
819 r
.out
.count
= &count
;
822 torture_comment(tctx
, "Testing EnumPrinters level %u\n", r
.in
.level
);
824 status
= dcerpc_spoolss_EnumPrinters(p
, ctx
, &r
);
825 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinters failed");
826 if (W_ERROR_IS_OK(r
.out
.result
)) {
827 /* TODO: do some more checks here */
830 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
831 "EnumPrinters unexpected return code");
833 blob
= data_blob_talloc(ctx
, NULL
, needed
);
834 data_blob_clear(&blob
);
836 r
.in
.offered
= needed
;
838 status
= dcerpc_spoolss_EnumPrinters(p
, ctx
, &r
);
839 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinters failed");
841 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
843 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
845 ctx
->printer_count
[level
] = count
;
846 ctx
->printers
[level
] = info
;
849 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
850 int level
= levels
[i
];
851 int old_level
= levels
[i
-1];
852 torture_assert_int_equal(tctx
, ctx
->printer_count
[level
], ctx
->printer_count
[old_level
],
853 "EnumPrinters invalid value");
856 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
857 int level
= levels
[i
];
858 for (j
=0;j
<ctx
->printer_count
[level
];j
++) {
859 union spoolss_PrinterInfo
*cur
= &ctx
->printers
[level
][j
];
860 union spoolss_PrinterInfo
*ref
= &ctx
->printers
[2][j
];
863 COMPARE_STRING(tctx
, cur
->info0
, ref
->info2
, printername
);
864 COMPARE_STRING(tctx
, cur
->info0
, ref
->info2
, servername
);
865 COMPARE_UINT32(tctx
, cur
->info0
, ref
->info2
, cjobs
);
866 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
867 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
868 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
869 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
870 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
871 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
872 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
873 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
874 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
875 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
876 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
877 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
878 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
879 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
880 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
881 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
882 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
883 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
884 COMPARE_UINT32(tctx
, cur
->info0
, ref
->info2
, status
);
885 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
886 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
887 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
888 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
889 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
890 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
891 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
894 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
895 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
896 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
897 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, comment
);
900 /* level 2 is our reference, and it makes no sense to compare it to itself */
903 COMPARE_STRING(tctx
, cur
->info4
, ref
->info2
, printername
);
904 COMPARE_STRING(tctx
, cur
->info4
, ref
->info2
, servername
);
905 COMPARE_UINT32(tctx
, cur
->info4
, ref
->info2
, attributes
);
908 COMPARE_STRING(tctx
, cur
->info5
, ref
->info2
, printername
);
909 COMPARE_STRING(tctx
, cur
->info5
, ref
->info2
, portname
);
910 COMPARE_UINT32(tctx
, cur
->info5
, ref
->info2
, attributes
);
911 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
912 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
919 * - verify that the port of a printer was in the list returned by EnumPorts
925 static bool test_GetPrinterDriver2(struct torture_context
*tctx
,
926 struct dcerpc_pipe
*p
,
927 struct policy_handle
*handle
,
928 const char *driver_name
,
929 const char *environment
);
931 bool test_GetPrinter_level(struct torture_context
*tctx
,
932 struct dcerpc_pipe
*p
,
933 struct policy_handle
*handle
,
935 union spoolss_PrinterInfo
*info
)
937 struct spoolss_GetPrinter r
;
940 r
.in
.handle
= handle
;
944 r
.out
.needed
= &needed
;
946 torture_comment(tctx
, "Testing GetPrinter level %u\n", r
.in
.level
);
948 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinter(p
, tctx
, &r
),
949 "GetPrinter failed");
951 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
952 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
953 data_blob_clear(&blob
);
955 r
.in
.offered
= needed
;
957 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinter(p
, tctx
, &r
),
958 "GetPrinter failed");
961 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrinter failed");
963 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
965 if (info
&& r
.out
.info
) {
973 static bool test_GetPrinter(struct torture_context
*tctx
,
974 struct dcerpc_pipe
*p
,
975 struct policy_handle
*handle
,
976 const char *environment
)
978 uint32_t levels
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
981 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
983 union spoolss_PrinterInfo info
;
987 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, handle
, levels
[i
], &info
),
988 "failed to call GetPrinter");
990 if ((levels
[i
] == 2) && info
.info2
.drivername
&& strlen(info
.info2
.drivername
)) {
992 test_GetPrinterDriver2(tctx
, p
, handle
, info
.info2
.drivername
, environment
),
993 "failed to call test_GetPrinterDriver2");
1000 static bool test_SetPrinter(struct torture_context
*tctx
,
1001 struct dcerpc_pipe
*p
,
1002 struct policy_handle
*handle
,
1003 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
1004 struct spoolss_DevmodeContainer
*devmode_ctr
,
1005 struct sec_desc_buf
*secdesc_ctr
,
1006 enum spoolss_PrinterControl command
)
1008 struct spoolss_SetPrinter r
;
1010 r
.in
.handle
= handle
;
1011 r
.in
.info_ctr
= info_ctr
;
1012 r
.in
.devmode_ctr
= devmode_ctr
;
1013 r
.in
.secdesc_ctr
= secdesc_ctr
;
1014 r
.in
.command
= command
;
1016 torture_comment(tctx
, "Testing SetPrinter level %d\n", r
.in
.info_ctr
->level
);
1018 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter(p
, tctx
, &r
),
1019 "failed to call SetPrinter");
1020 torture_assert_werr_ok(tctx
, r
.out
.result
,
1021 "failed to call SetPrinter");
1026 static bool test_SetPrinter_errors(struct torture_context
*tctx
,
1027 struct dcerpc_pipe
*p
,
1028 struct policy_handle
*handle
)
1030 struct spoolss_SetPrinter r
;
1031 uint16_t levels
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1034 struct spoolss_SetPrinterInfoCtr info_ctr
;
1035 struct spoolss_DevmodeContainer devmode_ctr
;
1036 struct sec_desc_buf secdesc_ctr
;
1039 info_ctr
.info
.info0
= NULL
;
1041 ZERO_STRUCT(devmode_ctr
);
1042 ZERO_STRUCT(secdesc_ctr
);
1044 r
.in
.handle
= handle
;
1045 r
.in
.info_ctr
= &info_ctr
;
1046 r
.in
.devmode_ctr
= &devmode_ctr
;
1047 r
.in
.secdesc_ctr
= &secdesc_ctr
;
1050 torture_comment(tctx
, "Testing SetPrinter all zero\n");
1052 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter(p
, tctx
, &r
),
1053 "failed to call SetPrinter");
1054 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
1055 "failed to call SetPrinter");
1058 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
1060 struct spoolss_SetPrinterInfo0 info0
;
1061 struct spoolss_SetPrinterInfo1 info1
;
1062 struct spoolss_SetPrinterInfo2 info2
;
1063 struct spoolss_SetPrinterInfo3 info3
;
1064 struct spoolss_SetPrinterInfo4 info4
;
1065 struct spoolss_SetPrinterInfo5 info5
;
1066 struct spoolss_SetPrinterInfo6 info6
;
1067 struct spoolss_SetPrinterInfo7 info7
;
1068 struct spoolss_SetPrinterInfo8 info8
;
1069 struct spoolss_SetPrinterInfo9 info9
;
1072 info_ctr
.level
= levels
[i
];
1073 switch (levels
[i
]) {
1076 info_ctr
.info
.info0
= &info0
;
1080 info_ctr
.info
.info1
= &info1
;
1084 info_ctr
.info
.info2
= &info2
;
1088 info_ctr
.info
.info3
= &info3
;
1092 info_ctr
.info
.info4
= &info4
;
1096 info_ctr
.info
.info5
= &info5
;
1100 info_ctr
.info
.info6
= &info6
;
1104 info_ctr
.info
.info7
= &info7
;
1108 info_ctr
.info
.info8
= &info8
;
1112 info_ctr
.info
.info9
= &info9
;
1116 torture_comment(tctx
, "Testing SetPrinter level %d, command %d\n",
1117 info_ctr
.level
, r
.in
.command
);
1119 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter(p
, tctx
, &r
),
1120 "failed to call SetPrinter");
1122 switch (r
.in
.command
) {
1123 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
: /* 0 */
1124 /* is ignored for all levels other then 0 */
1125 if (info_ctr
.level
> 0) {
1129 case SPOOLSS_PRINTER_CONTROL_PAUSE
: /* 1 */
1130 case SPOOLSS_PRINTER_CONTROL_RESUME
: /* 2 */
1131 case SPOOLSS_PRINTER_CONTROL_PURGE
: /* 3 */
1132 if (info_ctr
.level
> 0) {
1133 /* is invalid for all levels other then 0 */
1134 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PRINTER_COMMAND
,
1135 "unexpected error code returned");
1138 torture_assert_werr_ok(tctx
, r
.out
.result
,
1139 "failed to call SetPrinter with non 0 command");
1144 case SPOOLSS_PRINTER_CONTROL_SET_STATUS
: /* 4 */
1145 /* FIXME: gd needs further investigation */
1147 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PRINTER_COMMAND
,
1148 "unexpected error code returned");
1152 switch (info_ctr
.level
) {
1154 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
,
1155 "unexpected error code returned");
1158 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_PRINTER_DRIVER
,
1159 "unexpected error code returned");
1165 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
1166 "unexpected error code returned");
1169 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_NOT_SUPPORTED
,
1170 "unexpected error code returned");
1173 torture_assert_werr_ok(tctx
, r
.out
.result
,
1174 "failed to call SetPrinter");
1179 if (r
.in
.command
< 5) {
1187 static void clear_info2(struct spoolss_SetPrinterInfoCtr
*r
)
1189 if ((r
->level
== 2) && (r
->info
.info2
)) {
1190 r
->info
.info2
->secdesc_ptr
= 0;
1191 r
->info
.info2
->devmode_ptr
= 0;
1195 static bool test_PrinterInfo(struct torture_context
*tctx
,
1196 struct dcerpc_pipe
*p
,
1197 struct policy_handle
*handle
)
1200 struct spoolss_SetPrinter s
;
1201 struct spoolss_GetPrinter q
;
1202 struct spoolss_GetPrinter q0
;
1203 struct spoolss_SetPrinterInfoCtr info_ctr
;
1204 union spoolss_PrinterInfo info
;
1205 struct spoolss_DevmodeContainer devmode_ctr
;
1206 struct sec_desc_buf secdesc_ctr
;
1211 uint32_t status_list
[] = {
1212 /* these do not stick
1213 PRINTER_STATUS_PAUSED,
1214 PRINTER_STATUS_ERROR,
1215 PRINTER_STATUS_PENDING_DELETION, */
1216 PRINTER_STATUS_PAPER_JAM
,
1217 PRINTER_STATUS_PAPER_OUT
,
1218 PRINTER_STATUS_MANUAL_FEED
,
1219 PRINTER_STATUS_PAPER_PROBLEM
,
1220 PRINTER_STATUS_OFFLINE
,
1221 PRINTER_STATUS_IO_ACTIVE
,
1222 PRINTER_STATUS_BUSY
,
1223 PRINTER_STATUS_PRINTING
,
1224 PRINTER_STATUS_OUTPUT_BIN_FULL
,
1225 PRINTER_STATUS_NOT_AVAILABLE
,
1226 PRINTER_STATUS_WAITING
,
1227 PRINTER_STATUS_PROCESSING
,
1228 PRINTER_STATUS_INITIALIZING
,
1229 PRINTER_STATUS_WARMING_UP
,
1230 PRINTER_STATUS_TONER_LOW
,
1231 PRINTER_STATUS_NO_TONER
,
1232 PRINTER_STATUS_PAGE_PUNT
,
1233 PRINTER_STATUS_USER_INTERVENTION
,
1234 PRINTER_STATUS_OUT_OF_MEMORY
,
1235 PRINTER_STATUS_DOOR_OPEN
,
1236 PRINTER_STATUS_SERVER_UNKNOWN
,
1237 PRINTER_STATUS_POWER_SAVE
,
1238 /* these do not stick
1247 uint32_t default_attribute
= PRINTER_ATTRIBUTE_LOCAL
;
1248 uint32_t attribute_list
[] = {
1249 PRINTER_ATTRIBUTE_QUEUED
,
1250 /* fails with WERR_INVALID_DATATYPE:
1251 PRINTER_ATTRIBUTE_DIRECT, */
1253 PRINTER_ATTRIBUTE_DEFAULT, */
1254 PRINTER_ATTRIBUTE_SHARED
,
1256 PRINTER_ATTRIBUTE_NETWORK, */
1257 PRINTER_ATTRIBUTE_HIDDEN
,
1258 PRINTER_ATTRIBUTE_LOCAL
,
1259 PRINTER_ATTRIBUTE_ENABLE_DEVQ
,
1260 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
,
1261 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST
,
1262 PRINTER_ATTRIBUTE_WORK_OFFLINE
,
1264 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1265 /* fails with WERR_INVALID_DATATYPE:
1266 PRINTER_ATTRIBUTE_RAW_ONLY, */
1267 /* these do not stick
1268 PRINTER_ATTRIBUTE_PUBLISHED,
1269 PRINTER_ATTRIBUTE_FAX,
1270 PRINTER_ATTRIBUTE_TS,
1289 ZERO_STRUCT(devmode_ctr
);
1290 ZERO_STRUCT(secdesc_ctr
);
1292 s
.in
.handle
= handle
;
1294 s
.in
.info_ctr
= &info_ctr
;
1295 s
.in
.devmode_ctr
= &devmode_ctr
;
1296 s
.in
.secdesc_ctr
= &secdesc_ctr
;
1298 q
.in
.handle
= handle
;
1302 #define TESTGETCALL(call, r) \
1303 r.in.buffer = NULL; \
1305 r.out.needed = &needed; \
1306 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1307 if (!NT_STATUS_IS_OK(status)) { \
1308 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1309 r.in.level, nt_errstr(status), __location__); \
1313 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1314 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1315 data_blob_clear(&blob); \
1316 r.in.buffer = &blob; \
1317 r.in.offered = needed; \
1319 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1320 if (!NT_STATUS_IS_OK(status)) { \
1321 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1322 r.in.level, nt_errstr(status), __location__); \
1326 if (!W_ERROR_IS_OK(r.out.result)) { \
1327 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1328 r.in.level, win_errstr(r.out.result), __location__); \
1334 #define TESTSETCALL_EXP(call, r, err) \
1335 clear_info2(&info_ctr);\
1336 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1337 if (!NT_STATUS_IS_OK(status)) { \
1338 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1339 r.in.info_ctr->level, nt_errstr(status), __location__); \
1343 if (!W_ERROR_IS_OK(err)) { \
1344 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1345 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1346 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1351 if (!W_ERROR_IS_OK(r.out.result)) { \
1352 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1353 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1358 #define TESTSETCALL(call, r) \
1359 TESTSETCALL_EXP(call, r, WERR_OK)
1361 #define STRING_EQUAL(s1, s2, field) \
1362 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1363 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1364 #field, s2, __location__); \
1369 #define MEM_EQUAL(s1, s2, length, field) \
1370 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1371 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1372 #field, (const char *)s2, __location__); \
1377 #define INT_EQUAL(i1, i2, field) \
1379 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1380 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1385 #define SD_EQUAL(sd1, sd2, field) \
1386 if (!security_descriptor_equal(sd1, sd2)) { \
1387 torture_comment(tctx, "Failed to set %s (%s)\n", \
1388 #field, __location__); \
1393 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1394 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1395 q.in.level = lvl1; \
1396 TESTGETCALL(GetPrinter, q) \
1397 info_ctr.level = lvl1; \
1398 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1399 info_ctr.info.info ## lvl1->field1 = value;\
1400 TESTSETCALL_EXP(SetPrinter, s, err) \
1401 info_ctr.info.info ## lvl1->field1 = ""; \
1402 TESTGETCALL(GetPrinter, q) \
1403 info_ctr.info.info ## lvl1->field1 = value; \
1404 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1405 q.in.level = lvl2; \
1406 TESTGETCALL(GetPrinter, q) \
1407 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1408 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1411 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1412 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1415 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1416 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1417 q.in.level = lvl1; \
1418 TESTGETCALL(GetPrinter, q) \
1419 info_ctr.level = lvl1; \
1420 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1421 info_ctr.info.info ## lvl1->field1 = value; \
1422 TESTSETCALL(SetPrinter, s) \
1423 info_ctr.info.info ## lvl1->field1 = 0; \
1424 TESTGETCALL(GetPrinter, q) \
1425 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1426 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1427 q.in.level = lvl2; \
1428 TESTGETCALL(GetPrinter, q) \
1429 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1430 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1433 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1434 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1438 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1440 TEST_PRINTERINFO_STRING(2, comment
, 1, comment
, "xx2-1 comment");
1441 TEST_PRINTERINFO_STRING(2, comment
, 2, comment
, "xx2-2 comment");
1443 /* level 0 printername does not stick */
1444 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1445 TEST_PRINTERINFO_STRING(2, printername
, 1, name
, "xx2-1 printer");
1446 TEST_PRINTERINFO_STRING(2, printername
, 2, printername
, "xx2-2 printer");
1447 TEST_PRINTERINFO_STRING(2, printername
, 4, printername
, "xx2-4 printer");
1448 TEST_PRINTERINFO_STRING(2, printername
, 5, printername
, "xx2-5 printer");
1449 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1450 TEST_PRINTERINFO_STRING(4, printername
, 1, name
, "xx4-1 printer");
1451 TEST_PRINTERINFO_STRING(4, printername
, 2, printername
, "xx4-2 printer");
1452 TEST_PRINTERINFO_STRING(4, printername
, 4, printername
, "xx4-4 printer");
1453 TEST_PRINTERINFO_STRING(4, printername
, 5, printername
, "xx4-5 printer");
1454 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1455 TEST_PRINTERINFO_STRING(5, printername
, 1, name
, "xx5-1 printer");
1456 TEST_PRINTERINFO_STRING(5, printername
, 2, printername
, "xx5-2 printer");
1457 TEST_PRINTERINFO_STRING(5, printername
, 4, printername
, "xx5-4 printer");
1458 TEST_PRINTERINFO_STRING(5, printername
, 5, printername
, "xx5-5 printer");
1460 /* servername can be set but does not stick
1461 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1462 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1463 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1466 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1467 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname
, 2, portname
, "xx2-2 portname", WERR_UNKNOWN_PORT
);
1468 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname
, 5, portname
, "xx2-5 portname", WERR_UNKNOWN_PORT
);
1469 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname
, 2, portname
, "xx5-2 portname", WERR_UNKNOWN_PORT
);
1470 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname
, 5, portname
, "xx5-5 portname", WERR_UNKNOWN_PORT
);
1472 TEST_PRINTERINFO_STRING(2, sharename
, 2, sharename
, "xx2-2 sharename");
1473 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1474 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername
, 2, drivername
, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER
);
1475 TEST_PRINTERINFO_STRING(2, location
, 2, location
, "xx2-2 location");
1476 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1477 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile
, 2, sepfile
, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE
);
1478 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1479 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor
, 2, printprocessor
, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR
);
1480 TEST_PRINTERINFO_STRING(2, datatype
, 2, datatype
, "xx2-2 datatype");
1481 TEST_PRINTERINFO_STRING(2, parameters
, 2, parameters
, "xx2-2 parameters");
1483 for (i
=0; i
< ARRAY_SIZE(attribute_list
); i
++) {
1484 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1486 (attribute_list[i] | default_attribute)
1488 TEST_PRINTERINFO_INT_EXP(2, attributes
, 2, attributes
,
1490 (attribute_list
[i
] | default_attribute
)
1492 TEST_PRINTERINFO_INT_EXP(2, attributes
, 4, attributes
,
1494 (attribute_list
[i
] | default_attribute
)
1496 TEST_PRINTERINFO_INT_EXP(2, attributes
, 5, attributes
,
1498 (attribute_list
[i
] | default_attribute
)
1500 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1502 (attribute_list[i] | default_attribute)
1504 TEST_PRINTERINFO_INT_EXP(4, attributes
, 2, attributes
,
1506 (attribute_list
[i
] | default_attribute
)
1508 TEST_PRINTERINFO_INT_EXP(4, attributes
, 4, attributes
,
1510 (attribute_list
[i
] | default_attribute
)
1512 TEST_PRINTERINFO_INT_EXP(4, attributes
, 5, attributes
,
1514 (attribute_list
[i
] | default_attribute
)
1516 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1518 (attribute_list[i] | default_attribute)
1520 TEST_PRINTERINFO_INT_EXP(5, attributes
, 2, attributes
,
1522 (attribute_list
[i
] | default_attribute
)
1524 TEST_PRINTERINFO_INT_EXP(5, attributes
, 4, attributes
,
1526 (attribute_list
[i
] | default_attribute
)
1528 TEST_PRINTERINFO_INT_EXP(5, attributes
, 5, attributes
,
1530 (attribute_list
[i
] | default_attribute
)
1534 for (i
=0; i
< ARRAY_SIZE(status_list
); i
++) {
1535 /* level 2 sets do not stick
1536 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1537 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1538 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1539 TEST_PRINTERINFO_INT(6, status
, 0, status
, status_list
[i
]);
1540 TEST_PRINTERINFO_INT(6, status
, 2, status
, status_list
[i
]);
1541 TEST_PRINTERINFO_INT(6, status
, 6, status
, status_list
[i
]);
1544 /* priorities need to be between 0 and 99
1545 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1546 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 0);
1547 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 1);
1548 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 99);
1549 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1550 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 0);
1551 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 1);
1552 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 99);
1553 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1555 TEST_PRINTERINFO_INT(2, starttime
, 2, starttime
, __LINE__
);
1556 TEST_PRINTERINFO_INT(2, untiltime
, 2, untiltime
, __LINE__
);
1559 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1560 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1563 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1564 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1566 /* FIXME: gd also test devmode and secdesc behavior */
1569 /* verify composition of level 1 description field */
1570 const char *description
;
1574 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1576 description
= talloc_strdup(tctx
, q0
.out
.info
->info1
.description
);
1579 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1581 tmp
= talloc_asprintf(tctx
, "%s,%s,%s",
1582 q0
.out
.info
->info2
.printername
,
1583 q0
.out
.info
->info2
.drivername
,
1584 q0
.out
.info
->info2
.location
);
1586 do { STRING_EQUAL(description
, tmp
, "description")} while (0);
1592 #define torture_assert_sid_equal(torture_ctx,got,expected,cmt)\
1593 do { struct dom_sid *__got = (got), *__expected = (expected); \
1594 if (!dom_sid_equal(__got, __expected)) { \
1595 torture_result(torture_ctx, TORTURE_FAIL, \
1596 __location__": "#got" was %s, expected %s: %s", \
1597 dom_sid_string(torture_ctx, __got), dom_sid_string(torture_ctx, __expected), cmt); \
1602 static bool test_security_descriptor_equal(struct torture_context
*tctx
,
1603 const struct security_descriptor
*sd1
,
1604 const struct security_descriptor
*sd2
)
1611 torture_comment(tctx
, "%s\n", __location__
);
1615 torture_assert_int_equal(tctx
, sd1
->revision
, sd2
->revision
, "revision mismatch");
1616 torture_assert_int_equal(tctx
, sd1
->type
, sd2
->type
, "type mismatch");
1618 torture_assert_sid_equal(tctx
, sd1
->owner_sid
, sd2
->owner_sid
, "owner mismatch");
1619 torture_assert_sid_equal(tctx
, sd1
->group_sid
, sd2
->group_sid
, "group mismatch");
1621 if (!security_acl_equal(sd1
->sacl
, sd2
->sacl
)) {
1622 torture_comment(tctx
, "%s: sacl mismatch\n", __location__
);
1623 NDR_PRINT_DEBUG(security_acl
, sd1
->sacl
);
1624 NDR_PRINT_DEBUG(security_acl
, sd2
->sacl
);
1627 if (!security_acl_equal(sd1
->dacl
, sd2
->dacl
)) {
1628 torture_comment(tctx
, "%s: dacl mismatch\n", __location__
);
1629 NDR_PRINT_DEBUG(security_acl
, sd1
->dacl
);
1630 NDR_PRINT_DEBUG(security_acl
, sd2
->dacl
);
1637 static bool test_sd_set_level(struct torture_context
*tctx
,
1638 struct dcerpc_pipe
*p
,
1639 struct policy_handle
*handle
,
1641 struct security_descriptor
*sd
)
1643 struct spoolss_SetPrinterInfoCtr info_ctr
;
1644 struct spoolss_DevmodeContainer devmode_ctr
;
1645 struct sec_desc_buf secdesc_ctr
;
1646 union spoolss_SetPrinterInfo sinfo
;
1648 ZERO_STRUCT(devmode_ctr
);
1649 ZERO_STRUCT(secdesc_ctr
);
1653 union spoolss_PrinterInfo info
;
1654 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, handle
, 2, &info
), "");
1655 torture_assert(tctx
, PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
1658 info_ctr
.info
= sinfo
;
1663 struct spoolss_SetPrinterInfo3 info3
;
1665 info3
.sec_desc_ptr
= 0;
1668 info_ctr
.info
.info3
= &info3
;
1676 secdesc_ctr
.sd
= sd
;
1678 torture_assert(tctx
,
1679 test_SetPrinter(tctx
, p
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0), "");
1684 static bool test_PrinterInfo_SDs(struct torture_context
*tctx
,
1685 struct dcerpc_pipe
*p
,
1686 struct policy_handle
*handle
)
1688 union spoolss_PrinterInfo info
;
1689 struct security_descriptor
*sd1
, *sd2
;
1692 /* just compare level 2 and level 3 */
1694 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, handle
, 2, &info
), "");
1696 sd1
= info
.info2
.secdesc
;
1698 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, handle
, 3, &info
), "");
1700 sd2
= info
.info3
.secdesc
;
1702 torture_assert(tctx
, test_security_descriptor_equal(tctx
, sd1
, sd2
),
1703 "SD level 2 != SD level 3");
1706 /* query level 2, set level 2, query level 2 */
1708 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, handle
, 2, &info
), "");
1710 sd1
= info
.info2
.secdesc
;
1712 torture_assert(tctx
, test_sd_set_level(tctx
, p
, handle
, 2, sd1
), "");
1714 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, handle
, 2, &info
), "");
1716 sd2
= info
.info2
.secdesc
;
1717 if (sd1
->type
& SEC_DESC_DACL_DEFAULTED
) {
1718 torture_comment(tctx
, "removing SEC_DESC_DACL_DEFAULTED\n");
1719 sd1
->type
&= ~SEC_DESC_DACL_DEFAULTED
;
1722 torture_assert(tctx
, test_security_descriptor_equal(tctx
, sd1
, sd2
),
1723 "SD level 2 != SD level 2 after SD has been set via level 2");
1726 /* query level 2, set level 3, query level 2 */
1728 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, handle
, 2, &info
), "");
1730 sd1
= info
.info2
.secdesc
;
1732 torture_assert(tctx
, test_sd_set_level(tctx
, p
, handle
, 3, sd1
), "");
1734 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, handle
, 2, &info
), "");
1736 sd2
= info
.info2
.secdesc
;
1738 torture_assert(tctx
, test_security_descriptor_equal(tctx
, sd1
, sd2
),
1739 "SD level 2 != SD level 2 after SD has been set via level 3");
1741 /* set modified sd level 3, query level 2 */
1743 for (i
=0; i
< 93; i
++) {
1744 struct security_ace a
;
1745 const char *sid_string
= talloc_asprintf(tctx
, "S-1-5-32-9999%i", i
);
1746 a
.type
= SEC_ACE_TYPE_ACCESS_ALLOWED
;
1748 a
.size
= 0; /* autogenerated */
1750 a
.trustee
= *dom_sid_parse_talloc(tctx
, sid_string
);
1751 torture_assert_ntstatus_ok(tctx
, security_descriptor_dacl_add(sd1
, &a
), "");
1754 torture_assert(tctx
, test_sd_set_level(tctx
, p
, handle
, 3, sd1
), "");
1756 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, handle
, 2, &info
), "");
1757 sd2
= info
.info2
.secdesc
;
1759 if (sd1
->type
& SEC_DESC_DACL_DEFAULTED
) {
1760 torture_comment(tctx
, "removing SEC_DESC_DACL_DEFAULTED\n");
1761 sd1
->type
&= ~SEC_DESC_DACL_DEFAULTED
;
1764 torture_assert(tctx
, test_security_descriptor_equal(tctx
, sd1
, sd2
),
1765 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1772 * wrapper call that saves original sd, runs tests, and restores sd
1775 static bool test_PrinterInfo_SD(struct torture_context
*tctx
,
1776 struct dcerpc_pipe
*p
,
1777 struct policy_handle
*handle
)
1779 union spoolss_PrinterInfo info
;
1780 struct security_descriptor
*sd
;
1783 torture_comment(tctx
, "\nTesting Printer Security Descriptors\n");
1785 /* save original sd */
1787 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, handle
, 2, &info
),
1788 "failed to get initial security descriptor");
1790 sd
= security_descriptor_copy(tctx
, info
.info2
.secdesc
);
1794 ret
= test_PrinterInfo_SDs(tctx
, p
, handle
);
1796 /* restore original sd */
1798 torture_assert(tctx
, test_sd_set_level(tctx
, p
, handle
, 3, sd
),
1799 "failed to restore initial security descriptor");
1801 torture_comment(tctx
, "Printer Security Descriptors test %s\n",
1802 ret
? "succeeded" : "failed");
1808 static bool test_devmode_set_level(struct torture_context
*tctx
,
1809 struct dcerpc_pipe
*p
,
1810 struct policy_handle
*handle
,
1812 struct spoolss_DeviceMode
*devmode
)
1814 struct spoolss_SetPrinterInfoCtr info_ctr
;
1815 struct spoolss_DevmodeContainer devmode_ctr
;
1816 struct sec_desc_buf secdesc_ctr
;
1817 union spoolss_SetPrinterInfo sinfo
;
1819 ZERO_STRUCT(devmode_ctr
);
1820 ZERO_STRUCT(secdesc_ctr
);
1824 union spoolss_PrinterInfo info
;
1825 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, handle
, 2, &info
), "");
1826 torture_assert(tctx
, PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
1829 info_ctr
.info
= sinfo
;
1834 struct spoolss_SetPrinterInfo8 info8
;
1836 info8
.devmode_ptr
= 0;
1839 info_ctr
.info
.info8
= &info8
;
1847 devmode_ctr
.devmode
= devmode
;
1849 torture_assert(tctx
,
1850 test_SetPrinter(tctx
, p
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0), "");
1856 static bool test_devicemode_equal(struct torture_context
*tctx
,
1857 const struct spoolss_DeviceMode
*d1
,
1858 const struct spoolss_DeviceMode
*d2
)
1865 torture_comment(tctx
, "%s\n", __location__
);
1868 torture_assert_str_equal(tctx
, d1
->devicename
, d2
->devicename
, "devicename mismatch");
1869 torture_assert_int_equal(tctx
, d1
->specversion
, d2
->specversion
, "specversion mismatch");
1870 torture_assert_int_equal(tctx
, d1
->driverversion
, d2
->driverversion
, "driverversion mismatch");
1871 torture_assert_int_equal(tctx
, d1
->size
, d2
->size
, "size mismatch");
1872 torture_assert_int_equal(tctx
, d1
->__driverextra_length
, d2
->__driverextra_length
, "__driverextra_length mismatch");
1873 torture_assert_int_equal(tctx
, d1
->fields
, d2
->fields
, "fields mismatch");
1874 torture_assert_int_equal(tctx
, d1
->orientation
, d2
->orientation
, "orientation mismatch");
1875 torture_assert_int_equal(tctx
, d1
->papersize
, d2
->papersize
, "papersize mismatch");
1876 torture_assert_int_equal(tctx
, d1
->paperlength
, d2
->paperlength
, "paperlength mismatch");
1877 torture_assert_int_equal(tctx
, d1
->paperwidth
, d2
->paperwidth
, "paperwidth mismatch");
1878 torture_assert_int_equal(tctx
, d1
->scale
, d2
->scale
, "scale mismatch");
1879 torture_assert_int_equal(tctx
, d1
->copies
, d2
->copies
, "copies mismatch");
1880 torture_assert_int_equal(tctx
, d1
->defaultsource
, d2
->defaultsource
, "defaultsource mismatch");
1881 torture_assert_int_equal(tctx
, d1
->printquality
, d2
->printquality
, "printquality mismatch");
1882 torture_assert_int_equal(tctx
, d1
->color
, d2
->color
, "color mismatch");
1883 torture_assert_int_equal(tctx
, d1
->duplex
, d2
->duplex
, "duplex mismatch");
1884 torture_assert_int_equal(tctx
, d1
->yresolution
, d2
->yresolution
, "yresolution mismatch");
1885 torture_assert_int_equal(tctx
, d1
->ttoption
, d2
->ttoption
, "ttoption mismatch");
1886 torture_assert_int_equal(tctx
, d1
->collate
, d2
->collate
, "collate mismatch");
1887 torture_assert_str_equal(tctx
, d1
->formname
, d2
->formname
, "formname mismatch");
1888 torture_assert_int_equal(tctx
, d1
->logpixels
, d2
->logpixels
, "logpixels mismatch");
1889 torture_assert_int_equal(tctx
, d1
->bitsperpel
, d2
->bitsperpel
, "bitsperpel mismatch");
1890 torture_assert_int_equal(tctx
, d1
->pelswidth
, d2
->pelswidth
, "pelswidth mismatch");
1891 torture_assert_int_equal(tctx
, d1
->pelsheight
, d2
->pelsheight
, "pelsheight mismatch");
1892 torture_assert_int_equal(tctx
, d1
->displayflags
, d2
->displayflags
, "displayflags mismatch");
1893 torture_assert_int_equal(tctx
, d1
->displayfrequency
, d2
->displayfrequency
, "displayfrequency mismatch");
1894 torture_assert_int_equal(tctx
, d1
->icmmethod
, d2
->icmmethod
, "icmmethod mismatch");
1895 torture_assert_int_equal(tctx
, d1
->icmintent
, d2
->icmintent
, "icmintent mismatch");
1896 torture_assert_int_equal(tctx
, d1
->mediatype
, d2
->mediatype
, "mediatype mismatch");
1897 torture_assert_int_equal(tctx
, d1
->dithertype
, d2
->dithertype
, "dithertype mismatch");
1898 torture_assert_int_equal(tctx
, d1
->reserved1
, d2
->reserved1
, "reserved1 mismatch");
1899 torture_assert_int_equal(tctx
, d1
->reserved2
, d2
->reserved2
, "reserved2 mismatch");
1900 torture_assert_int_equal(tctx
, d1
->panningwidth
, d2
->panningwidth
, "panningwidth mismatch");
1901 torture_assert_int_equal(tctx
, d1
->panningheight
, d2
->panningheight
, "panningheight mismatch");
1902 torture_assert_data_blob_equal(tctx
, d1
->driverextra_data
, d2
->driverextra_data
, "driverextra_data mismatch");
1907 static bool test_devicemode_full(struct torture_context
*tctx
,
1908 struct dcerpc_pipe
*p
,
1909 struct policy_handle
*handle
)
1911 struct spoolss_SetPrinter s
;
1912 struct spoolss_GetPrinter q
;
1913 struct spoolss_GetPrinter q0
;
1914 struct spoolss_SetPrinterInfoCtr info_ctr
;
1915 struct spoolss_SetPrinterInfo8 info8
;
1916 union spoolss_PrinterInfo info
;
1917 struct spoolss_DevmodeContainer devmode_ctr
;
1918 struct sec_desc_buf secdesc_ctr
;
1923 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1924 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1925 q.in.level = lvl1; \
1926 TESTGETCALL(GetPrinter, q) \
1927 info_ctr.level = lvl1; \
1929 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1930 } else if (lvl1 == 8) {\
1931 info_ctr.info.info ## lvl1 = &info8; \
1933 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
1934 devmode_ctr.devmode->field1 = value; \
1935 TESTSETCALL(SetPrinter, s) \
1936 TESTGETCALL(GetPrinter, q) \
1937 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
1938 q.in.level = lvl2; \
1939 TESTGETCALL(GetPrinter, q) \
1940 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
1943 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
1944 TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1947 ZERO_STRUCT(devmode_ctr
);
1948 ZERO_STRUCT(secdesc_ctr
);
1951 s
.in
.handle
= handle
;
1953 s
.in
.info_ctr
= &info_ctr
;
1954 s
.in
.devmode_ctr
= &devmode_ctr
;
1955 s
.in
.secdesc_ctr
= &secdesc_ctr
;
1957 q
.in
.handle
= handle
;
1962 const char *devicename
;/* [charset(UTF16)] */
1963 enum spoolss_DeviceModeSpecVersion specversion
;
1964 uint16_t driverversion
;
1966 uint16_t __driverextra_length
;/* [value(r->driverextra_data.length)] */
1970 TEST_DEVMODE_INT(8, orientation
, 8, orientation
, __LINE__
);
1971 TEST_DEVMODE_INT(8, papersize
, 8, papersize
, __LINE__
);
1972 TEST_DEVMODE_INT(8, paperlength
, 8, paperlength
, __LINE__
);
1973 TEST_DEVMODE_INT(8, paperwidth
, 8, paperwidth
, __LINE__
);
1974 TEST_DEVMODE_INT(8, scale
, 8, scale
, __LINE__
);
1975 TEST_DEVMODE_INT(8, copies
, 8, copies
, __LINE__
);
1976 TEST_DEVMODE_INT(8, defaultsource
, 8, defaultsource
, __LINE__
);
1977 TEST_DEVMODE_INT(8, printquality
, 8, printquality
, __LINE__
);
1978 TEST_DEVMODE_INT(8, color
, 8, color
, __LINE__
);
1979 TEST_DEVMODE_INT(8, duplex
, 8, duplex
, __LINE__
);
1980 TEST_DEVMODE_INT(8, yresolution
, 8, yresolution
, __LINE__
);
1981 TEST_DEVMODE_INT(8, ttoption
, 8, ttoption
, __LINE__
);
1982 TEST_DEVMODE_INT(8, collate
, 8, collate
, __LINE__
);
1984 const char *formname
;/* [charset(UTF16)] */
1986 TEST_DEVMODE_INT(8, logpixels
, 8, logpixels
, __LINE__
);
1987 TEST_DEVMODE_INT(8, bitsperpel
, 8, bitsperpel
, __LINE__
);
1988 TEST_DEVMODE_INT(8, pelswidth
, 8, pelswidth
, __LINE__
);
1989 TEST_DEVMODE_INT(8, pelsheight
, 8, pelsheight
, __LINE__
);
1990 TEST_DEVMODE_INT(8, displayflags
, 8, displayflags
, __LINE__
);
1991 TEST_DEVMODE_INT(8, displayfrequency
, 8, displayfrequency
, __LINE__
);
1992 TEST_DEVMODE_INT(8, icmmethod
, 8, icmmethod
, __LINE__
);
1993 TEST_DEVMODE_INT(8, icmintent
, 8, icmintent
, __LINE__
);
1994 TEST_DEVMODE_INT(8, mediatype
, 8, mediatype
, __LINE__
);
1995 TEST_DEVMODE_INT(8, dithertype
, 8, dithertype
, __LINE__
);
1996 TEST_DEVMODE_INT(8, reserved1
, 8, reserved1
, __LINE__
);
1997 TEST_DEVMODE_INT(8, reserved2
, 8, reserved2
, __LINE__
);
1998 TEST_DEVMODE_INT(8, panningwidth
, 8, panningwidth
, __LINE__
);
1999 TEST_DEVMODE_INT(8, panningheight
, 8, panningheight
, __LINE__
);
2004 static bool call_OpenPrinterEx(struct torture_context
*tctx
,
2005 struct dcerpc_pipe
*p
,
2007 struct spoolss_DeviceMode
*devmode
,
2008 struct policy_handle
*handle
);
2010 static bool test_ClosePrinter(struct torture_context
*tctx
,
2011 struct dcerpc_pipe
*p
,
2012 struct policy_handle
*handle
);
2014 static bool test_PrinterInfo_DevModes(struct torture_context
*tctx
,
2015 struct dcerpc_pipe
*p
,
2016 struct policy_handle
*handle
,
2019 union spoolss_PrinterInfo info
;
2020 struct spoolss_DeviceMode
*devmode
;
2021 struct spoolss_DeviceMode
*devmode2
;
2022 struct policy_handle handle_devmode
;
2024 /* simply compare level8 and level2 devmode */
2026 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, handle
, 8, &info
), "");
2028 devmode
= info
.info8
.devmode
;
2030 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, handle
, 2, &info
), "");
2032 devmode2
= info
.info2
.devmode
;
2034 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2035 "DM level 8 != DM level 2");
2038 /* set devicemode level 8 and see if it persists */
2040 devmode
->copies
= 93;
2041 devmode
->formname
= talloc_strdup(tctx
, "Legal");
2043 torture_assert(tctx
, test_devmode_set_level(tctx
, p
, handle
, 8, devmode
), "");
2045 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, handle
, 8, &info
), "");
2047 devmode2
= info
.info8
.devmode
;
2049 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2050 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2052 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, handle
, 2, &info
), "");
2054 devmode2
= info
.info2
.devmode
;
2056 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2057 "modified DM level 8 != DM level 2");
2060 /* set devicemode level 2 and see if it persists */
2062 devmode
->copies
= 39;
2063 devmode
->formname
= talloc_strdup(tctx
, "Executive");
2065 torture_assert(tctx
, test_devmode_set_level(tctx
, p
, handle
, 2, devmode
), "");
2067 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, handle
, 8, &info
), "");
2069 devmode2
= info
.info8
.devmode
;
2071 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2072 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2074 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, handle
, 2, &info
), "");
2076 devmode2
= info
.info2
.devmode
;
2078 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2079 "modified DM level 8 != DM level 2");
2082 /* check every single bit in public part of devicemode */
2084 torture_assert(tctx
, test_devicemode_full(tctx
, p
, handle
),
2085 "failed to set every single devicemode component");
2088 /* change formname upon open and see if it persists in getprinter calls */
2090 devmode
->formname
= talloc_strdup(tctx
, "A4");
2091 devmode
->copies
= 42;
2093 torture_assert(tctx
, call_OpenPrinterEx(tctx
, p
, name
, devmode
, &handle_devmode
),
2094 "failed to open printer handle");
2096 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, &handle_devmode
, 8, &info
), "");
2098 devmode2
= info
.info8
.devmode
;
2100 if (strequal(devmode
->devicename
, devmode2
->devicename
)) {
2101 torture_warning(tctx
, "devicenames are the same\n");
2103 torture_comment(tctx
, "devicename passed in for open: %s\n", devmode
->devicename
);
2104 torture_comment(tctx
, "devicename after level 8 get: %s\n", devmode2
->devicename
);
2107 if (strequal(devmode
->formname
, devmode2
->formname
)) {
2108 torture_warning(tctx
, "formname are the same\n");
2110 torture_comment(tctx
, "formname passed in for open: %s\n", devmode
->formname
);
2111 torture_comment(tctx
, "formname after level 8 get: %s\n", devmode2
->formname
);
2114 if (devmode
->copies
== devmode2
->copies
) {
2115 torture_warning(tctx
, "copies are the same\n");
2117 torture_comment(tctx
, "copies passed in for open: %d\n", devmode
->copies
);
2118 torture_comment(tctx
, "copies after level 8 get: %d\n", devmode2
->copies
);
2121 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, &handle_devmode
, 2, &info
), "");
2123 devmode2
= info
.info2
.devmode
;
2125 if (strequal(devmode
->devicename
, devmode2
->devicename
)) {
2126 torture_warning(tctx
, "devicenames are the same\n");
2128 torture_comment(tctx
, "devicename passed in for open: %s\n", devmode
->devicename
);
2129 torture_comment(tctx
, "devicename after level 2 get: %s\n", devmode2
->devicename
);
2132 if (strequal(devmode
->formname
, devmode2
->formname
)) {
2133 torture_warning(tctx
, "formname is the same\n");
2135 torture_comment(tctx
, "formname passed in for open: %s\n", devmode
->formname
);
2136 torture_comment(tctx
, "formname after level 2 get: %s\n", devmode2
->formname
);
2139 if (devmode
->copies
== devmode2
->copies
) {
2140 torture_warning(tctx
, "copies are the same\n");
2142 torture_comment(tctx
, "copies passed in for open: %d\n", devmode
->copies
);
2143 torture_comment(tctx
, "copies after level 2 get: %d\n", devmode2
->copies
);
2146 test_ClosePrinter(tctx
, p
, &handle_devmode
);
2152 * wrapper call that saves original devmode, runs tests, and restores devmode
2155 static bool test_PrinterInfo_DevMode(struct torture_context
*tctx
,
2156 struct dcerpc_pipe
*p
,
2157 struct policy_handle
*handle
,
2160 union spoolss_PrinterInfo info
;
2161 struct spoolss_DeviceMode
*devmode
;
2164 torture_comment(tctx
, "\nTesting Printer Devicemodes\n");
2166 /* save original devmode */
2168 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, handle
, 8, &info
),
2169 "failed to get initial global devicemode");
2171 devmode
= info
.info8
.devmode
;
2175 ret
= test_PrinterInfo_DevModes(tctx
, p
, handle
, name
);
2177 /* restore original devmode */
2179 torture_assert(tctx
, test_devmode_set_level(tctx
, p
, handle
, 8, devmode
),
2180 "failed to restore initial global device mode");
2182 torture_comment(tctx
, "Printer Devicemodes test %s\n",
2183 ret
? "succeeded" : "failed");
2189 static bool test_ClosePrinter(struct torture_context
*tctx
,
2190 struct dcerpc_pipe
*p
,
2191 struct policy_handle
*handle
)
2194 struct spoolss_ClosePrinter r
;
2196 r
.in
.handle
= handle
;
2197 r
.out
.handle
= handle
;
2199 torture_comment(tctx
, "Testing ClosePrinter\n");
2201 status
= dcerpc_spoolss_ClosePrinter(p
, tctx
, &r
);
2202 torture_assert_ntstatus_ok(tctx
, status
, "ClosePrinter failed");
2203 torture_assert_werr_ok(tctx
, r
.out
.result
, "ClosePrinter failed");
2208 static bool test_GetForm(struct torture_context
*tctx
,
2209 struct dcerpc_pipe
*p
,
2210 struct policy_handle
*handle
,
2211 const char *form_name
,
2215 struct spoolss_GetForm r
;
2218 r
.in
.handle
= handle
;
2219 r
.in
.form_name
= form_name
;
2223 r
.out
.needed
= &needed
;
2225 torture_comment(tctx
, "Testing GetForm level %d\n", r
.in
.level
);
2227 status
= dcerpc_spoolss_GetForm(p
, tctx
, &r
);
2228 torture_assert_ntstatus_ok(tctx
, status
, "GetForm failed");
2230 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2231 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2232 data_blob_clear(&blob
);
2233 r
.in
.buffer
= &blob
;
2234 r
.in
.offered
= needed
;
2235 status
= dcerpc_spoolss_GetForm(p
, tctx
, &r
);
2236 torture_assert_ntstatus_ok(tctx
, status
, "GetForm failed");
2238 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetForm failed");
2240 torture_assert(tctx
, r
.out
.info
, "No form info returned");
2243 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetForm failed");
2245 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
2250 static bool test_EnumForms(struct torture_context
*tctx
,
2251 struct dcerpc_pipe
*p
,
2252 struct policy_handle
*handle
, bool print_server
)
2255 struct spoolss_EnumForms r
;
2259 uint32_t levels
[] = { 1, 2 };
2262 for (i
=0; i
<ARRAY_SIZE(levels
); i
++) {
2264 union spoolss_FormInfo
*info
;
2266 r
.in
.handle
= handle
;
2267 r
.in
.level
= levels
[i
];
2270 r
.out
.needed
= &needed
;
2271 r
.out
.count
= &count
;
2274 torture_comment(tctx
, "Testing EnumForms level %d\n", levels
[i
]);
2276 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &r
);
2277 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
2279 if ((r
.in
.level
== 2) && (W_ERROR_EQUAL(r
.out
.result
, WERR_UNKNOWN_LEVEL
))) {
2283 if (print_server
&& W_ERROR_EQUAL(r
.out
.result
, WERR_BADFID
))
2284 torture_fail(tctx
, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2286 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2288 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2289 data_blob_clear(&blob
);
2290 r
.in
.buffer
= &blob
;
2291 r
.in
.offered
= needed
;
2293 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &r
);
2295 torture_assert(tctx
, info
, "No forms returned");
2297 for (j
= 0; j
< count
; j
++) {
2299 ret
&= test_GetForm(tctx
, p
, handle
, info
[j
].info1
.form_name
, levels
[i
]);
2303 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
2305 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumForms failed");
2307 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
2313 static bool test_DeleteForm(struct torture_context
*tctx
,
2314 struct dcerpc_pipe
*p
,
2315 struct policy_handle
*handle
,
2316 const char *form_name
)
2319 struct spoolss_DeleteForm r
;
2321 r
.in
.handle
= handle
;
2322 r
.in
.form_name
= form_name
;
2324 status
= dcerpc_spoolss_DeleteForm(p
, tctx
, &r
);
2326 torture_assert_ntstatus_ok(tctx
, status
, "DeleteForm failed");
2328 torture_assert_werr_ok(tctx
, r
.out
.result
, "DeleteForm failed");
2333 static bool test_AddForm(struct torture_context
*tctx
,
2334 struct dcerpc_pipe
*p
,
2335 struct policy_handle
*handle
, bool print_server
)
2337 struct spoolss_AddForm r
;
2338 struct spoolss_AddFormInfo1 addform
;
2339 const char *form_name
= "testform3";
2343 r
.in
.handle
= handle
;
2345 r
.in
.info
.info1
= &addform
;
2346 addform
.flags
= SPOOLSS_FORM_USER
;
2347 addform
.form_name
= form_name
;
2348 addform
.size
.width
= 50;
2349 addform
.size
.height
= 25;
2350 addform
.area
.left
= 5;
2351 addform
.area
.top
= 10;
2352 addform
.area
.right
= 45;
2353 addform
.area
.bottom
= 15;
2355 status
= dcerpc_spoolss_AddForm(p
, tctx
, &r
);
2357 torture_assert_ntstatus_ok(tctx
, status
, "AddForm failed");
2359 torture_assert_werr_ok(tctx
, r
.out
.result
, "AddForm failed");
2361 if (!print_server
) ret
&= test_GetForm(tctx
, p
, handle
, form_name
, 1);
2364 struct spoolss_SetForm sf
;
2365 struct spoolss_AddFormInfo1 setform
;
2367 sf
.in
.handle
= handle
;
2368 sf
.in
.form_name
= form_name
;
2370 sf
.in
.info
.info1
= &setform
;
2371 setform
.flags
= addform
.flags
;
2372 setform
.form_name
= addform
.form_name
;
2373 setform
.size
= addform
.size
;
2374 setform
.area
= addform
.area
;
2376 setform
.size
.width
= 1234;
2378 status
= dcerpc_spoolss_SetForm(p
, tctx
, &sf
);
2380 torture_assert_ntstatus_ok(tctx
, status
, "SetForm failed");
2382 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetForm failed");
2385 if (!print_server
) ret
&= test_GetForm(tctx
, p
, handle
, form_name
, 1);
2388 struct spoolss_EnumForms e
;
2389 union spoolss_FormInfo
*info
;
2394 e
.in
.handle
= handle
;
2398 e
.out
.needed
= &needed
;
2399 e
.out
.count
= &count
;
2402 torture_comment(tctx
, "Testing EnumForms level 1\n");
2404 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &e
);
2405 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
2407 if (print_server
&& W_ERROR_EQUAL(e
.out
.result
, WERR_BADFID
))
2408 torture_fail(tctx
, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2410 if (W_ERROR_EQUAL(e
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2412 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2413 data_blob_clear(&blob
);
2414 e
.in
.buffer
= &blob
;
2415 e
.in
.offered
= needed
;
2417 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &e
);
2419 torture_assert(tctx
, info
, "No forms returned");
2421 for (j
= 0; j
< count
; j
++) {
2422 if (strequal(form_name
, info
[j
].info1
.form_name
)) {
2428 torture_assert(tctx
, found
, "Newly added form not found in enum call");
2431 if (!test_DeleteForm(tctx
, p
, handle
, form_name
)) {
2438 static bool test_EnumPorts_old(struct torture_context
*tctx
,
2439 struct dcerpc_pipe
*p
)
2442 struct spoolss_EnumPorts r
;
2445 union spoolss_PortInfo
*info
;
2447 r
.in
.servername
= talloc_asprintf(tctx
, "\\\\%s",
2448 dcerpc_server_name(p
));
2452 r
.out
.needed
= &needed
;
2453 r
.out
.count
= &count
;
2456 torture_comment(tctx
, "Testing EnumPorts\n");
2458 status
= dcerpc_spoolss_EnumPorts(p
, tctx
, &r
);
2460 torture_assert_ntstatus_ok(tctx
, status
, "EnumPorts failed");
2462 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2463 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2464 data_blob_clear(&blob
);
2465 r
.in
.buffer
= &blob
;
2466 r
.in
.offered
= needed
;
2468 status
= dcerpc_spoolss_EnumPorts(p
, tctx
, &r
);
2469 torture_assert_ntstatus_ok(tctx
, status
, "EnumPorts failed");
2470 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
2472 torture_assert(tctx
, info
, "No ports returned");
2475 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
2477 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts
, info
, 2, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
2482 static bool test_AddPort(struct torture_context
*tctx
,
2483 struct dcerpc_pipe
*p
)
2486 struct spoolss_AddPort r
;
2488 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s",
2489 dcerpc_server_name(p
));
2491 r
.in
.monitor_name
= "foo";
2493 torture_comment(tctx
, "Testing AddPort\n");
2495 status
= dcerpc_spoolss_AddPort(p
, tctx
, &r
);
2497 torture_assert_ntstatus_ok(tctx
, status
, "AddPort failed");
2499 /* win2k3 returns WERR_NOT_SUPPORTED */
2503 if (!W_ERROR_IS_OK(r
.out
.result
)) {
2504 printf("AddPort failed - %s\n", win_errstr(r
.out
.result
));
2513 static bool test_GetJob(struct torture_context
*tctx
,
2514 struct dcerpc_pipe
*p
,
2515 struct policy_handle
*handle
, uint32_t job_id
)
2518 struct spoolss_GetJob r
;
2519 union spoolss_JobInfo info
;
2521 uint32_t levels
[] = {1, 2 /* 3, 4 */};
2524 r
.in
.handle
= handle
;
2525 r
.in
.job_id
= job_id
;
2529 r
.out
.needed
= &needed
;
2532 torture_comment(tctx
, "Testing GetJob level %d\n", r
.in
.level
);
2534 status
= dcerpc_spoolss_GetJob(p
, tctx
, &r
);
2535 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
, "Unexpected return code");
2537 for (i
= 0; i
< ARRAY_SIZE(levels
); i
++) {
2539 torture_comment(tctx
, "Testing GetJob level %d\n", r
.in
.level
);
2543 r
.in
.level
= levels
[i
];
2547 status
= dcerpc_spoolss_GetJob(p
, tctx
, &r
);
2548 torture_assert_ntstatus_ok(tctx
, status
, "GetJob failed");
2550 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2551 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2552 data_blob_clear(&blob
);
2553 r
.in
.buffer
= &blob
;
2554 r
.in
.offered
= needed
;
2556 status
= dcerpc_spoolss_GetJob(p
, tctx
, &r
);
2557 torture_assert_ntstatus_ok(tctx
, status
, "GetJob failed");
2560 torture_assert(tctx
, r
.out
.info
, "No job info returned");
2561 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetJob failed");
2563 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
2569 static bool test_SetJob(struct torture_context
*tctx
,
2570 struct dcerpc_pipe
*p
,
2571 struct policy_handle
*handle
, uint32_t job_id
,
2572 enum spoolss_JobControl command
)
2575 struct spoolss_SetJob r
;
2577 r
.in
.handle
= handle
;
2578 r
.in
.job_id
= job_id
;
2580 r
.in
.command
= command
;
2583 case SPOOLSS_JOB_CONTROL_PAUSE
:
2584 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
2586 case SPOOLSS_JOB_CONTROL_RESUME
:
2587 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
2589 case SPOOLSS_JOB_CONTROL_CANCEL
:
2590 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
2592 case SPOOLSS_JOB_CONTROL_RESTART
:
2593 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
2595 case SPOOLSS_JOB_CONTROL_DELETE
:
2596 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
2598 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER
:
2599 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
2601 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED
:
2602 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
2604 case SPOOLSS_JOB_CONTROL_RETAIN
:
2605 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
2607 case SPOOLSS_JOB_CONTROL_RELEASE
:
2608 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
2611 torture_comment(tctx
, "Testing SetJob\n");
2615 status
= dcerpc_spoolss_SetJob(p
, tctx
, &r
);
2616 torture_assert_ntstatus_ok(tctx
, status
, "SetJob failed");
2617 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetJob failed");
2622 static bool test_AddJob(struct torture_context
*tctx
,
2623 struct dcerpc_pipe
*p
,
2624 struct policy_handle
*handle
)
2627 struct spoolss_AddJob r
;
2631 r
.in
.handle
= handle
;
2633 r
.out
.needed
= &needed
;
2634 r
.in
.buffer
= r
.out
.buffer
= NULL
;
2636 torture_comment(tctx
, "Testing AddJob\n");
2638 status
= dcerpc_spoolss_AddJob(p
, tctx
, &r
);
2639 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
, "AddJob failed");
2643 status
= dcerpc_spoolss_AddJob(p
, tctx
, &r
);
2644 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
, "AddJob failed");
2650 static bool test_EnumJobs(struct torture_context
*tctx
,
2651 struct dcerpc_pipe
*p
,
2652 struct policy_handle
*handle
)
2655 struct spoolss_EnumJobs r
;
2658 union spoolss_JobInfo
*info
;
2660 r
.in
.handle
= handle
;
2662 r
.in
.numjobs
= 0xffffffff;
2666 r
.out
.needed
= &needed
;
2667 r
.out
.count
= &count
;
2670 torture_comment(tctx
, "Testing EnumJobs\n");
2672 status
= dcerpc_spoolss_EnumJobs(p
, tctx
, &r
);
2674 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
2676 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2678 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2679 data_blob_clear(&blob
);
2680 r
.in
.buffer
= &blob
;
2681 r
.in
.offered
= needed
;
2683 status
= dcerpc_spoolss_EnumJobs(p
, tctx
, &r
);
2685 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
2686 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumJobs failed");
2687 torture_assert(tctx
, info
, "No jobs returned");
2689 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs
, *r
.out
.info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
2691 for (j
= 0; j
< count
; j
++) {
2693 torture_assert(tctx
, test_GetJob(tctx
, p
, handle
, info
[j
].info1
.job_id
),
2694 "failed to call test_GetJob");
2697 if (!torture_setting_bool(tctx
, "samba3", false)) {
2698 test_SetJob(tctx
, p
, handle
, info
[j
].info1
.job_id
, SPOOLSS_JOB_CONTROL_PAUSE
);
2699 test_SetJob(tctx
, p
, handle
, info
[j
].info1
.job_id
, SPOOLSS_JOB_CONTROL_RESUME
);
2704 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumJobs failed");
2710 static bool test_DoPrintTest(struct torture_context
*tctx
,
2711 struct dcerpc_pipe
*p
,
2712 struct policy_handle
*handle
)
2716 struct spoolss_StartDocPrinter s
;
2717 struct spoolss_DocumentInfo1 info1
;
2718 struct spoolss_StartPagePrinter sp
;
2719 struct spoolss_WritePrinter w
;
2720 struct spoolss_EndPagePrinter ep
;
2721 struct spoolss_EndDocPrinter e
;
2724 uint32_t num_written
;
2726 torture_comment(tctx
, "Testing StartDocPrinter\n");
2728 s
.in
.handle
= handle
;
2730 s
.in
.info
.info1
= &info1
;
2731 s
.out
.job_id
= &job_id
;
2732 info1
.document_name
= "TorturePrintJob";
2733 info1
.output_file
= NULL
;
2734 info1
.datatype
= "RAW";
2736 status
= dcerpc_spoolss_StartDocPrinter(p
, tctx
, &s
);
2737 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_StartDocPrinter failed");
2738 torture_assert_werr_ok(tctx
, s
.out
.result
, "StartDocPrinter failed");
2740 for (i
=1; i
< 4; i
++) {
2741 torture_comment(tctx
, "Testing StartPagePrinter: Page[%d]\n", i
);
2743 sp
.in
.handle
= handle
;
2745 status
= dcerpc_spoolss_StartPagePrinter(p
, tctx
, &sp
);
2746 torture_assert_ntstatus_ok(tctx
, status
,
2747 "dcerpc_spoolss_StartPagePrinter failed");
2748 torture_assert_werr_ok(tctx
, sp
.out
.result
, "StartPagePrinter failed");
2750 torture_comment(tctx
, "Testing WritePrinter: Page[%d]\n", i
);
2752 w
.in
.handle
= handle
;
2753 w
.in
.data
= data_blob_string_const(talloc_asprintf(tctx
,"TortureTestPage: %d\nData\n",i
));
2754 w
.out
.num_written
= &num_written
;
2756 status
= dcerpc_spoolss_WritePrinter(p
, tctx
, &w
);
2757 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_WritePrinter failed");
2758 torture_assert_werr_ok(tctx
, w
.out
.result
, "WritePrinter failed");
2760 torture_comment(tctx
, "Testing EndPagePrinter: Page[%d]\n", i
);
2762 ep
.in
.handle
= handle
;
2764 status
= dcerpc_spoolss_EndPagePrinter(p
, tctx
, &ep
);
2765 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndPagePrinter failed");
2766 torture_assert_werr_ok(tctx
, ep
.out
.result
, "EndPagePrinter failed");
2769 torture_comment(tctx
, "Testing EndDocPrinter\n");
2771 e
.in
.handle
= handle
;
2773 status
= dcerpc_spoolss_EndDocPrinter(p
, tctx
, &e
);
2774 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndDocPrinter failed");
2775 torture_assert_werr_ok(tctx
, e
.out
.result
, "EndDocPrinter failed");
2777 ret
&= test_AddJob(tctx
, p
, handle
);
2778 ret
&= test_EnumJobs(tctx
, p
, handle
);
2780 ret
&= test_SetJob(tctx
, p
, handle
, job_id
, SPOOLSS_JOB_CONTROL_DELETE
);
2785 static bool test_PausePrinter(struct torture_context
*tctx
,
2786 struct dcerpc_pipe
*p
,
2787 struct policy_handle
*handle
)
2790 struct spoolss_SetPrinter r
;
2791 struct spoolss_SetPrinterInfoCtr info_ctr
;
2792 struct spoolss_DevmodeContainer devmode_ctr
;
2793 struct sec_desc_buf secdesc_ctr
;
2796 info_ctr
.info
.info0
= NULL
;
2798 ZERO_STRUCT(devmode_ctr
);
2799 ZERO_STRUCT(secdesc_ctr
);
2801 r
.in
.handle
= handle
;
2802 r
.in
.info_ctr
= &info_ctr
;
2803 r
.in
.devmode_ctr
= &devmode_ctr
;
2804 r
.in
.secdesc_ctr
= &secdesc_ctr
;
2805 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
2807 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
2809 status
= dcerpc_spoolss_SetPrinter(p
, tctx
, &r
);
2811 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
2813 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
2818 static bool test_ResumePrinter(struct torture_context
*tctx
,
2819 struct dcerpc_pipe
*p
,
2820 struct policy_handle
*handle
)
2823 struct spoolss_SetPrinter r
;
2824 struct spoolss_SetPrinterInfoCtr info_ctr
;
2825 struct spoolss_DevmodeContainer devmode_ctr
;
2826 struct sec_desc_buf secdesc_ctr
;
2829 info_ctr
.info
.info0
= NULL
;
2831 ZERO_STRUCT(devmode_ctr
);
2832 ZERO_STRUCT(secdesc_ctr
);
2834 r
.in
.handle
= handle
;
2835 r
.in
.info_ctr
= &info_ctr
;
2836 r
.in
.devmode_ctr
= &devmode_ctr
;
2837 r
.in
.secdesc_ctr
= &secdesc_ctr
;
2838 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
2840 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2842 status
= dcerpc_spoolss_SetPrinter(p
, tctx
, &r
);
2844 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
2846 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
2851 static bool test_GetPrinterData(struct torture_context
*tctx
,
2852 struct dcerpc_pipe
*p
,
2853 struct policy_handle
*handle
,
2854 const char *value_name
,
2855 enum winreg_Type
*type_p
,
2860 struct spoolss_GetPrinterData r
;
2862 enum winreg_Type type
;
2863 union spoolss_PrinterData data
;
2865 r
.in
.handle
= handle
;
2866 r
.in
.value_name
= value_name
;
2868 r
.out
.needed
= &needed
;
2870 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
2872 torture_comment(tctx
, "Testing GetPrinterData(%s)\n", r
.in
.value_name
);
2874 status
= dcerpc_spoolss_GetPrinterData(p
, tctx
, &r
);
2875 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
2877 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
2878 r
.in
.offered
= needed
;
2879 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
2880 status
= dcerpc_spoolss_GetPrinterData(p
, tctx
, &r
);
2881 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
2884 torture_assert_werr_ok(tctx
, r
.out
.result
,
2885 talloc_asprintf(tctx
, "GetPrinterData(%s) failed", r
.in
.value_name
));
2887 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData
, &data
, type
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 1);
2894 *data_p
= r
.out
.data
;
2904 static bool test_GetPrinterDataEx(struct torture_context
*tctx
,
2905 struct dcerpc_pipe
*p
,
2906 struct policy_handle
*handle
,
2907 const char *key_name
,
2908 const char *value_name
,
2909 enum winreg_Type
*type_p
,
2914 struct spoolss_GetPrinterDataEx r
;
2915 enum winreg_Type type
;
2917 union spoolss_PrinterData data
;
2919 r
.in
.handle
= handle
;
2920 r
.in
.key_name
= key_name
;
2921 r
.in
.value_name
= value_name
;
2924 r
.out
.needed
= &needed
;
2925 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
2927 torture_comment(tctx
, "Testing GetPrinterDataEx(%s - %s)\n",
2928 r
.in
.key_name
, r
.in
.value_name
);
2930 status
= dcerpc_spoolss_GetPrinterDataEx(p
, tctx
, &r
);
2931 if (!NT_STATUS_IS_OK(status
)) {
2932 if (NT_STATUS_EQUAL(status
,NT_STATUS_NET_WRITE_FAULT
) &&
2933 p
->last_fault_code
== DCERPC_FAULT_OP_RNG_ERROR
) {
2934 torture_skip(tctx
, "GetPrinterDataEx not supported by server\n");
2936 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
2939 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
2940 r
.in
.offered
= needed
;
2941 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
2942 status
= dcerpc_spoolss_GetPrinterDataEx(p
, tctx
, &r
);
2943 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
2946 torture_assert_werr_ok(tctx
, r
.out
.result
,
2947 talloc_asprintf(tctx
, "GetPrinterDataEx(%s - %s) failed", r
.in
.key_name
, r
.in
.value_name
));
2949 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData
, &data
, type
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 1);
2956 *data_p
= r
.out
.data
;
2966 static bool test_GetPrinterData_list(struct torture_context
*tctx
,
2967 struct dcerpc_pipe
*p
,
2968 struct policy_handle
*handle
,
2969 const char **architecture
)
2971 const char *list
[] = {
2975 /* "NetPopup", not on w2k8 */
2976 /* "NetPopupToComputer", not on w2k8 */
2979 "DefaultSpoolDirectory",
2983 /* "OSVersionEx", not on s3 */
2988 for (i
=0; i
< ARRAY_SIZE(list
); i
++) {
2989 enum winreg_Type type
, type_ex
;
2990 uint8_t *data
, *data_ex
;
2991 uint32_t needed
, needed_ex
;
2993 torture_assert(tctx
, test_GetPrinterData(tctx
, p
, handle
, list
[i
], &type
, &data
, &needed
),
2994 talloc_asprintf(tctx
, "GetPrinterData failed on %s\n", list
[i
]));
2995 torture_assert(tctx
, test_GetPrinterDataEx(tctx
, p
, handle
, "random_string", list
[i
], &type_ex
, &data_ex
, &needed_ex
),
2996 talloc_asprintf(tctx
, "GetPrinterDataEx failed on %s\n", list
[i
]));
2997 torture_assert_int_equal(tctx
, type
, type_ex
, "type mismatch");
2998 torture_assert_int_equal(tctx
, needed
, needed_ex
, "needed mismatch");
2999 torture_assert_mem_equal(tctx
, data
, data_ex
, needed
, "data mismatch");
3001 if (strequal(list
[i
], "Architecture")) {
3003 DATA_BLOB blob
= data_blob_const(data
, needed
);
3004 *architecture
= reg_val_data_string(tctx
, lp_iconv_convenience(tctx
->lp_ctx
), REG_SZ
, blob
);
3012 static bool test_EnumPrinterData(struct torture_context
*tctx
,
3013 struct dcerpc_pipe
*p
,
3014 struct policy_handle
*handle
,
3015 uint32_t enum_index
,
3016 uint32_t value_offered
,
3017 uint32_t data_offered
,
3018 enum winreg_Type
*type_p
,
3019 uint32_t *value_needed_p
,
3020 uint32_t *data_needed_p
,
3021 const char **value_name_p
,
3025 struct spoolss_EnumPrinterData r
;
3026 uint32_t data_needed
;
3027 uint32_t value_needed
;
3028 enum winreg_Type type
;
3030 r
.in
.handle
= handle
;
3031 r
.in
.enum_index
= enum_index
;
3032 r
.in
.value_offered
= value_offered
;
3033 r
.in
.data_offered
= data_offered
;
3034 r
.out
.data_needed
= &data_needed
;
3035 r
.out
.value_needed
= &value_needed
;
3037 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.data_offered
);
3038 r
.out
.value_name
= talloc_zero_array(tctx
, const char, r
.in
.value_offered
);
3040 torture_comment(tctx
, "Testing EnumPrinterData(%d)\n", enum_index
);
3042 torture_assert_ntstatus_ok(tctx
,
3043 dcerpc_spoolss_EnumPrinterData(p
, tctx
, &r
),
3044 "EnumPrinterData failed");
3049 if (value_needed_p
) {
3050 *value_needed_p
= value_needed
;
3052 if (data_needed_p
) {
3053 *data_needed_p
= data_needed
;
3056 *value_name_p
= r
.out
.value_name
;
3059 *data_p
= r
.out
.data
;
3062 *result_p
= r
.out
.result
;
3069 static bool test_EnumPrinterData_all(struct torture_context
*tctx
,
3070 struct dcerpc_pipe
*p
,
3071 struct policy_handle
*handle
)
3073 uint32_t enum_index
= 0;
3074 enum winreg_Type type
;
3075 uint32_t value_needed
;
3076 uint32_t data_needed
;
3078 const char *value_name
;
3082 torture_assert(tctx
,
3083 test_EnumPrinterData(tctx
, p
, handle
, enum_index
, 0, 0,
3084 &type
, &value_needed
, &data_needed
,
3085 &value_name
, &data
, &result
),
3086 "EnumPrinterData failed");
3088 if (W_ERROR_EQUAL(result
, WERR_NO_MORE_ITEMS
)) {
3092 torture_assert(tctx
,
3093 test_EnumPrinterData(tctx
, p
, handle
, enum_index
, value_needed
, data_needed
,
3094 &type
, &value_needed
, &data_needed
,
3095 &value_name
, &data
, &result
),
3096 "EnumPrinterData failed");
3098 if (W_ERROR_EQUAL(result
, WERR_NO_MORE_ITEMS
)) {
3104 } while (W_ERROR_IS_OK(result
));
3109 static bool test_EnumPrinterDataEx(struct torture_context
*tctx
,
3110 struct dcerpc_pipe
*p
,
3111 struct policy_handle
*handle
,
3112 const char *key_name
,
3114 struct spoolss_PrinterEnumValues
**info_p
)
3116 struct spoolss_EnumPrinterDataEx r
;
3117 struct spoolss_PrinterEnumValues
*info
;
3121 r
.in
.handle
= handle
;
3122 r
.in
.key_name
= key_name
;
3124 r
.out
.needed
= &needed
;
3125 r
.out
.count
= &count
;
3128 torture_comment(tctx
, "Testing EnumPrinterDataEx(%s)\n", key_name
);
3130 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterDataEx(p
, tctx
, &r
),
3131 "EnumPrinterDataEx failed");
3132 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
3133 r
.in
.offered
= needed
;
3134 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterDataEx(p
, tctx
, &r
),
3135 "EnumPrinterDataEx failed");
3138 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDataEx failed");
3140 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx
, info
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 1);
3152 static bool test_SetPrinterData(struct torture_context
*tctx
,
3153 struct dcerpc_pipe
*p
,
3154 struct policy_handle
*handle
,
3155 const char *value_name
,
3156 enum winreg_Type type
,
3159 static bool test_DeletePrinterData(struct torture_context
*tctx
,
3160 struct dcerpc_pipe
*p
,
3161 struct policy_handle
*handle
,
3162 const char *value_name
);
3164 static bool test_EnumPrinterData_consistency(struct torture_context
*tctx
,
3165 struct dcerpc_pipe
*p
,
3166 struct policy_handle
*handle
)
3169 struct spoolss_PrinterEnumValues
*info
;
3171 uint32_t value_needed
, data_needed
;
3172 uint32_t value_offered
, data_offered
;
3175 enum winreg_Type type
;
3178 torture_comment(tctx
, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3180 torture_assert(tctx
,
3181 reg_string_to_val(tctx
, lp_iconv_convenience(tctx
->lp_ctx
),
3182 "REG_SZ", "torture_data1", &type
, &blob
), "");
3184 torture_assert(tctx
,
3185 test_SetPrinterData(tctx
, p
, handle
, "torture_value1", type
, blob
.data
, blob
.length
),
3186 "SetPrinterData failed");
3188 blob
= data_blob_string_const("torture_data2");
3190 torture_assert(tctx
,
3191 test_SetPrinterData(tctx
, p
, handle
, "torture_value2", REG_BINARY
, blob
.data
, blob
.length
),
3192 "SetPrinterData failed");
3194 blob
= data_blob_talloc(tctx
, NULL
, 4);
3195 SIVAL(blob
.data
, 0, 0x11223344);
3197 torture_assert(tctx
,
3198 test_SetPrinterData(tctx
, p
, handle
, "torture_value3", type
, blob
.data
, blob
.length
),
3199 "SetPrinterData failed");
3201 torture_assert(tctx
,
3202 test_EnumPrinterDataEx(tctx
, p
, handle
, "PrinterDriverData", &count
, &info
),
3203 "failed to call EnumPrinterDataEx");
3205 /* get the max sizes for value and data */
3207 torture_assert(tctx
,
3208 test_EnumPrinterData(tctx
, p
, handle
, 0, 0, 0,
3209 NULL
, &value_needed
, &data_needed
,
3210 NULL
, NULL
, &result
),
3211 "EnumPrinterData failed");
3212 torture_assert_werr_ok(tctx
, result
, "unexpected result");
3214 /* check if the reply from the EnumPrinterData really matches max values */
3216 for (i
=0; i
< count
; i
++) {
3217 if (info
[i
].value_name_len
> value_needed
) {
3219 talloc_asprintf(tctx
,
3220 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3221 info
[i
].value_name_len
, value_needed
));
3223 if (info
[i
].data_length
> data_needed
) {
3225 talloc_asprintf(tctx
,
3226 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3227 info
[i
].data_length
, data_needed
));
3231 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3232 * sort or not sort the replies by value name, we should be able to do
3233 * the following entry comparison */
3235 data_offered
= data_needed
;
3236 value_offered
= value_needed
;
3238 for (i
=0; i
< count
; i
++) {
3240 enum winreg_Type type
;
3241 const char *value_name
;
3244 torture_assert(tctx
,
3245 test_EnumPrinterData(tctx
, p
, handle
, i
, value_offered
, data_offered
,
3246 &type
, &value_needed
, &data_needed
,
3247 &value_name
, &data
, &result
),
3248 "EnumPrinterData failed");
3250 if (i
-1 == count
) {
3251 torture_assert_werr_equal(tctx
, result
, WERR_NO_MORE_ITEMS
,
3252 "unexpected result");
3255 torture_assert_werr_ok(tctx
, result
, "unexpected result");
3258 torture_assert_int_equal(tctx
, type
, info
[i
].type
, "type mismatch");
3259 torture_assert_int_equal(tctx
, value_needed
, info
[i
].value_name_len
, "value name length mismatch");
3260 torture_assert_str_equal(tctx
, value_name
, info
[i
].value_name
, "value name mismatch");
3261 torture_assert_int_equal(tctx
, data_needed
, info
[i
].data_length
, "data length mismatch");
3262 torture_assert_mem_equal(tctx
, data
, info
[i
].data
->data
, info
[i
].data_length
, "data mismatch");
3265 torture_assert(tctx
,
3266 test_DeletePrinterData(tctx
, p
, handle
, "torture_value1"),
3267 "DeletePrinterData failed");
3268 torture_assert(tctx
,
3269 test_DeletePrinterData(tctx
, p
, handle
, "torture_value2"),
3270 "DeletePrinterData failed");
3271 torture_assert(tctx
,
3272 test_DeletePrinterData(tctx
, p
, handle
, "torture_value3"),
3273 "DeletePrinterData failed");
3275 torture_comment(tctx
, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
3280 static bool test_DeletePrinterData(struct torture_context
*tctx
,
3281 struct dcerpc_pipe
*p
,
3282 struct policy_handle
*handle
,
3283 const char *value_name
)
3286 struct spoolss_DeletePrinterData r
;
3288 r
.in
.handle
= handle
;
3289 r
.in
.value_name
= value_name
;
3291 torture_comment(tctx
, "Testing DeletePrinterData(%s)\n",
3294 status
= dcerpc_spoolss_DeletePrinterData(p
, tctx
, &r
);
3296 torture_assert_ntstatus_ok(tctx
, status
, "DeletePrinterData failed");
3297 torture_assert_werr_ok(tctx
, r
.out
.result
, "DeletePrinterData failed");
3302 static bool test_DeletePrinterDataEx(struct torture_context
*tctx
,
3303 struct dcerpc_pipe
*p
,
3304 struct policy_handle
*handle
,
3305 const char *key_name
,
3306 const char *value_name
)
3308 struct spoolss_DeletePrinterDataEx r
;
3310 r
.in
.handle
= handle
;
3311 r
.in
.key_name
= key_name
;
3312 r
.in
.value_name
= value_name
;
3314 torture_comment(tctx
, "Testing DeletePrinterDataEx(%s - %s)\n",
3315 r
.in
.key_name
, r
.in
.value_name
);
3317 torture_assert_ntstatus_ok(tctx
,
3318 dcerpc_spoolss_DeletePrinterDataEx(p
, tctx
, &r
),
3319 "DeletePrinterDataEx failed");
3320 torture_assert_werr_ok(tctx
, r
.out
.result
,
3321 "DeletePrinterDataEx failed");
3326 static bool test_DeletePrinterKey(struct torture_context
*tctx
,
3327 struct dcerpc_pipe
*p
,
3328 struct policy_handle
*handle
,
3329 const char *key_name
)
3331 struct spoolss_DeletePrinterKey r
;
3333 r
.in
.handle
= handle
;
3334 r
.in
.key_name
= key_name
;
3336 torture_comment(tctx
, "Testing DeletePrinterKey(%s)\n", r
.in
.key_name
);
3338 if (strequal(key_name
, "") && !torture_setting_bool(tctx
, "dangerous", false)) {
3339 torture_skip(tctx
, "not wiping out printer registry - enable dangerous tests to use\n");
3343 torture_assert_ntstatus_ok(tctx
,
3344 dcerpc_spoolss_DeletePrinterKey(p
, tctx
, &r
),
3345 "DeletePrinterKey failed");
3346 torture_assert_werr_ok(tctx
, r
.out
.result
,
3347 "DeletePrinterKey failed");
3352 static bool test_winreg_OpenHKLM(struct torture_context
*tctx
,
3353 struct dcerpc_pipe
*p
,
3354 struct policy_handle
*handle
)
3356 struct winreg_OpenHKLM r
;
3358 r
.in
.system_name
= NULL
;
3359 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
3360 r
.out
.handle
= handle
;
3362 torture_comment(tctx
, "Testing winreg_OpenHKLM\n");
3364 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_OpenHKLM(p
, tctx
, &r
), "OpenHKLM failed");
3365 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenHKLM failed");
3370 static void init_winreg_String(struct winreg_String
*name
, const char *s
)
3374 name
->name_len
= 2 * (strlen_m(s
) + 1);
3375 name
->name_size
= name
->name_len
;
3378 name
->name_size
= 0;
3382 static bool test_winreg_OpenKey(struct torture_context
*tctx
,
3383 struct dcerpc_pipe
*p
,
3384 struct policy_handle
*hive_handle
,
3385 const char *keyname
,
3386 struct policy_handle
*key_handle
)
3388 struct winreg_OpenKey r
;
3390 r
.in
.parent_handle
= hive_handle
;
3391 init_winreg_String(&r
.in
.keyname
, keyname
);
3392 r
.in
.options
= REG_KEYTYPE_NON_VOLATILE
;
3393 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
3394 r
.out
.handle
= key_handle
;
3396 torture_comment(tctx
, "Testing winreg_OpenKey(%s)\n", keyname
);
3398 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_OpenKey(p
, tctx
, &r
), "OpenKey failed");
3399 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenKey failed");
3404 static bool test_winreg_CloseKey(struct torture_context
*tctx
,
3405 struct dcerpc_pipe
*p
,
3406 struct policy_handle
*handle
)
3408 struct winreg_CloseKey r
;
3410 r
.in
.handle
= handle
;
3411 r
.out
.handle
= handle
;
3413 torture_comment(tctx
, "Testing winreg_CloseKey\n");
3415 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_CloseKey(p
, tctx
, &r
), "CloseKey failed");
3416 torture_assert_werr_ok(tctx
, r
.out
.result
, "CloseKey failed");
3421 bool test_winreg_QueryValue(struct torture_context
*tctx
,
3422 struct dcerpc_pipe
*p
,
3423 struct policy_handle
*handle
,
3424 const char *value_name
,
3425 enum winreg_Type
*type_p
,
3426 uint32_t *data_size_p
,
3427 uint32_t *data_length_p
,
3430 struct winreg_QueryValue r
;
3431 enum winreg_Type type
= REG_NONE
;
3432 uint32_t data_size
= 0;
3433 uint32_t data_length
= 0;
3434 struct winreg_String valuename
;
3435 uint8_t *data
= NULL
;
3437 init_winreg_String(&valuename
, value_name
);
3439 data
= talloc_zero_array(tctx
, uint8_t, 0);
3441 r
.in
.handle
= handle
;
3442 r
.in
.value_name
= &valuename
;
3444 r
.in
.data_size
= &data_size
;
3445 r
.in
.data_length
= &data_length
;
3449 r
.out
.data_size
= &data_size
;
3450 r
.out
.data_length
= &data_length
;
3452 torture_comment(tctx
, "Testing winreg_QueryValue(%s)\n", value_name
);
3454 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_QueryValue(p
, tctx
, &r
), "QueryValue failed");
3455 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
3456 *r
.in
.data_size
= *r
.out
.data_size
;
3457 data
= talloc_zero_array(tctx
, uint8_t, *r
.in
.data_size
);
3460 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_QueryValue(p
, tctx
, &r
), "QueryValue failed");
3462 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryValue failed");
3465 *type_p
= *r
.out
.type
;
3468 *data_size_p
= *r
.out
.data_size
;
3470 if (data_length_p
) {
3471 *data_length_p
= *r
.out
.data_length
;
3474 *data_p
= r
.out
.data
;
3480 static bool test_winreg_query_printerdata(struct torture_context
*tctx
,
3481 struct dcerpc_pipe
*p
,
3482 struct policy_handle
*handle
,
3483 const char *printer_name
,
3484 const char *key_name
,
3485 const char *value_name
,
3486 enum winreg_Type
*w_type
,
3491 const char *printer_key
;
3492 struct policy_handle key_handle
;
3494 printer_key
= talloc_asprintf(tctx
, "%s\\%s\\%s",
3495 TOP_LEVEL_PRINTER_KEY
, printer_name
, key_name
);
3497 torture_assert(tctx
,
3498 test_winreg_OpenKey(tctx
, p
, handle
, printer_key
, &key_handle
), "");
3500 torture_assert(tctx
,
3501 test_winreg_QueryValue(tctx
, p
, &key_handle
, value_name
, w_type
, w_size
, w_length
, w_data
), "");
3503 torture_assert(tctx
,
3504 test_winreg_CloseKey(tctx
, p
, &key_handle
), "");
3509 static bool test_SetPrinterData(struct torture_context
*tctx
,
3510 struct dcerpc_pipe
*p
,
3511 struct policy_handle
*handle
,
3512 const char *value_name
,
3513 enum winreg_Type type
,
3517 struct spoolss_SetPrinterData r
;
3519 r
.in
.handle
= handle
;
3520 r
.in
.value_name
= value_name
;
3523 r
.in
.offered
= offered
;
3525 torture_comment(tctx
, "Testing SetPrinterData(%s)\n",
3528 torture_assert_ntstatus_ok(tctx
,
3529 dcerpc_spoolss_SetPrinterData(p
, tctx
, &r
),
3530 "SetPrinterData failed");
3531 torture_assert_werr_ok(tctx
, r
.out
.result
,
3532 "SetPrinterData failed");
3537 static bool test_SetPrinterData_matrix(struct torture_context
*tctx
,
3538 struct dcerpc_pipe
*p
,
3539 struct policy_handle
*handle
,
3540 const char *printer_name
,
3541 struct dcerpc_pipe
*winreg_pipe
,
3542 struct policy_handle
*hive_handle
)
3544 const char *values
[] = {
3548 /* FIXME: not working with s3 atm. */
3554 /* FIXME: not working with s3 atm. */
3561 for (i
=0; i
< ARRAY_SIZE(values
); i
++) {
3563 enum winreg_Type type
;
3568 torture_assert(tctx
,
3569 reg_string_to_val(tctx
, lp_iconv_convenience(tctx
->lp_ctx
),
3570 "REG_SZ", "dog", &type
, &blob
), "");
3572 torture_assert(tctx
,
3573 test_SetPrinterData(tctx
, p
, handle
, values
[i
], REG_SZ
, blob
.data
, blob
.length
),
3574 "SetPrinterData failed");
3576 torture_assert(tctx
,
3577 test_GetPrinterData(tctx
, p
, handle
, values
[i
], &type
, &data
, &needed
),
3578 "GetPrinterData failed");
3580 torture_assert_int_equal(tctx
, type
, REG_SZ
, "type mismatch");
3581 torture_assert_int_equal(tctx
, needed
, blob
.length
, "size mismatch");
3582 torture_assert_mem_equal(tctx
, data
, blob
.data
, blob
.length
, "buffer mismatch");
3584 if (winreg_pipe
&& hive_handle
) {
3586 enum winreg_Type w_type
;
3591 torture_assert(tctx
,
3592 test_winreg_query_printerdata(tctx
, winreg_pipe
, hive_handle
,
3593 printer_name
, "PrinterDriverData", values
[i
],
3594 &w_type
, &w_size
, &w_length
, &w_data
), "");
3596 torture_assert_int_equal(tctx
, w_type
, REG_SZ
, "winreg type mismatch");
3597 torture_assert_int_equal(tctx
, w_size
, blob
.length
, "winreg size mismatch");
3598 torture_assert_int_equal(tctx
, w_length
, blob
.length
, "winreg length mismatch");
3599 torture_assert_mem_equal(tctx
, w_data
, blob
.data
, blob
.length
, "winreg buffer mismatch");
3602 torture_assert(tctx
,
3603 test_DeletePrinterData(tctx
, p
, handle
, values
[i
]),
3604 "DeletePrinterData failed");
3611 static bool test_EnumPrinterKey(struct torture_context
*tctx
,
3612 struct dcerpc_pipe
*p
,
3613 struct policy_handle
*handle
,
3614 const char *key_name
,
3615 const char ***array
);
3617 static bool test_SetPrinterDataEx(struct torture_context
*tctx
,
3618 struct dcerpc_pipe
*p
,
3619 struct policy_handle
*handle
,
3620 const char *key_name
,
3621 const char *value_name
,
3622 enum winreg_Type type
,
3627 struct spoolss_SetPrinterDataEx r
;
3629 r
.in
.handle
= handle
;
3630 r
.in
.key_name
= key_name
;
3631 r
.in
.value_name
= value_name
;
3634 r
.in
.offered
= offered
;
3636 torture_comment(tctx
, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
3637 r
.in
.key_name
, r
.in
.value_name
, str_regtype(r
.in
.type
), r
.in
.offered
);
3639 status
= dcerpc_spoolss_SetPrinterDataEx(p
, tctx
, &r
);
3641 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinterDataEx failed");
3642 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinterDataEx failed");
3647 static bool test_SetPrinterDataEx_matrix(struct torture_context
*tctx
,
3648 struct dcerpc_pipe
*p
,
3649 struct policy_handle
*handle
,
3650 const char *printername
,
3651 struct dcerpc_pipe
*winreg_pipe
,
3652 struct policy_handle
*hive_handle
)
3654 const char *value_name
= "dog";
3655 const char *keys
[] = {
3659 /* FIXME: not working with s3 atm. */
3660 "torturedataex_with_subkey\\subkey",
3661 "torturedataex_with_subkey\\subkey:0",
3662 "torturedataex_with_subkey\\subkey:1",
3663 "torturedataex_with_subkey\\subkey\\subsubkey",
3664 "torturedataex_with_subkey\\subkey\\subsubkey:0",
3665 "torturedataex_with_subkey\\subkey\\subsubkey:1",
3669 /* FIXME: not working with s3 atm. */
3676 enum winreg_Type types
[] = {
3681 const char *str
= "abcdefghijklmnopqrstuvwxzy";
3685 for (i
=0; i
< ARRAY_SIZE(keys
); i
++) {
3686 for (t
=0; t
< ARRAY_SIZE(types
); t
++) {
3687 for (s
=0; s
< strlen(str
); s
++) {
3691 enum winreg_Type type
;
3692 const char *string
= talloc_strndup(tctx
, str
, s
);
3693 DATA_BLOB blob
= data_blob_string_const(string
);
3694 const char **subkeys
;
3697 uint32_t needed
, offered
= 0;
3699 struct spoolss_PrinterEnumValues
*einfo
;
3705 offered
= blob
.length
;
3708 torture_assert(tctx
,
3709 reg_string_to_val(tctx
, lp_iconv_convenience(tctx
->lp_ctx
),
3710 "REG_SZ", string
, &type
, &data
), "");
3711 offered
= data
.length
;
3712 /*strlen_m_term(data.string)*2;*/
3715 torture_fail(tctx
, talloc_asprintf(tctx
, "type %d untested\n", types
[t
]));
3718 torture_assert(tctx
,
3719 test_SetPrinterDataEx(tctx
, p
, handle
, keys
[i
], value_name
, types
[t
], data
.data
, offered
),
3720 "failed to call SetPrinterDataEx");
3722 torture_assert(tctx
,
3723 test_GetPrinterDataEx(tctx
, p
, handle
, keys
[i
], value_name
, &type
, &data_out
, &needed
),
3724 "failed to call GetPrinterDataEx");
3726 torture_assert(tctx
,
3727 test_EnumPrinterDataEx(tctx
, p
, handle
, keys
[i
], &ecount
, &einfo
),
3728 "failed to call EnumPrinterDataEx");
3730 torture_assert_int_equal(tctx
, types
[t
], type
, "type mismatch");
3731 torture_assert_int_equal(tctx
, needed
, offered
, "size mismatch");
3732 torture_assert_mem_equal(tctx
, data_out
, data
.data
, offered
, "buffer mismatch");
3734 torture_assert_int_equal(tctx
, ecount
, 1, "unexpected enum count");
3735 torture_assert_str_equal(tctx
, einfo
[0].value_name
, value_name
, "value_name mismatch");
3736 torture_assert_int_equal(tctx
, einfo
[0].value_name_len
, strlen_m_term(value_name
)*2, "unexpected value_name_len");
3737 torture_assert_int_equal(tctx
, einfo
[0].type
, types
[t
], "type mismatch");
3738 torture_assert_int_equal(tctx
, einfo
[0].data_length
, offered
, "size mismatch");
3739 if (einfo
[0].data_length
> 0) {
3740 torture_assert_mem_equal(tctx
, einfo
[0].data
->data
, data
.data
, offered
, "buffer mismatch");
3743 if (winreg_pipe
&& hive_handle
) {
3745 enum winreg_Type w_type
;
3750 torture_assert(tctx
,
3751 test_winreg_query_printerdata(tctx
, winreg_pipe
, hive_handle
,
3752 printername
, keys
[i
], value_name
,
3753 &w_type
, &w_size
, &w_length
, &w_data
), "");
3755 torture_assert_int_equal(tctx
, w_type
, types
[t
], "winreg type mismatch");
3756 torture_assert_int_equal(tctx
, w_size
, offered
, "winreg size mismatch");
3757 torture_assert_int_equal(tctx
, w_length
, offered
, "winreg length mismatch");
3758 torture_assert_mem_equal(tctx
, w_data
, data
.data
, offered
, "winreg buffer mismatch");
3761 key
= talloc_strdup(tctx
, keys
[i
]);
3763 if (!test_DeletePrinterDataEx(tctx
, p
, handle
, keys
[i
], value_name
)) {
3767 c
= strchr(key
, '\\');
3771 /* we have subkeys */
3775 if (!test_EnumPrinterKey(tctx
, p
, handle
, key
, &subkeys
)) {
3779 for (k
=0; subkeys
&& subkeys
[k
]; k
++) {
3781 const char *current_key
= talloc_asprintf(tctx
, "%s\\%s", key
, subkeys
[k
]);
3783 if (!test_DeletePrinterKey(tctx
, p
, handle
, current_key
)) {
3788 if (!test_DeletePrinterKey(tctx
, p
, handle
, key
)) {
3793 if (!test_DeletePrinterKey(tctx
, p
, handle
, key
)) {
3804 static bool test_PrinterData_winreg(struct torture_context
*tctx
,
3805 struct dcerpc_pipe
*p
,
3806 struct policy_handle
*handle
,
3807 const char *printer_name
)
3809 struct dcerpc_pipe
*p2
;
3811 struct policy_handle hive_handle
;
3813 torture_assert_ntstatus_ok(tctx
,
3814 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
3815 "could not open winreg pipe");
3817 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, p2
, &hive_handle
), "");
3819 ret
&= test_SetPrinterData_matrix(tctx
, p
, handle
, printer_name
, p2
, &hive_handle
);
3820 ret
&= test_SetPrinterDataEx_matrix(tctx
, p
, handle
, printer_name
, p2
, &hive_handle
);
3822 test_winreg_CloseKey(tctx
, p2
, &hive_handle
);
3829 static bool test_GetChangeID_PrinterData(struct torture_context
*tctx
,
3830 struct dcerpc_pipe
*p
,
3831 struct policy_handle
*handle
,
3832 uint32_t *change_id
)
3834 enum winreg_Type type
;
3838 torture_assert(tctx
,
3839 test_GetPrinterData(tctx
, p
, handle
, "ChangeID", &type
, &data
, &needed
),
3840 "failed to call GetPrinterData");
3842 torture_assert(tctx
, type
== REG_DWORD
, "unexpected type");
3843 torture_assert_int_equal(tctx
, needed
, 4, "unexpected size");
3845 *change_id
= IVAL(data
, 0);
3850 static bool test_GetChangeID_PrinterDataEx(struct torture_context
*tctx
,
3851 struct dcerpc_pipe
*p
,
3852 struct policy_handle
*handle
,
3853 uint32_t *change_id
)
3855 enum winreg_Type type
;
3859 torture_assert(tctx
,
3860 test_GetPrinterDataEx(tctx
, p
, handle
, "PrinterDriverData", "ChangeID", &type
, &data
, &needed
),
3861 "failed to call GetPrinterData");
3863 torture_assert(tctx
, type
== REG_DWORD
, "unexpected type");
3864 torture_assert_int_equal(tctx
, needed
, 4, "unexpected size");
3866 *change_id
= IVAL(data
, 0);
3871 static bool test_GetChangeID_PrinterInfo(struct torture_context
*tctx
,
3872 struct dcerpc_pipe
*p
,
3873 struct policy_handle
*handle
,
3874 uint32_t *change_id
)
3876 union spoolss_PrinterInfo info
;
3878 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, handle
, 0, &info
),
3879 "failed to query Printer level 0");
3881 *change_id
= info
.info0
.change_id
;
3886 static bool test_ChangeID(struct torture_context
*tctx
,
3887 struct dcerpc_pipe
*p
,
3888 struct policy_handle
*handle
)
3890 uint32_t change_id
, change_id_ex
, change_id_info
;
3891 uint32_t change_id2
, change_id_ex2
, change_id_info2
;
3892 union spoolss_PrinterInfo info
;
3893 const char *comment
;
3896 torture_comment(tctx
, "Testing ChangeID: id change test #1\n");
3898 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, p
, handle
, &change_id
),
3899 "failed to query for ChangeID");
3900 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex
),
3901 "failed to query for ChangeID");
3902 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, p
, handle
, &change_id_info
),
3903 "failed to query for ChangeID");
3905 torture_assert_int_equal(tctx
, change_id
, change_id_ex
,
3906 "change_ids should all be equal");
3907 torture_assert_int_equal(tctx
, change_id_ex
, change_id_info
,
3908 "change_ids should all be equal");
3911 torture_comment(tctx
, "Testing ChangeID: id change test #2\n");
3913 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, p
, handle
, &change_id
),
3914 "failed to query for ChangeID");
3915 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, handle
, 2, &info
),
3916 "failed to query Printer level 2");
3917 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex
),
3918 "failed to query for ChangeID");
3919 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, p
, handle
, &change_id_info
),
3920 "failed to query for ChangeID");
3921 torture_assert_int_equal(tctx
, change_id
, change_id_ex
,
3922 "change_id should not have changed");
3923 torture_assert_int_equal(tctx
, change_id_ex
, change_id_info
,
3924 "change_id should not have changed");
3927 torture_comment(tctx
, "Testing ChangeID: id change test #3\n");
3929 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, p
, handle
, &change_id
),
3930 "failed to query for ChangeID");
3931 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex
),
3932 "failed to query for ChangeID");
3933 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, p
, handle
, &change_id_info
),
3934 "failed to query for ChangeID");
3935 torture_assert(tctx
, test_GetPrinter_level(tctx
, p
, handle
, 2, &info
),
3936 "failed to query Printer level 2");
3937 comment
= talloc_strdup(tctx
, info
.info2
.comment
);
3940 struct spoolss_SetPrinterInfoCtr info_ctr
;
3941 struct spoolss_DevmodeContainer devmode_ctr
;
3942 struct sec_desc_buf secdesc_ctr
;
3943 union spoolss_SetPrinterInfo sinfo
;
3945 ZERO_STRUCT(info_ctr
);
3946 ZERO_STRUCT(devmode_ctr
);
3947 ZERO_STRUCT(secdesc_ctr
);
3950 torture_assert(tctx
, PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
3951 sinfo
.info2
->comment
= "torture_comment";
3954 info_ctr
.info
= sinfo
;
3956 torture_assert(tctx
, test_SetPrinter(tctx
, p
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0),
3957 "failed to call SetPrinter");
3959 sinfo
.info2
->comment
= comment
;
3961 torture_assert(tctx
, test_SetPrinter(tctx
, p
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0),
3962 "failed to call SetPrinter");
3966 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, p
, handle
, &change_id2
),
3967 "failed to query for ChangeID");
3968 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex2
),
3969 "failed to query for ChangeID");
3970 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, p
, handle
, &change_id_info2
),
3971 "failed to query for ChangeID");
3973 torture_assert_int_equal(tctx
, change_id2
, change_id_ex2
,
3974 "change_ids should all be equal");
3975 torture_assert_int_equal(tctx
, change_id_ex2
, change_id_info2
,
3976 "change_ids should all be equal");
3978 torture_assert(tctx
, (change_id
< change_id2
),
3979 talloc_asprintf(tctx
, "change_id %d needs to be larger than change_id %d",
3980 change_id2
, change_id
));
3981 torture_assert(tctx
, (change_id_ex
< change_id_ex2
),
3982 talloc_asprintf(tctx
, "change_id %d needs to be larger than change_id %d",
3983 change_id_ex2
, change_id_ex
));
3984 torture_assert(tctx
, (change_id_info
< change_id_info2
),
3985 talloc_asprintf(tctx
, "change_id %d needs to be larger than change_id %d",
3986 change_id_info2
, change_id_info
));
3991 static bool test_SecondaryClosePrinter(struct torture_context
*tctx
,
3992 struct dcerpc_pipe
*p
,
3993 struct policy_handle
*handle
)
3996 struct dcerpc_binding
*b
;
3997 struct dcerpc_pipe
*p2
;
3998 struct spoolss_ClosePrinter cp
;
4000 /* only makes sense on SMB */
4001 if (p
->conn
->transport
.transport
!= NCACN_NP
) {
4005 torture_comment(tctx
, "testing close on secondary pipe\n");
4007 status
= dcerpc_parse_binding(tctx
, p
->conn
->binding_string
, &b
);
4008 torture_assert_ntstatus_ok(tctx
, status
, "Failed to parse dcerpc binding");
4010 status
= dcerpc_secondary_connection(p
, &p2
, b
);
4011 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create secondary connection");
4013 status
= dcerpc_bind_auth_none(p2
, &ndr_table_spoolss
);
4014 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create bind on secondary connection");
4016 cp
.in
.handle
= handle
;
4017 cp
.out
.handle
= handle
;
4019 status
= dcerpc_spoolss_ClosePrinter(p2
, tctx
, &cp
);
4020 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_NET_WRITE_FAULT
,
4021 "ERROR: Allowed close on secondary connection");
4023 torture_assert_int_equal(tctx
, p2
->last_fault_code
, DCERPC_FAULT_CONTEXT_MISMATCH
,
4024 "Unexpected fault code");
4031 static bool test_OpenPrinter_badname(struct torture_context
*tctx
,
4032 struct dcerpc_pipe
*p
, const char *name
)
4035 struct spoolss_OpenPrinter op
;
4036 struct spoolss_OpenPrinterEx opEx
;
4037 struct policy_handle handle
;
4040 op
.in
.printername
= name
;
4041 op
.in
.datatype
= NULL
;
4042 op
.in
.devmode_ctr
.devmode
= NULL
;
4043 op
.in
.access_mask
= 0;
4044 op
.out
.handle
= &handle
;
4046 torture_comment(tctx
, "Testing OpenPrinter(%s) with bad name\n", op
.in
.printername
);
4048 status
= dcerpc_spoolss_OpenPrinter(p
, tctx
, &op
);
4049 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
4050 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME
,op
.out
.result
)) {
4051 torture_comment(tctx
, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
4052 name
, win_errstr(op
.out
.result
));
4055 if (W_ERROR_IS_OK(op
.out
.result
)) {
4056 ret
&=test_ClosePrinter(tctx
, p
, &handle
);
4059 opEx
.in
.printername
= name
;
4060 opEx
.in
.datatype
= NULL
;
4061 opEx
.in
.devmode_ctr
.devmode
= NULL
;
4062 opEx
.in
.access_mask
= 0;
4064 opEx
.in
.userlevel
.level1
= NULL
;
4065 opEx
.out
.handle
= &handle
;
4067 torture_comment(tctx
, "Testing OpenPrinterEx(%s) with bad name\n", opEx
.in
.printername
);
4069 status
= dcerpc_spoolss_OpenPrinterEx(p
, tctx
, &opEx
);
4070 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinterEx failed");
4071 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM
,opEx
.out
.result
)) {
4072 torture_comment(tctx
, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
4073 name
, win_errstr(opEx
.out
.result
));
4076 if (W_ERROR_IS_OK(opEx
.out
.result
)) {
4077 ret
&=test_ClosePrinter(tctx
, p
, &handle
);
4083 static bool test_OpenPrinter(struct torture_context
*tctx
,
4084 struct dcerpc_pipe
*p
,
4086 const char *environment
)
4089 struct spoolss_OpenPrinter r
;
4090 struct policy_handle handle
;
4093 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s\\%s", dcerpc_server_name(p
), name
);
4094 r
.in
.datatype
= NULL
;
4095 r
.in
.devmode_ctr
.devmode
= NULL
;
4096 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4097 r
.out
.handle
= &handle
;
4099 torture_comment(tctx
, "Testing OpenPrinter(%s)\n", r
.in
.printername
);
4101 status
= dcerpc_spoolss_OpenPrinter(p
, tctx
, &r
);
4103 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
4105 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenPrinter failed");
4107 if (!test_GetPrinter(tctx
, p
, &handle
, environment
)) {
4111 if (!torture_setting_bool(tctx
, "samba3", false)) {
4112 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
4117 if (!test_ClosePrinter(tctx
, p
, &handle
)) {
4124 static bool call_OpenPrinterEx(struct torture_context
*tctx
,
4125 struct dcerpc_pipe
*p
,
4127 struct spoolss_DeviceMode
*devmode
,
4128 struct policy_handle
*handle
)
4130 struct spoolss_OpenPrinterEx r
;
4131 struct spoolss_UserLevel1 userlevel1
;
4134 if (name
&& name
[0]) {
4135 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s\\%s",
4136 dcerpc_server_name(p
), name
);
4138 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s",
4139 dcerpc_server_name(p
));
4142 r
.in
.datatype
= NULL
;
4143 r
.in
.devmode_ctr
.devmode
= devmode
;
4144 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4146 r
.in
.userlevel
.level1
= &userlevel1
;
4147 r
.out
.handle
= handle
;
4149 userlevel1
.size
= 1234;
4150 userlevel1
.client
= "hello";
4151 userlevel1
.user
= "spottyfoot!";
4152 userlevel1
.build
= 1;
4153 userlevel1
.major
= 2;
4154 userlevel1
.minor
= 3;
4155 userlevel1
.processor
= 4;
4157 torture_comment(tctx
, "Testing OpenPrinterEx(%s)\n", r
.in
.printername
);
4159 status
= dcerpc_spoolss_OpenPrinterEx(p
, tctx
, &r
);
4161 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinterEx failed");
4163 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenPrinterEx failed");
4168 static bool test_printer_rename(struct torture_context
*tctx
,
4169 struct dcerpc_pipe
*p
,
4170 struct policy_handle
*handle
,
4174 union spoolss_PrinterInfo info
;
4175 union spoolss_SetPrinterInfo sinfo
;
4176 struct spoolss_SetPrinterInfoCtr info_ctr
;
4177 struct spoolss_DevmodeContainer devmode_ctr
;
4178 struct sec_desc_buf secdesc_ctr
;
4179 const char *printer_name
;
4180 const char *printer_name_orig
;
4181 const char *printer_name_new
= "SAMBA smbtorture Test Printer (Copy 2)";
4182 struct policy_handle new_handle
;
4185 ZERO_STRUCT(devmode_ctr
);
4186 ZERO_STRUCT(secdesc_ctr
);
4188 torture_comment(tctx
, "Testing Printer rename operations\n");
4190 torture_assert(tctx
,
4191 test_GetPrinter_level(tctx
, p
, handle
, 2, &info
),
4192 "failed to call GetPrinter level 2");
4194 printer_name_orig
= talloc_strdup(tctx
, info
.info2
.printername
);
4196 q
= strrchr(info
.info2
.printername
, '\\');
4198 torture_warning(tctx
,
4199 "server returns printername %s incl. servername although we did not set servername", info
.info2
.printername
);
4202 torture_assert(tctx
,
4203 PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
4205 sinfo
.info2
->printername
= printer_name_new
;
4208 info_ctr
.info
= sinfo
;
4210 torture_assert(tctx
,
4211 test_SetPrinter(tctx
, p
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0),
4212 "failed to call SetPrinter level 2");
4214 torture_assert(tctx
,
4215 test_GetPrinter_level(tctx
, p
, handle
, 2, &info
),
4216 "failed to call GetPrinter level 2");
4218 printer_name
= talloc_strdup(tctx
, info
.info2
.printername
);
4220 q
= strrchr(info
.info2
.printername
, '\\');
4222 torture_warning(tctx
,
4223 "server returns printername %s incl. servername although we did not set servername", info
.info2
.printername
);
4228 torture_assert_str_equal(tctx
, printer_name
, printer_name_new
,
4229 "new printer name was not set");
4231 torture_assert(tctx
,
4232 test_OpenPrinter_badname(tctx
, p
, printer_name_orig
),
4233 "still can open printer with oldname");
4235 torture_assert(tctx
,
4236 call_OpenPrinterEx(tctx
, p
, printer_name_new
, NULL
, &new_handle
),
4237 "failed to open printer with new name");
4239 torture_assert(tctx
,
4240 test_GetPrinter_level(tctx
, p
, &new_handle
, 2, &info
),
4241 "failed to call GetPrinter level 2");
4243 /* FIXME: we openend with servername! */
4244 printer_name
= talloc_asprintf(tctx
, "\\\\%s\\%s",
4245 dcerpc_server_name(p
), printer_name_new
);
4247 torture_assert_str_equal(tctx
, info
.info2
.printername
, printer_name
,
4248 "new printer name was not set");
4250 torture_assert(tctx
,
4251 test_ClosePrinter(tctx
, p
, &new_handle
),
4252 "failed to close printer");
4258 static bool test_OpenPrinterEx(struct torture_context
*tctx
,
4259 struct dcerpc_pipe
*p
,
4261 const char *environment
)
4263 struct policy_handle handle
;
4266 if (!call_OpenPrinterEx(tctx
, p
, name
, NULL
, &handle
)) {
4270 if (!test_PrinterInfo_SD(tctx
, p
, &handle
)) {
4274 if (!test_GetPrinter(tctx
, p
, &handle
, environment
)) {
4278 if (!test_EnumForms(tctx
, p
, &handle
, false)) {
4282 if (!test_AddForm(tctx
, p
, &handle
, false)) {
4286 if (!test_EnumPrinterData_all(tctx
, p
, &handle
)) {
4290 if (!test_EnumPrinterDataEx(tctx
, p
, &handle
, "PrinterDriverData", NULL
, NULL
)) {
4294 if (!test_EnumPrinterData_consistency(tctx
, p
, &handle
)) {
4298 if (!test_printer_keys(tctx
, p
, &handle
)) {
4302 if (!test_PausePrinter(tctx
, p
, &handle
)) {
4306 if (!test_DoPrintTest(tctx
, p
, &handle
)) {
4310 if (!test_ResumePrinter(tctx
, p
, &handle
)) {
4314 if (!test_SetPrinterData_matrix(tctx
, p
, &handle
, name
, NULL
, NULL
)) {
4318 if (!test_SetPrinterDataEx_matrix(tctx
, p
, &handle
, name
, NULL
, NULL
)) {
4322 if (!torture_setting_bool(tctx
, "samba3", false)) {
4323 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
4328 if (!test_ClosePrinter(tctx
, p
, &handle
)) {
4335 static bool test_EnumPrinters_old(struct torture_context
*tctx
,
4336 struct dcerpc_pipe
*p
,
4337 const char *environment
)
4339 struct spoolss_EnumPrinters r
;
4341 uint16_t levels
[] = {1, 2, 4, 5};
4345 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
4346 union spoolss_PrinterInfo
*info
;
4351 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
4353 r
.in
.level
= levels
[i
];
4356 r
.out
.needed
= &needed
;
4357 r
.out
.count
= &count
;
4360 torture_comment(tctx
, "Testing EnumPrinters level %u\n", r
.in
.level
);
4362 status
= dcerpc_spoolss_EnumPrinters(p
, tctx
, &r
);
4363 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
4365 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
4366 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
4367 data_blob_clear(&blob
);
4368 r
.in
.buffer
= &blob
;
4369 r
.in
.offered
= needed
;
4370 status
= dcerpc_spoolss_EnumPrinters(p
, tctx
, &r
);
4373 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
4375 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
4377 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
4380 torture_comment(tctx
, "No printers returned\n");
4384 for (j
=0;j
<count
;j
++) {
4385 if (r
.in
.level
== 1) {
4386 char *unc
= talloc_strdup(tctx
, info
[j
].info1
.name
);
4389 if (unc
[0] == '\\' && unc
[1] == '\\') {
4392 slash
= strchr(unc
, '\\');
4397 if (!test_OpenPrinter(tctx
, p
, name
, environment
)) {
4400 if (!test_OpenPrinterEx(tctx
, p
, name
, environment
)) {
4410 static bool test_GetPrinterDriver(struct torture_context
*tctx
,
4411 struct dcerpc_pipe
*p
,
4412 struct policy_handle
*handle
,
4413 const char *driver_name
)
4415 struct spoolss_GetPrinterDriver r
;
4418 r
.in
.handle
= handle
;
4419 r
.in
.architecture
= "W32X86";
4423 r
.out
.needed
= &needed
;
4425 torture_comment(tctx
, "Testing GetPrinterDriver level %d\n", r
.in
.level
);
4427 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver(p
, tctx
, &r
),
4428 "failed to call GetPrinterDriver");
4429 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
4430 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
4431 data_blob_clear(&blob
);
4432 r
.in
.buffer
= &blob
;
4433 r
.in
.offered
= needed
;
4434 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver(p
, tctx
, &r
),
4435 "failed to call GetPrinterDriver");
4438 torture_assert_werr_ok(tctx
, r
.out
.result
,
4439 "failed to call GetPrinterDriver");
4441 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
4446 static bool test_GetPrinterDriver2(struct torture_context
*tctx
,
4447 struct dcerpc_pipe
*p
,
4448 struct policy_handle
*handle
,
4449 const char *driver_name
,
4450 const char *architecture
)
4452 struct spoolss_GetPrinterDriver2 r
;
4453 uint16_t levels
[] = {1, 2, 3, 4, 5, 6, 8, 101 };
4455 uint32_t server_major_version
;
4456 uint32_t server_minor_version
;
4459 r
.in
.handle
= handle
;
4460 r
.in
.architecture
= architecture
;
4461 r
.in
.client_major_version
= 3;
4462 r
.in
.client_minor_version
= 0;
4463 r
.out
.needed
= &needed
;
4464 r
.out
.server_major_version
= &server_major_version
;
4465 r
.out
.server_minor_version
= &server_minor_version
;
4467 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
4471 r
.in
.level
= levels
[i
];
4473 torture_comment(tctx
, "Testing GetPrinterDriver2(%s) level %d\n",
4474 driver_name
, r
.in
.level
);
4476 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver2(p
, tctx
, &r
),
4477 "failed to call GetPrinterDriver2");
4478 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
4479 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
4480 data_blob_clear(&blob
);
4481 r
.in
.buffer
= &blob
;
4482 r
.in
.offered
= needed
;
4483 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver2(p
, tctx
, &r
),
4484 "failed to call GetPrinterDriver2");
4487 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INVALID_LEVEL
)) {
4488 switch (r
.in
.level
) {
4497 torture_assert_werr_ok(tctx
, r
.out
.result
,
4498 "failed to call GetPrinterDriver2");
4500 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
4506 static bool test_EnumPrinterDrivers_old(struct torture_context
*tctx
,
4507 struct dcerpc_pipe
*p
,
4508 const char *environment
)
4510 struct spoolss_EnumPrinterDrivers r
;
4512 uint16_t levels
[] = {1, 2, 3, 4, 5, 6};
4515 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
4519 union spoolss_DriverInfo
*info
;
4521 r
.in
.server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
4522 r
.in
.environment
= environment
;
4523 r
.in
.level
= levels
[i
];
4526 r
.out
.needed
= &needed
;
4527 r
.out
.count
= &count
;
4530 torture_comment(tctx
, "Testing EnumPrinterDrivers level %u\n", r
.in
.level
);
4532 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, tctx
, &r
);
4534 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterDrivers failed");
4536 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
4537 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
4538 data_blob_clear(&blob
);
4539 r
.in
.buffer
= &blob
;
4540 r
.in
.offered
= needed
;
4541 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, tctx
, &r
);
4544 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterDrivers failed");
4546 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDrivers failed");
4549 torture_comment(tctx
, "No printer drivers returned\n");
4553 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
4559 static bool test_DeletePrinter(struct torture_context
*tctx
,
4560 struct dcerpc_pipe
*p
,
4561 struct policy_handle
*handle
)
4563 struct spoolss_DeletePrinter r
;
4565 torture_comment(tctx
, "Testing DeletePrinter\n");
4567 r
.in
.handle
= handle
;
4569 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_DeletePrinter(p
, tctx
, &r
),
4570 "failed to delete printer");
4571 torture_assert_werr_ok(tctx
, r
.out
.result
,
4572 "failed to delete printer");
4577 static bool test_EnumPrinters_findname(struct torture_context
*tctx
,
4578 struct dcerpc_pipe
*p
,
4584 struct spoolss_EnumPrinters e
;
4586 union spoolss_PrinterInfo
*info
;
4597 e
.out
.count
= &count
;
4599 e
.out
.needed
= &needed
;
4601 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters(p
, tctx
, &e
),
4602 "failed to enum printers");
4604 if (W_ERROR_EQUAL(e
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
4605 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
4606 data_blob_clear(&blob
);
4607 e
.in
.buffer
= &blob
;
4608 e
.in
.offered
= needed
;
4610 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters(p
, tctx
, &e
),
4611 "failed to enum printers");
4614 torture_assert_werr_ok(tctx
, e
.out
.result
,
4615 "failed to enum printers");
4617 for (i
=0; i
< count
; i
++) {
4619 const char *current
= NULL
;
4624 current
= info
[i
].info1
.name
;
4628 if (strequal(current
, name
)) {
4633 q
= strrchr(current
, '\\');
4636 torture_warning(tctx
,
4637 "server returns printername %s incl. servername although we did not set servername", current
);
4640 if (strequal(q
, name
)) {
4650 static bool test_AddPrinter_wellknown(struct torture_context
*tctx
,
4651 struct dcerpc_pipe
*p
,
4652 const char *printername
,
4656 struct spoolss_AddPrinter r
;
4657 struct spoolss_AddPrinterEx rex
;
4658 struct spoolss_SetPrinterInfoCtr info_ctr
;
4659 struct spoolss_SetPrinterInfo1 info1
;
4660 struct spoolss_DevmodeContainer devmode_ctr
;
4661 struct sec_desc_buf secdesc_ctr
;
4662 struct spoolss_UserLevelCtr userlevel_ctr
;
4663 struct policy_handle handle
;
4666 ZERO_STRUCT(devmode_ctr
);
4667 ZERO_STRUCT(secdesc_ctr
);
4668 ZERO_STRUCT(userlevel_ctr
);
4671 torture_comment(tctx
, "Testing AddPrinter%s level 1\n", ex
? "Ex":"");
4673 /* try to add printer to wellknown printer list (level 1) */
4675 userlevel_ctr
.level
= 1;
4677 info_ctr
.info
.info1
= &info1
;
4680 rex
.in
.server
= NULL
;
4681 rex
.in
.info_ctr
= &info_ctr
;
4682 rex
.in
.devmode_ctr
= &devmode_ctr
;
4683 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
4684 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
4685 rex
.out
.handle
= &handle
;
4688 r
.in
.info_ctr
= &info_ctr
;
4689 r
.in
.devmode_ctr
= &devmode_ctr
;
4690 r
.in
.secdesc_ctr
= &secdesc_ctr
;
4691 r
.out
.handle
= &handle
;
4693 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
4694 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
4695 "failed to add printer");
4696 result
= ex
? rex
.out
.result
: r
.out
.result
;
4697 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
4698 "unexpected result code");
4700 info1
.name
= printername
;
4701 info1
.flags
= PRINTER_ATTRIBUTE_SHARED
;
4703 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
4704 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
4705 "failed to add printer");
4706 result
= ex
? rex
.out
.result
: r
.out
.result
;
4707 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
4708 "unexpected result code");
4710 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
4711 better do a real check to see the printer is really there */
4713 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, p
,
4714 PRINTER_ENUM_NETWORK
, 1,
4717 "failed to enum printers");
4719 torture_assert(tctx
, found
, "failed to find newly added printer");
4723 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
4724 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
4725 "failed to add printer");
4726 result
= ex
? rex
.out
.result
: r
.out
.result
;
4727 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
4728 "unexpected result code");
4730 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
4731 better do a real check to see the printer has really been removed
4732 from the well known printer list */
4736 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, p
,
4737 PRINTER_ENUM_NETWORK
, 1,
4740 "failed to enum printers");
4742 torture_assert(tctx
, !found
, "printer still in well known printer list");
4747 static bool test_AddPrinter_normal(struct torture_context
*tctx
,
4748 struct dcerpc_pipe
*p
,
4749 struct policy_handle
*handle_p
,
4750 const char *printername
,
4751 const char *drivername
,
4752 const char *portname
,
4756 struct spoolss_AddPrinter r
;
4757 struct spoolss_AddPrinterEx rex
;
4758 struct spoolss_SetPrinterInfoCtr info_ctr
;
4759 struct spoolss_SetPrinterInfo2 info2
;
4760 struct spoolss_DevmodeContainer devmode_ctr
;
4761 struct sec_desc_buf secdesc_ctr
;
4762 struct spoolss_UserLevelCtr userlevel_ctr
;
4763 struct policy_handle handle
;
4765 bool existing_printer_deleted
= false;
4767 ZERO_STRUCT(devmode_ctr
);
4768 ZERO_STRUCT(secdesc_ctr
);
4769 ZERO_STRUCT(userlevel_ctr
);
4771 torture_comment(tctx
, "Testing AddPrinter%s level 2\n", ex
? "Ex":"");
4773 userlevel_ctr
.level
= 1;
4775 rex
.in
.server
= NULL
;
4776 rex
.in
.info_ctr
= &info_ctr
;
4777 rex
.in
.devmode_ctr
= &devmode_ctr
;
4778 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
4779 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
4780 rex
.out
.handle
= &handle
;
4783 r
.in
.info_ctr
= &info_ctr
;
4784 r
.in
.devmode_ctr
= &devmode_ctr
;
4785 r
.in
.secdesc_ctr
= &secdesc_ctr
;
4786 r
.out
.handle
= &handle
;
4790 /* try to add printer to printer list (level 2) */
4794 info_ctr
.info
.info2
= &info2
;
4797 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
4798 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
4799 "failed to add printer");
4800 result
= ex
? rex
.out
.result
: r
.out
.result
;
4801 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
4802 "unexpected result code");
4804 info2
.printername
= printername
;
4806 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
4807 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
4808 "failed to add printer");
4809 result
= ex
? rex
.out
.result
: r
.out
.result
;
4811 if (W_ERROR_EQUAL(result
, WERR_PRINTER_ALREADY_EXISTS
)) {
4812 struct policy_handle printer_handle
;
4814 if (existing_printer_deleted
) {
4815 torture_fail(tctx
, "already deleted printer still existing?");
4818 torture_assert(tctx
, call_OpenPrinterEx(tctx
, p
, printername
, NULL
, &printer_handle
),
4819 "failed to open printer handle");
4821 torture_assert(tctx
, test_DeletePrinter(tctx
, p
, &printer_handle
),
4822 "failed to delete printer");
4824 torture_assert(tctx
, test_ClosePrinter(tctx
, p
, &printer_handle
),
4825 "failed to close server handle");
4827 existing_printer_deleted
= true;
4832 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PORT
,
4833 "unexpected result code");
4835 info2
.portname
= portname
;
4837 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
4838 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
4839 "failed to add printer");
4840 result
= ex
? rex
.out
.result
: r
.out
.result
;
4841 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTER_DRIVER
,
4842 "unexpected result code");
4844 info2
.drivername
= drivername
;
4846 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
4847 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
4848 "failed to add printer");
4849 result
= ex
? rex
.out
.result
: r
.out
.result
;
4851 /* w2k8r2 allows to add printer w/o defining printprocessor */
4853 if (!W_ERROR_IS_OK(result
)) {
4854 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTPROCESSOR
,
4855 "unexpected result code");
4857 info2
.printprocessor
= "winprint";
4859 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
4860 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
4861 "failed to add printer");
4862 result
= ex
? rex
.out
.result
: r
.out
.result
;
4863 torture_assert_werr_ok(tctx
, result
,
4864 "failed to add printer");
4869 /* we are paranoid, really check if the printer is there now */
4871 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, p
,
4872 PRINTER_ENUM_LOCAL
, 1,
4875 "failed to enum printers");
4876 torture_assert(tctx
, found
, "failed to find newly added printer");
4878 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
4879 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
4880 "failed to add printer");
4881 result
= ex
? rex
.out
.result
: r
.out
.result
;
4882 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
4883 "unexpected result code");
4888 static bool test_AddPrinterEx(struct torture_context
*tctx
,
4889 struct dcerpc_pipe
*p
,
4890 struct policy_handle
*handle_p
,
4891 const char *printername
,
4892 const char *drivername
,
4893 const char *portname
)
4897 if (!torture_setting_bool(tctx
, "samba3", false)) {
4898 if (!test_AddPrinter_wellknown(tctx
, p
, TORTURE_WELLKNOWN_PRINTER_EX
, true)) {
4899 torture_comment(tctx
, "failed to add printer to well known list\n");
4904 if (!test_AddPrinter_normal(tctx
, p
, handle_p
,
4905 printername
, drivername
, portname
,
4907 torture_comment(tctx
, "failed to add printer to printer list\n");
4914 static bool test_AddPrinter(struct torture_context
*tctx
,
4915 struct dcerpc_pipe
*p
,
4916 struct policy_handle
*handle_p
,
4917 const char *printername
,
4918 const char *drivername
,
4919 const char *portname
)
4923 if (!torture_setting_bool(tctx
, "samba3", false)) {
4924 if (!test_AddPrinter_wellknown(tctx
, p
, TORTURE_WELLKNOWN_PRINTER
, false)) {
4925 torture_comment(tctx
, "failed to add printer to well known list\n");
4930 if (!test_AddPrinter_normal(tctx
, p
, handle_p
,
4931 printername
, drivername
, portname
,
4933 torture_comment(tctx
, "failed to add printer to printer list\n");
4940 static bool test_printer_info(struct torture_context
*tctx
,
4941 struct dcerpc_pipe
*p
,
4942 struct policy_handle
*handle
)
4946 if (torture_setting_bool(tctx
, "samba3", false)) {
4947 torture_skip(tctx
, "skipping printer info cross tests against samba 3");
4950 if (!test_PrinterInfo(tctx
, p
, handle
)) {
4954 if (!test_SetPrinter_errors(tctx
, p
, handle
)) {
4961 static bool test_EnumPrinterKey(struct torture_context
*tctx
,
4962 struct dcerpc_pipe
*p
,
4963 struct policy_handle
*handle
,
4964 const char *key_name
,
4965 const char ***array
)
4967 struct spoolss_EnumPrinterKey r
;
4968 uint32_t needed
= 0;
4969 union spoolss_KeyNames key_buffer
;
4970 int32_t offered
[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
4974 r
.in
.handle
= handle
;
4975 r
.in
.key_name
= key_name
;
4976 r
.out
.key_buffer
= &key_buffer
;
4977 r
.out
.needed
= &needed
;
4978 r
.out
._ndr_size
= &_ndr_size
;
4980 for (i
=0; i
< ARRAY_SIZE(offered
); i
++) {
4982 if (offered
[i
] < 0 && needed
) {
4986 r
.in
.offered
= needed
+ offered
[i
];
4988 r
.in
.offered
= offered
[i
];
4991 ZERO_STRUCT(key_buffer
);
4993 torture_comment(tctx
, "Testing EnumPrinterKey(%s) with %d offered\n", r
.in
.key_name
, r
.in
.offered
);
4995 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterKey(p
, tctx
, &r
),
4996 "failed to call EnumPrinterKey");
4997 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
4999 torture_assert(tctx
, (_ndr_size
== r
.in
.offered
/2),
5000 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
5001 _ndr_size
, r
.in
.offered
/2));
5003 r
.in
.offered
= needed
;
5004 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterKey(p
, tctx
, &r
),
5005 "failed to call EnumPrinterKey");
5008 if (offered
[i
] > 0) {
5009 torture_assert_werr_ok(tctx
, r
.out
.result
,
5010 "failed to call EnumPrinterKey");
5013 torture_assert(tctx
, (_ndr_size
== r
.in
.offered
/2),
5014 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
5015 _ndr_size
, r
.in
.offered
/2));
5017 torture_assert(tctx
, (*r
.out
.needed
<= r
.in
.offered
),
5018 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r
.out
.needed
, r
.in
.offered
));
5020 torture_assert(tctx
, (*r
.out
.needed
<= _ndr_size
* 2),
5021 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r
.out
.needed
, _ndr_size
));
5023 if (key_buffer
.string_array
) {
5024 uint32_t calc_needed
= 0;
5026 for (s
=0; key_buffer
.string_array
[s
]; s
++) {
5027 calc_needed
+= strlen_m_term(key_buffer
.string_array
[s
])*2;
5029 if (!key_buffer
.string_array
[0]) {
5034 torture_assert_int_equal(tctx
, *r
.out
.needed
, calc_needed
,
5035 "EnumPrinterKey unexpected size");
5040 *array
= key_buffer
.string_array
;
5046 bool test_printer_keys(struct torture_context
*tctx
,
5047 struct dcerpc_pipe
*p
,
5048 struct policy_handle
*handle
)
5050 const char **key_array
= NULL
;
5053 torture_comment(tctx
, "\nTesting Printer Keys\n");
5055 torture_assert(tctx
, test_EnumPrinterKey(tctx
, p
, handle
, "", &key_array
),
5056 "failed to call test_EnumPrinterKey");
5058 for (i
=0; key_array
&& key_array
[i
]; i
++) {
5059 torture_assert(tctx
, test_EnumPrinterKey(tctx
, p
, handle
, key_array
[i
], NULL
),
5060 "failed to call test_EnumPrinterKey");
5062 for (i
=0; key_array
&& key_array
[i
]; i
++) {
5063 torture_assert(tctx
, test_EnumPrinterDataEx(tctx
, p
, handle
, key_array
[i
], NULL
, NULL
),
5064 "failed to call test_EnumPrinterDataEx");
5070 static bool test_one_printer(struct torture_context
*tctx
,
5071 struct dcerpc_pipe
*p
,
5072 struct policy_handle
*handle
,
5077 if (!test_printer_info(tctx
, p
, handle
)) {
5081 if (!test_PrinterInfo_SD(tctx
, p
, handle
)) {
5085 if (!test_PrinterInfo_DevMode(tctx
, p
, handle
, name
)) {
5089 if (!test_ChangeID(tctx
, p
, handle
)) {
5093 if (!test_printer_keys(tctx
, p
, handle
)) {
5097 if (!test_EnumPrinterData_consistency(tctx
, p
, handle
)) {
5101 if (!test_SetPrinterDataEx_matrix(tctx
, p
, handle
, name
, NULL
, NULL
)) {
5105 if (!test_PrinterData_winreg(tctx
, p
, handle
, name
)) {
5109 if (!test_printer_rename(tctx
, p
, handle
, name
)) {
5116 static bool test_printer(struct torture_context
*tctx
,
5117 struct dcerpc_pipe
*p
)
5120 struct policy_handle handle
[2];
5122 const char *drivername
= "Microsoft XPS Document Writer";
5123 const char *portname
= "LPT1:";
5125 /* test printer created via AddPrinter */
5127 if (!test_AddPrinter(tctx
, p
, &handle
[0], TORTURE_PRINTER
, drivername
, portname
)) {
5131 if (!test_one_printer(tctx
, p
, &handle
[0], TORTURE_PRINTER
)) {
5135 if (!test_DeletePrinter(tctx
, p
, &handle
[0])) {
5139 if (!test_EnumPrinters_findname(tctx
, p
, PRINTER_ENUM_LOCAL
, 1,
5140 TORTURE_PRINTER
, &found
)) {
5144 torture_assert(tctx
, !found
, "deleted printer still there");
5146 /* test printer created via AddPrinterEx */
5148 if (!test_AddPrinterEx(tctx
, p
, &handle
[1], TORTURE_PRINTER_EX
, drivername
, portname
)) {
5152 if (!test_one_printer(tctx
, p
, &handle
[1], TORTURE_PRINTER_EX
)) {
5156 if (!test_DeletePrinter(tctx
, p
, &handle
[1])) {
5160 if (!test_EnumPrinters_findname(tctx
, p
, PRINTER_ENUM_LOCAL
, 1,
5161 TORTURE_PRINTER_EX
, &found
)) {
5165 torture_assert(tctx
, !found
, "deleted printer still there");
5170 static bool test_architecture_buffer(struct torture_context
*tctx
,
5171 struct dcerpc_pipe
*p
)
5173 struct spoolss_OpenPrinterEx r
;
5174 struct spoolss_UserLevel1 u1
;
5175 struct policy_handle handle
;
5176 uint32_t architectures
[] = {
5177 PROCESSOR_ARCHITECTURE_INTEL
,
5178 PROCESSOR_ARCHITECTURE_IA64
,
5179 PROCESSOR_ARCHITECTURE_AMD64
5184 for (i
=0; i
< ARRAY_SIZE(architectures
); i
++) {
5186 torture_comment(tctx
, "Testing OpenPrinterEx with architecture %d\n", architectures
[i
]);
5194 u1
.processor
= architectures
[i
];
5196 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
5197 r
.in
.datatype
= NULL
;
5198 r
.in
.devmode_ctr
.devmode
= NULL
;
5199 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
5201 r
.in
.userlevel
.level1
= &u1
;
5202 r
.out
.handle
= &handle
;
5204 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_OpenPrinterEx(p
, tctx
, &r
), "");
5205 torture_assert_werr_ok(tctx
, r
.out
.result
, "");
5208 struct spoolss_EnumPrinters e
;
5210 union spoolss_PrinterInfo
*info
;
5212 e
.in
.flags
= PRINTER_ENUM_LOCAL
;
5217 e
.out
.count
= &count
;
5219 e
.out
.needed
= &needed
[i
];
5221 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters(p
, tctx
, &e
), "");
5223 torture_comment(tctx
, "needed was %d\n", needed
[i
]);
5227 torture_assert(tctx
, test_ClosePrinter(tctx
, p
, &handle
), "");
5230 for (i
=1; i
< ARRAY_SIZE(architectures
); i
++) {
5231 if (needed
[i
-1] != needed
[i
]) {
5233 talloc_asprintf(tctx
, "needed size %d for architecture %d != needed size %d for architecture %d\n",
5234 needed
[i
-1], architectures
[i
-1], needed
[i
], architectures
[i
]));
5241 bool torture_rpc_spoolss(struct torture_context
*torture
)
5244 struct dcerpc_pipe
*p
;
5246 struct test_spoolss_context
*ctx
;
5247 const char *environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
5249 status
= torture_rpc_connection(torture
, &p
, &ndr_table_spoolss
);
5250 if (!NT_STATUS_IS_OK(status
)) {
5254 ctx
= talloc_zero(torture
, struct test_spoolss_context
);
5256 ret
&= test_OpenPrinter_server(torture
, p
, &ctx
->server_handle
);
5257 ret
&= test_GetPrinterData_list(torture
, p
, &ctx
->server_handle
, &environment
);
5258 ret
&= test_EnumForms(torture
, p
, &ctx
->server_handle
, true);
5259 ret
&= test_AddForm(torture
, p
, &ctx
->server_handle
, true);
5260 ret
&= test_EnumPorts(torture
, p
, ctx
);
5261 ret
&= test_GetPrinterDriverDirectory(torture
, p
, ctx
, environment
);
5262 ret
&= test_GetPrintProcessorDirectory(torture
, p
, ctx
, environment
);
5263 ret
&= test_EnumPrinterDrivers(torture
, p
, ctx
, environment
);
5264 ret
&= test_EnumPrinterDrivers(torture
, p
, ctx
, SPOOLSS_ARCHITECTURE_ALL
);
5265 ret
&= test_EnumMonitors(torture
, p
, ctx
);
5266 ret
&= test_EnumPrintProcessors(torture
, p
, ctx
, environment
);
5267 ret
&= test_EnumPrintProcDataTypes(torture
, p
, ctx
);
5268 ret
&= test_EnumPrinters(torture
, p
, ctx
);
5269 ret
&= test_OpenPrinter_badname(torture
, p
, "__INVALID_PRINTER__");
5270 ret
&= test_OpenPrinter_badname(torture
, p
, "\\\\__INVALID_HOST__");
5271 ret
&= test_OpenPrinter_badname(torture
, p
, "");
5272 ret
&= test_OpenPrinter_badname(torture
, p
, "\\\\\\");
5273 ret
&= test_OpenPrinter_badname(torture
, p
, "\\\\\\__INVALID_PRINTER__");
5274 ret
&= test_OpenPrinter_badname(torture
, p
, talloc_asprintf(torture
, "\\\\%s\\", dcerpc_server_name(p
)));
5275 ret
&= test_OpenPrinter_badname(torture
, p
,
5276 talloc_asprintf(torture
, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p
)));
5279 ret
&= test_AddPort(torture
, p
);
5280 ret
&= test_EnumPorts_old(torture
, p
);
5281 ret
&= test_EnumPrinters_old(torture
, p
, environment
);
5282 ret
&= test_EnumPrinterDrivers_old(torture
, p
, environment
);
5283 ret
&= test_architecture_buffer(torture
, p
);
5288 struct torture_suite
*torture_rpc_spoolss_printer(TALLOC_CTX
*mem_ctx
)
5290 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "SPOOLSS-PRINTER");
5292 struct torture_rpc_tcase
*tcase
= torture_suite_add_rpc_iface_tcase(suite
,
5293 "printer", &ndr_table_spoolss
);
5295 torture_rpc_tcase_add_test(tcase
, "printer", test_printer
);