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
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 "torture/rpc/rpc.h"
27 #include "librpc/gen_ndr/ndr_misc.h"
28 #include "librpc/gen_ndr/ndr_spoolss.h"
29 #include "librpc/gen_ndr/ndr_spoolss_c.h"
30 #include "param/param.h"
32 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
33 #define TORTURE_PRINTER "torture_printer"
34 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
35 #define TORTURE_PRINTER_EX "torture_printer_ex"
37 struct test_spoolss_context
{
38 /* print server handle */
39 struct policy_handle server_handle
;
42 uint32_t port_count
[3];
43 union spoolss_PortInfo
*ports
[3];
45 /* for EnumPrinterDrivers */
46 uint32_t driver_count
[8];
47 union spoolss_DriverInfo
*drivers
[8];
49 /* for EnumMonitors */
50 uint32_t monitor_count
[3];
51 union spoolss_MonitorInfo
*monitors
[3];
53 /* for EnumPrintProcessors */
54 uint32_t print_processor_count
[2];
55 union spoolss_PrintProcessorInfo
*print_processors
[2];
57 /* for EnumPrinters */
58 uint32_t printer_count
[6];
59 union spoolss_PrinterInfo
*printers
[6];
62 #define COMPARE_STRING(tctx, c,r,e) \
63 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
65 /* not every compiler supports __typeof__() */
67 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
68 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
69 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
71 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
72 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
76 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
79 #define COMPARE_UINT32(tctx, c, r, e) do {\
80 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
81 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
84 #define COMPARE_UINT64(tctx, c, r, e) do {\
85 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
86 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
90 #define COMPARE_NTTIME(tctx, c, r, e) do {\
91 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
92 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
95 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
101 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
104 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
106 for (__i=0;c.e[__i] != NULL; __i++) { \
107 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
111 #define CHECK_ALIGN(size, n) do {\
113 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
114 size, n, size + n - (size % n));\
118 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
120 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, ic, needed, align) do { \
121 uint32_t size = ndr_size_##fn##_info(tctx, ic, level, count, info);\
122 uint32_t round_size = DO_ROUND(size, align);\
123 if (round_size != needed) {\
124 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
125 CHECK_ALIGN(size, align);\
129 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, ic, needed, align) do { \
130 uint32_t size = ndr_size_##fn##_info(tctx, ic, count, info);\
131 uint32_t round_size = DO_ROUND(size, align);\
132 if (round_size != needed) {\
133 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
134 CHECK_ALIGN(size, align);\
138 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, ic, needed, align) do { \
139 uint32_t size = ndr_size_##fn(info, level, ic, 0);\
140 uint32_t round_size = DO_ROUND(size, align);\
141 if (round_size != needed) {\
142 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
143 CHECK_ALIGN(size, align);\
147 static bool test_OpenPrinter_server(struct torture_context
*tctx
,
148 struct dcerpc_pipe
*p
,
149 struct policy_handle
*server_handle
)
152 struct spoolss_OpenPrinter op
;
154 op
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
155 op
.in
.datatype
= NULL
;
156 op
.in
.devmode_ctr
.devmode
= NULL
;
157 op
.in
.access_mask
= 0;
158 op
.out
.handle
= server_handle
;
160 torture_comment(tctx
, "Testing OpenPrinter(%s)\n", op
.in
.printername
);
162 status
= dcerpc_spoolss_OpenPrinter(p
, tctx
, &op
);
163 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_OpenPrinter failed");
164 torture_assert_werr_ok(tctx
, op
.out
.result
, "dcerpc_spoolss_OpenPrinter failed");
169 static bool test_EnumPorts(struct torture_context
*tctx
,
170 struct dcerpc_pipe
*p
,
171 struct test_spoolss_context
*ctx
)
174 struct spoolss_EnumPorts r
;
175 uint16_t levels
[] = { 1, 2 };
178 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
179 int level
= levels
[i
];
183 union spoolss_PortInfo
*info
;
185 r
.in
.servername
= "";
189 r
.out
.needed
= &needed
;
190 r
.out
.count
= &count
;
193 torture_comment(tctx
, "Testing EnumPorts level %u\n", r
.in
.level
);
195 status
= dcerpc_spoolss_EnumPorts(p
, ctx
, &r
);
196 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPorts failed");
197 if (W_ERROR_IS_OK(r
.out
.result
)) {
198 /* TODO: do some more checks here */
201 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
202 "EnumPorts unexpected return code");
204 blob
= data_blob_talloc(ctx
, NULL
, needed
);
205 data_blob_clear(&blob
);
207 r
.in
.offered
= needed
;
209 status
= dcerpc_spoolss_EnumPorts(p
, ctx
, &r
);
210 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPorts failed");
212 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
214 torture_assert(tctx
, info
, "EnumPorts returned no info");
216 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
218 ctx
->port_count
[level
] = count
;
219 ctx
->ports
[level
] = info
;
222 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
223 int level
= levels
[i
];
224 int old_level
= levels
[i
-1];
225 torture_assert_int_equal(tctx
, ctx
->port_count
[level
], ctx
->port_count
[old_level
],
226 "EnumPorts invalid value");
228 /* if the array sizes are not the same we would maybe segfault in the following code */
230 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
231 int level
= levels
[i
];
232 for (j
=0;j
<ctx
->port_count
[level
];j
++) {
233 union spoolss_PortInfo
*cur
= &ctx
->ports
[level
][j
];
234 union spoolss_PortInfo
*ref
= &ctx
->ports
[2][j
];
237 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, port_name
);
240 /* level 2 is our reference, and it makes no sense to compare it to itself */
249 static bool test_GetPrintProcessorDirectory(struct torture_context
*tctx
,
250 struct dcerpc_pipe
*p
,
251 struct test_spoolss_context
*ctx
)
254 struct spoolss_GetPrintProcessorDirectory r
;
269 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
272 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
278 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
279 int level
= levels
[i
].level
;
282 r
.in
.server
= levels
[i
].server
;
283 r
.in
.environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
287 r
.out
.needed
= &needed
;
289 torture_comment(tctx
, "Testing GetPrintProcessorDirectory level %u\n", r
.in
.level
);
291 status
= dcerpc_spoolss_GetPrintProcessorDirectory(p
, ctx
, &r
);
292 torture_assert_ntstatus_ok(tctx
, status
,
293 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
294 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
295 "GetPrintProcessorDirectory unexpected return code");
297 blob
= data_blob_talloc(ctx
, NULL
, needed
);
298 data_blob_clear(&blob
);
300 r
.in
.offered
= needed
;
302 status
= dcerpc_spoolss_GetPrintProcessorDirectory(p
, ctx
, &r
);
303 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
305 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrintProcessorDirectory failed");
307 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 2);
314 static bool test_GetPrinterDriverDirectory(struct torture_context
*tctx
,
315 struct dcerpc_pipe
*p
,
316 struct test_spoolss_context
*ctx
)
319 struct spoolss_GetPrinterDriverDirectory r
;
334 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
337 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
343 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
344 int level
= levels
[i
].level
;
347 r
.in
.server
= levels
[i
].server
;
348 r
.in
.environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
352 r
.out
.needed
= &needed
;
354 torture_comment(tctx
, "Testing GetPrinterDriverDirectory level %u\n", r
.in
.level
);
356 status
= dcerpc_spoolss_GetPrinterDriverDirectory(p
, ctx
, &r
);
357 torture_assert_ntstatus_ok(tctx
, status
,
358 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
359 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
360 "GetPrinterDriverDirectory unexpected return code");
362 blob
= data_blob_talloc(ctx
, NULL
, needed
);
363 data_blob_clear(&blob
);
365 r
.in
.offered
= needed
;
367 status
= dcerpc_spoolss_GetPrinterDriverDirectory(p
, ctx
, &r
);
368 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
370 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrinterDriverDirectory failed");
372 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 2);
378 static bool test_EnumPrinterDrivers(struct torture_context
*tctx
,
379 struct dcerpc_pipe
*p
,
380 struct test_spoolss_context
*ctx
,
381 const char *architecture
)
384 struct spoolss_EnumPrinterDrivers r
;
385 uint16_t levels
[] = { 1, 2, 3, 4, 5, 6, 8 };
388 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
389 int level
= levels
[i
];
393 union spoolss_DriverInfo
*info
;
395 /* FIXME: gd, come back and fix "" as server, and handle
396 * priority of returned error codes in torture test and samba 3
399 r
.in
.server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
400 r
.in
.environment
= architecture
;
404 r
.out
.needed
= &needed
;
405 r
.out
.count
= &count
;
408 torture_comment(tctx
, "Testing EnumPrinterDrivers level %u (%s)\n", r
.in
.level
, r
.in
.environment
);
410 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, ctx
, &r
);
411 torture_assert_ntstatus_ok(tctx
, status
,
412 "dcerpc_spoolss_EnumPrinterDrivers failed");
413 if (W_ERROR_IS_OK(r
.out
.result
)) {
414 /* TODO: do some more checks here */
417 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
418 blob
= data_blob_talloc(ctx
, NULL
, needed
);
419 data_blob_clear(&blob
);
421 r
.in
.offered
= needed
;
423 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, ctx
, &r
);
424 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinterDrivers failed");
427 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDrivers failed");
429 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
431 ctx
->driver_count
[level
] = count
;
432 ctx
->drivers
[level
] = info
;
435 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
436 int level
= levels
[i
];
437 int old_level
= levels
[i
-1];
439 torture_assert_int_equal(tctx
, ctx
->driver_count
[level
], ctx
->driver_count
[old_level
],
440 "EnumPrinterDrivers invalid value");
443 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
444 int level
= levels
[i
];
446 for (j
=0;j
<ctx
->driver_count
[level
];j
++) {
447 union spoolss_DriverInfo
*cur
= &ctx
->drivers
[level
][j
];
448 union spoolss_DriverInfo
*ref
= &ctx
->drivers
[8][j
];
452 COMPARE_STRING(tctx
, cur
->info1
, ref
->info8
, driver_name
);
455 COMPARE_UINT32(tctx
, cur
->info2
, ref
->info8
, version
);
456 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, driver_name
);
457 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, architecture
);
458 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, driver_path
);
459 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, data_file
);
460 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, config_file
);
463 COMPARE_UINT32(tctx
, cur
->info3
, ref
->info8
, version
);
464 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, driver_name
);
465 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, architecture
);
466 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, driver_path
);
467 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, data_file
);
468 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, config_file
);
469 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, help_file
);
470 COMPARE_STRING_ARRAY(tctx
, cur
->info3
, ref
->info8
, dependent_files
);
471 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, monitor_name
);
472 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, default_datatype
);
475 COMPARE_UINT32(tctx
, cur
->info4
, ref
->info8
, version
);
476 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, driver_name
);
477 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, architecture
);
478 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, driver_path
);
479 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, data_file
);
480 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, config_file
);
481 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, help_file
);
482 COMPARE_STRING_ARRAY(tctx
, cur
->info4
, ref
->info8
, dependent_files
);
483 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, monitor_name
);
484 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, default_datatype
);
485 COMPARE_STRING_ARRAY(tctx
, cur
->info4
, ref
->info8
, previous_names
);
488 COMPARE_UINT32(tctx
, cur
->info5
, ref
->info8
, version
);
489 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, driver_name
);
490 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, architecture
);
491 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, driver_path
);
492 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, data_file
);
493 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, config_file
);
494 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
495 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
496 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
499 COMPARE_UINT32(tctx
, cur
->info6
, ref
->info8
, version
);
500 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, driver_name
);
501 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, architecture
);
502 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, driver_path
);
503 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, data_file
);
504 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, config_file
);
505 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, help_file
);
506 COMPARE_STRING_ARRAY(tctx
, cur
->info6
, ref
->info8
, dependent_files
);
507 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, monitor_name
);
508 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, default_datatype
);
509 COMPARE_STRING_ARRAY(tctx
, cur
->info6
, ref
->info8
, previous_names
);
510 COMPARE_NTTIME(tctx
, cur
->info6
, ref
->info8
, driver_date
);
511 COMPARE_UINT64(tctx
, cur
->info6
, ref
->info8
, driver_version
);
512 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, manufacturer_name
);
513 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, manufacturer_url
);
514 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, hardware_id
);
515 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, provider
);
518 /* level 8 is our reference, and it makes no sense to compare it to itself */
527 static bool test_EnumMonitors(struct torture_context
*tctx
,
528 struct dcerpc_pipe
*p
,
529 struct test_spoolss_context
*ctx
)
532 struct spoolss_EnumMonitors r
;
533 uint16_t levels
[] = { 1, 2 };
536 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
537 int level
= levels
[i
];
541 union spoolss_MonitorInfo
*info
;
543 r
.in
.servername
= "";
547 r
.out
.needed
= &needed
;
548 r
.out
.count
= &count
;
551 torture_comment(tctx
, "Testing EnumMonitors level %u\n", r
.in
.level
);
553 status
= dcerpc_spoolss_EnumMonitors(p
, ctx
, &r
);
554 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumMonitors failed");
555 if (W_ERROR_IS_OK(r
.out
.result
)) {
556 /* TODO: do some more checks here */
559 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
560 "EnumMonitors failed");
562 blob
= data_blob_talloc(ctx
, NULL
, needed
);
563 data_blob_clear(&blob
);
565 r
.in
.offered
= needed
;
567 status
= dcerpc_spoolss_EnumMonitors(p
, ctx
, &r
);
568 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumMonitors failed");
570 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumMonitors failed");
572 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
574 ctx
->monitor_count
[level
] = count
;
575 ctx
->monitors
[level
] = info
;
578 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
579 int level
= levels
[i
];
580 int old_level
= levels
[i
-1];
581 torture_assert_int_equal(tctx
, ctx
->monitor_count
[level
], ctx
->monitor_count
[old_level
],
582 "EnumMonitors invalid value");
585 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
586 int level
= levels
[i
];
587 for (j
=0;j
<ctx
->monitor_count
[level
];j
++) {
588 union spoolss_MonitorInfo
*cur
= &ctx
->monitors
[level
][j
];
589 union spoolss_MonitorInfo
*ref
= &ctx
->monitors
[2][j
];
592 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, monitor_name
);
595 /* level 2 is our reference, and it makes no sense to compare it to itself */
604 static bool test_EnumPrintProcessors(struct torture_context
*tctx
,
605 struct dcerpc_pipe
*p
,
606 struct test_spoolss_context
*ctx
)
609 struct spoolss_EnumPrintProcessors r
;
610 uint16_t levels
[] = { 1 };
613 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
614 int level
= levels
[i
];
618 union spoolss_PrintProcessorInfo
*info
;
620 r
.in
.servername
= "";
621 r
.in
.environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
625 r
.out
.needed
= &needed
;
626 r
.out
.count
= &count
;
629 torture_comment(tctx
, "Testing EnumPrintProcessors level %u\n", r
.in
.level
);
631 status
= dcerpc_spoolss_EnumPrintProcessors(p
, ctx
, &r
);
632 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcessors failed");
633 if (W_ERROR_IS_OK(r
.out
.result
)) {
634 /* TODO: do some more checks here */
637 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
638 "EnumPrintProcessors unexpected return code");
640 blob
= data_blob_talloc(ctx
, NULL
, needed
);
641 data_blob_clear(&blob
);
643 r
.in
.offered
= needed
;
645 status
= dcerpc_spoolss_EnumPrintProcessors(p
, ctx
, &r
);
646 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcessors failed");
648 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrintProcessors failed");
650 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
652 ctx
->print_processor_count
[level
] = count
;
653 ctx
->print_processors
[level
] = info
;
656 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
657 int level
= levels
[i
];
658 int old_level
= levels
[i
-1];
659 torture_assert_int_equal(tctx
, ctx
->print_processor_count
[level
], ctx
->print_processor_count
[old_level
],
660 "EnumPrintProcessors failed");
663 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
664 int level
= levels
[i
];
665 for (j
=0;j
<ctx
->print_processor_count
[level
];j
++) {
667 union spoolss_PrintProcessorInfo
*cur
= &ctx
->print_processors
[level
][j
];
668 union spoolss_PrintProcessorInfo
*ref
= &ctx
->print_processors
[1][j
];
672 /* level 1 is our reference, and it makes no sense to compare it to itself */
681 static bool test_EnumPrintProcDataTypes(struct torture_context
*tctx
,
682 struct dcerpc_pipe
*p
,
683 struct test_spoolss_context
*ctx
)
686 struct spoolss_EnumPrintProcDataTypes r
;
687 uint16_t levels
[] = { 1 };
690 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
691 int level
= levels
[i
];
695 union spoolss_PrintProcDataTypesInfo
*info
;
697 r
.in
.servername
= "";
698 r
.in
.print_processor_name
= "winprint";
702 r
.out
.needed
= &needed
;
703 r
.out
.count
= &count
;
706 torture_comment(tctx
, "Testing EnumPrintProcDataTypes level %u\n", r
.in
.level
);
708 status
= dcerpc_spoolss_EnumPrintProcDataTypes(p
, ctx
, &r
);
709 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcDataType failed");
710 if (W_ERROR_IS_OK(r
.out
.result
)) {
711 /* TODO: do some more checks here */
714 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
715 "EnumPrintProcDataTypes unexpected return code");
717 blob
= data_blob_talloc(ctx
, NULL
, needed
);
718 data_blob_clear(&blob
);
720 r
.in
.offered
= needed
;
722 status
= dcerpc_spoolss_EnumPrintProcDataTypes(p
, ctx
, &r
);
723 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
725 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrintProcDataTypes failed");
727 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
735 static bool test_EnumPrinters(struct torture_context
*tctx
,
736 struct dcerpc_pipe
*p
,
737 struct test_spoolss_context
*ctx
)
739 struct spoolss_EnumPrinters r
;
741 uint16_t levels
[] = { 0, 1, 2, 4, 5 };
744 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
745 int level
= levels
[i
];
749 union spoolss_PrinterInfo
*info
;
751 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
756 r
.out
.needed
= &needed
;
757 r
.out
.count
= &count
;
760 torture_comment(tctx
, "Testing EnumPrinters level %u\n", r
.in
.level
);
762 status
= dcerpc_spoolss_EnumPrinters(p
, ctx
, &r
);
763 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinters failed");
764 if (W_ERROR_IS_OK(r
.out
.result
)) {
765 /* TODO: do some more checks here */
768 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
769 "EnumPrinters unexpected return code");
771 blob
= data_blob_talloc(ctx
, NULL
, needed
);
772 data_blob_clear(&blob
);
774 r
.in
.offered
= needed
;
776 status
= dcerpc_spoolss_EnumPrinters(p
, ctx
, &r
);
777 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinters failed");
779 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
781 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
783 ctx
->printer_count
[level
] = count
;
784 ctx
->printers
[level
] = info
;
787 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
788 int level
= levels
[i
];
789 int old_level
= levels
[i
-1];
790 torture_assert_int_equal(tctx
, ctx
->printer_count
[level
], ctx
->printer_count
[old_level
],
791 "EnumPrinters invalid value");
794 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
795 int level
= levels
[i
];
796 for (j
=0;j
<ctx
->printer_count
[level
];j
++) {
797 union spoolss_PrinterInfo
*cur
= &ctx
->printers
[level
][j
];
798 union spoolss_PrinterInfo
*ref
= &ctx
->printers
[2][j
];
801 COMPARE_STRING(tctx
, cur
->info0
, ref
->info2
, printername
);
802 COMPARE_STRING(tctx
, cur
->info0
, ref
->info2
, servername
);
803 COMPARE_UINT32(tctx
, cur
->info0
, ref
->info2
, cjobs
);
804 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
805 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
806 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
807 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
808 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
809 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
810 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
811 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
812 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
813 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
814 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
815 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
816 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
817 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
818 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
819 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
820 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
821 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
822 COMPARE_UINT32(tctx
, cur
->info0
, ref
->info2
, status
);
823 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
824 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
825 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
826 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
827 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
828 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
829 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
832 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
833 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
834 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
835 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, comment
);
838 /* level 2 is our reference, and it makes no sense to compare it to itself */
841 COMPARE_STRING(tctx
, cur
->info4
, ref
->info2
, printername
);
842 COMPARE_STRING(tctx
, cur
->info4
, ref
->info2
, servername
);
843 COMPARE_UINT32(tctx
, cur
->info4
, ref
->info2
, attributes
);
846 COMPARE_STRING(tctx
, cur
->info5
, ref
->info2
, printername
);
847 COMPARE_STRING(tctx
, cur
->info5
, ref
->info2
, portname
);
848 COMPARE_UINT32(tctx
, cur
->info5
, ref
->info2
, attributes
);
849 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
850 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
857 * - verify that the port of a printer was in the list returned by EnumPorts
863 static bool test_GetPrinterDriver2(struct torture_context
*tctx
,
864 struct dcerpc_pipe
*p
,
865 struct policy_handle
*handle
,
866 const char *driver_name
);
868 static bool test_GetPrinter(struct torture_context
*tctx
,
869 struct dcerpc_pipe
*p
,
870 struct policy_handle
*handle
)
873 struct spoolss_GetPrinter r
;
874 uint16_t levels
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
878 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
879 r
.in
.handle
= handle
;
880 r
.in
.level
= levels
[i
];
883 r
.out
.needed
= &needed
;
885 torture_comment(tctx
, "Testing GetPrinter level %u\n", r
.in
.level
);
887 status
= dcerpc_spoolss_GetPrinter(p
, tctx
, &r
);
888 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinter failed");
890 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
891 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
892 data_blob_clear(&blob
);
894 r
.in
.offered
= needed
;
895 status
= dcerpc_spoolss_GetPrinter(p
, tctx
, &r
);
898 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinter failed");
900 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrinter failed");
902 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
904 if ((r
.in
.level
== 2) && r
.out
.info
->info2
.drivername
&& strlen(r
.out
.info
->info2
.drivername
)) {
906 test_GetPrinterDriver2(tctx
, p
, handle
, r
.out
.info
->info2
.drivername
),
907 "failed to call test_GetPrinterDriver2");
914 static bool test_SetPrinter_errors(struct torture_context
*tctx
,
915 struct dcerpc_pipe
*p
,
916 struct policy_handle
*handle
)
918 struct spoolss_SetPrinter r
;
919 uint16_t levels
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
922 struct spoolss_SetPrinterInfoCtr info_ctr
;
923 struct spoolss_DevmodeContainer devmode_ctr
;
924 struct sec_desc_buf secdesc_ctr
;
927 info_ctr
.info
.info0
= NULL
;
929 ZERO_STRUCT(devmode_ctr
);
930 ZERO_STRUCT(secdesc_ctr
);
932 r
.in
.handle
= handle
;
933 r
.in
.info_ctr
= &info_ctr
;
934 r
.in
.devmode_ctr
= &devmode_ctr
;
935 r
.in
.secdesc_ctr
= &secdesc_ctr
;
938 torture_comment(tctx
, "Testing SetPrinter all zero\n");
940 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter(p
, tctx
, &r
),
941 "failed to call SetPrinter");
942 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
943 "failed to call SetPrinter");
946 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
948 struct spoolss_SetPrinterInfo0 info0
;
949 struct spoolss_SetPrinterInfo1 info1
;
950 struct spoolss_SetPrinterInfo2 info2
;
951 struct spoolss_SetPrinterInfo3 info3
;
952 struct spoolss_SetPrinterInfo4 info4
;
953 struct spoolss_SetPrinterInfo5 info5
;
954 struct spoolss_SetPrinterInfo6 info6
;
955 struct spoolss_SetPrinterInfo7 info7
;
956 struct spoolss_SetPrinterInfo8 info8
;
957 struct spoolss_SetPrinterInfo9 info9
;
960 info_ctr
.level
= levels
[i
];
964 info_ctr
.info
.info0
= &info0
;
968 info_ctr
.info
.info1
= &info1
;
972 info_ctr
.info
.info2
= &info2
;
976 info_ctr
.info
.info3
= &info3
;
980 info_ctr
.info
.info4
= &info4
;
984 info_ctr
.info
.info5
= &info5
;
988 info_ctr
.info
.info6
= &info6
;
992 info_ctr
.info
.info7
= &info7
;
996 info_ctr
.info
.info8
= &info8
;
1000 info_ctr
.info
.info9
= &info9
;
1004 torture_comment(tctx
, "Testing SetPrinter level %d, command %d\n",
1005 info_ctr
.level
, r
.in
.command
);
1007 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter(p
, tctx
, &r
),
1008 "failed to call SetPrinter");
1010 switch (r
.in
.command
) {
1011 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
: /* 0 */
1012 /* is ignored for all levels other then 0 */
1013 if (info_ctr
.level
> 0) {
1017 case SPOOLSS_PRINTER_CONTROL_PAUSE
: /* 1 */
1018 case SPOOLSS_PRINTER_CONTROL_RESUME
: /* 2 */
1019 case SPOOLSS_PRINTER_CONTROL_PURGE
: /* 3 */
1020 if (info_ctr
.level
> 0) {
1021 /* is invalid for all levels other then 0 */
1022 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PRINTER_COMMAND
,
1023 "unexpected error code returned");
1026 torture_assert_werr_ok(tctx
, r
.out
.result
,
1027 "failed to call SetPrinter with non 0 command");
1032 case SPOOLSS_PRINTER_CONTROL_SET_STATUS
: /* 4 */
1033 /* FIXME: gd needs further investigation */
1035 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PRINTER_COMMAND
,
1036 "unexpected error code returned");
1040 switch (info_ctr
.level
) {
1042 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
,
1043 "unexpected error code returned");
1046 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_PRINTER_DRIVER
,
1047 "unexpected error code returned");
1053 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
1054 "unexpected error code returned");
1057 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_NOT_SUPPORTED
,
1058 "unexpected error code returned");
1061 torture_assert_werr_ok(tctx
, r
.out
.result
,
1062 "failed to call SetPrinter");
1067 if (r
.in
.command
< 5) {
1075 static void clear_info2(struct spoolss_SetPrinterInfoCtr
*r
)
1077 if ((r
->level
== 2) && (r
->info
.info2
)) {
1078 r
->info
.info2
->secdesc_ptr
= 0;
1079 r
->info
.info2
->devmode_ptr
= 0;
1083 static bool test_PrinterInfo(struct torture_context
*tctx
,
1084 struct dcerpc_pipe
*p
,
1085 struct policy_handle
*handle
)
1088 struct spoolss_SetPrinter s
;
1089 struct spoolss_GetPrinter q
;
1090 struct spoolss_GetPrinter q0
;
1091 struct spoolss_SetPrinterInfoCtr info_ctr
;
1092 union spoolss_PrinterInfo info
;
1093 struct spoolss_DevmodeContainer devmode_ctr
;
1094 struct sec_desc_buf secdesc_ctr
;
1099 uint32_t status_list
[] = {
1100 /* these do not stick
1101 PRINTER_STATUS_PAUSED,
1102 PRINTER_STATUS_ERROR,
1103 PRINTER_STATUS_PENDING_DELETION, */
1104 PRINTER_STATUS_PAPER_JAM
,
1105 PRINTER_STATUS_PAPER_OUT
,
1106 PRINTER_STATUS_MANUAL_FEED
,
1107 PRINTER_STATUS_PAPER_PROBLEM
,
1108 PRINTER_STATUS_OFFLINE
,
1109 PRINTER_STATUS_IO_ACTIVE
,
1110 PRINTER_STATUS_BUSY
,
1111 PRINTER_STATUS_PRINTING
,
1112 PRINTER_STATUS_OUTPUT_BIN_FULL
,
1113 PRINTER_STATUS_NOT_AVAILABLE
,
1114 PRINTER_STATUS_WAITING
,
1115 PRINTER_STATUS_PROCESSING
,
1116 PRINTER_STATUS_INITIALIZING
,
1117 PRINTER_STATUS_WARMING_UP
,
1118 PRINTER_STATUS_TONER_LOW
,
1119 PRINTER_STATUS_NO_TONER
,
1120 PRINTER_STATUS_PAGE_PUNT
,
1121 PRINTER_STATUS_USER_INTERVENTION
,
1122 PRINTER_STATUS_OUT_OF_MEMORY
,
1123 PRINTER_STATUS_DOOR_OPEN
,
1124 PRINTER_STATUS_SERVER_UNKNOWN
,
1125 PRINTER_STATUS_POWER_SAVE
,
1126 /* these do not stick
1135 uint32_t default_attribute
= PRINTER_ATTRIBUTE_LOCAL
;
1136 uint32_t attribute_list
[] = {
1137 PRINTER_ATTRIBUTE_QUEUED
,
1138 /* fails with WERR_INVALID_DATATYPE:
1139 PRINTER_ATTRIBUTE_DIRECT, */
1141 PRINTER_ATTRIBUTE_DEFAULT, */
1142 PRINTER_ATTRIBUTE_SHARED
,
1144 PRINTER_ATTRIBUTE_NETWORK, */
1145 PRINTER_ATTRIBUTE_HIDDEN
,
1146 PRINTER_ATTRIBUTE_LOCAL
,
1147 PRINTER_ATTRIBUTE_ENABLE_DEVQ
,
1148 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
,
1149 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST
,
1150 PRINTER_ATTRIBUTE_WORK_OFFLINE
,
1152 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1153 /* fails with WERR_INVALID_DATATYPE:
1154 PRINTER_ATTRIBUTE_RAW_ONLY, */
1155 /* these do not stick
1156 PRINTER_ATTRIBUTE_PUBLISHED,
1157 PRINTER_ATTRIBUTE_FAX,
1158 PRINTER_ATTRIBUTE_TS,
1177 ZERO_STRUCT(devmode_ctr
);
1178 ZERO_STRUCT(secdesc_ctr
);
1180 s
.in
.handle
= handle
;
1182 s
.in
.info_ctr
= &info_ctr
;
1183 s
.in
.devmode_ctr
= &devmode_ctr
;
1184 s
.in
.secdesc_ctr
= &secdesc_ctr
;
1186 q
.in
.handle
= handle
;
1190 #define TESTGETCALL(call, r) \
1191 r.in.buffer = NULL; \
1193 r.out.needed = &needed; \
1194 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1195 if (!NT_STATUS_IS_OK(status)) { \
1196 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1197 r.in.level, nt_errstr(status), __location__); \
1201 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1202 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1203 data_blob_clear(&blob); \
1204 r.in.buffer = &blob; \
1205 r.in.offered = needed; \
1207 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1208 if (!NT_STATUS_IS_OK(status)) { \
1209 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1210 r.in.level, nt_errstr(status), __location__); \
1214 if (!W_ERROR_IS_OK(r.out.result)) { \
1215 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1216 r.in.level, win_errstr(r.out.result), __location__); \
1222 #define TESTSETCALL_EXP(call, r, err) \
1223 clear_info2(&info_ctr);\
1224 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1225 if (!NT_STATUS_IS_OK(status)) { \
1226 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1227 r.in.info_ctr->level, nt_errstr(status), __location__); \
1231 if (!W_ERROR_IS_OK(err)) { \
1232 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1233 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1234 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1239 if (!W_ERROR_IS_OK(r.out.result)) { \
1240 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1241 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1246 #define TESTSETCALL(call, r) \
1247 TESTSETCALL_EXP(call, r, WERR_OK)
1249 #define STRING_EQUAL(s1, s2, field) \
1250 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1251 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1252 #field, s2, __location__); \
1257 #define MEM_EQUAL(s1, s2, length, field) \
1258 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1259 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1260 #field, (const char *)s2, __location__); \
1265 #define INT_EQUAL(i1, i2, field) \
1267 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1268 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1273 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1274 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1275 q.in.level = lvl1; \
1276 TESTGETCALL(GetPrinter, q) \
1277 info_ctr.level = lvl1; \
1278 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1279 info_ctr.info.info ## lvl1->field1 = value;\
1280 TESTSETCALL_EXP(SetPrinter, s, err) \
1281 info_ctr.info.info ## lvl1->field1 = ""; \
1282 TESTGETCALL(GetPrinter, q) \
1283 info_ctr.info.info ## lvl1->field1 = value; \
1284 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1285 q.in.level = lvl2; \
1286 TESTGETCALL(GetPrinter, q) \
1287 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1288 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1291 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1292 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1295 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1296 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1297 q.in.level = lvl1; \
1298 TESTGETCALL(GetPrinter, q) \
1299 info_ctr.level = lvl1; \
1300 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1301 info_ctr.info.info ## lvl1->field1 = value; \
1302 TESTSETCALL(SetPrinter, s) \
1303 info_ctr.info.info ## lvl1->field1 = 0; \
1304 TESTGETCALL(GetPrinter, q) \
1305 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1306 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1307 q.in.level = lvl2; \
1308 TESTGETCALL(GetPrinter, q) \
1309 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1310 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1313 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1314 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1318 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1320 TEST_PRINTERINFO_STRING(2, comment
, 1, comment
, "xx2-1 comment");
1321 TEST_PRINTERINFO_STRING(2, comment
, 2, comment
, "xx2-2 comment");
1323 /* level 0 printername does not stick */
1324 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1325 TEST_PRINTERINFO_STRING(2, printername
, 1, name
, "xx2-1 printer");
1326 TEST_PRINTERINFO_STRING(2, printername
, 2, printername
, "xx2-2 printer");
1327 TEST_PRINTERINFO_STRING(2, printername
, 4, printername
, "xx2-4 printer");
1328 TEST_PRINTERINFO_STRING(2, printername
, 5, printername
, "xx2-5 printer");
1329 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1330 TEST_PRINTERINFO_STRING(4, printername
, 1, name
, "xx4-1 printer");
1331 TEST_PRINTERINFO_STRING(4, printername
, 2, printername
, "xx4-2 printer");
1332 TEST_PRINTERINFO_STRING(4, printername
, 4, printername
, "xx4-4 printer");
1333 TEST_PRINTERINFO_STRING(4, printername
, 5, printername
, "xx4-5 printer");
1334 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1335 TEST_PRINTERINFO_STRING(5, printername
, 1, name
, "xx5-1 printer");
1336 TEST_PRINTERINFO_STRING(5, printername
, 2, printername
, "xx5-2 printer");
1337 TEST_PRINTERINFO_STRING(5, printername
, 4, printername
, "xx5-4 printer");
1338 TEST_PRINTERINFO_STRING(5, printername
, 5, printername
, "xx5-5 printer");
1340 /* servername can be set but does not stick
1341 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1342 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1343 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1346 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1347 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname
, 2, portname
, "xx2-2 portname", WERR_UNKNOWN_PORT
);
1348 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname
, 5, portname
, "xx2-5 portname", WERR_UNKNOWN_PORT
);
1349 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname
, 2, portname
, "xx5-2 portname", WERR_UNKNOWN_PORT
);
1350 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname
, 5, portname
, "xx5-5 portname", WERR_UNKNOWN_PORT
);
1352 TEST_PRINTERINFO_STRING(2, sharename
, 2, sharename
, "xx2-2 sharename");
1353 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1354 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername
, 2, drivername
, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER
);
1355 TEST_PRINTERINFO_STRING(2, location
, 2, location
, "xx2-2 location");
1356 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1357 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile
, 2, sepfile
, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE
);
1358 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1359 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor
, 2, printprocessor
, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR
);
1360 TEST_PRINTERINFO_STRING(2, datatype
, 2, datatype
, "xx2-2 datatype");
1361 TEST_PRINTERINFO_STRING(2, parameters
, 2, parameters
, "xx2-2 parameters");
1363 for (i
=0; i
< ARRAY_SIZE(attribute_list
); i
++) {
1364 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1366 (attribute_list[i] | default_attribute)
1368 TEST_PRINTERINFO_INT_EXP(2, attributes
, 2, attributes
,
1370 (attribute_list
[i
] | default_attribute
)
1372 TEST_PRINTERINFO_INT_EXP(2, attributes
, 4, attributes
,
1374 (attribute_list
[i
] | default_attribute
)
1376 TEST_PRINTERINFO_INT_EXP(2, attributes
, 5, attributes
,
1378 (attribute_list
[i
] | default_attribute
)
1380 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1382 (attribute_list[i] | default_attribute)
1384 TEST_PRINTERINFO_INT_EXP(4, attributes
, 2, attributes
,
1386 (attribute_list
[i
] | default_attribute
)
1388 TEST_PRINTERINFO_INT_EXP(4, attributes
, 4, attributes
,
1390 (attribute_list
[i
] | default_attribute
)
1392 TEST_PRINTERINFO_INT_EXP(4, attributes
, 5, attributes
,
1394 (attribute_list
[i
] | default_attribute
)
1396 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1398 (attribute_list[i] | default_attribute)
1400 TEST_PRINTERINFO_INT_EXP(5, attributes
, 2, attributes
,
1402 (attribute_list
[i
] | default_attribute
)
1404 TEST_PRINTERINFO_INT_EXP(5, attributes
, 4, attributes
,
1406 (attribute_list
[i
] | default_attribute
)
1408 TEST_PRINTERINFO_INT_EXP(5, attributes
, 5, attributes
,
1410 (attribute_list
[i
] | default_attribute
)
1414 for (i
=0; i
< ARRAY_SIZE(status_list
); i
++) {
1415 /* level 2 sets do not stick
1416 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1417 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1418 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1419 TEST_PRINTERINFO_INT(6, status
, 0, status
, status_list
[i
]);
1420 TEST_PRINTERINFO_INT(6, status
, 2, status
, status_list
[i
]);
1421 TEST_PRINTERINFO_INT(6, status
, 6, status
, status_list
[i
]);
1424 /* priorities need to be between 0 and 99
1425 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1426 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 0);
1427 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 1);
1428 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 99);
1429 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1430 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 0);
1431 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 1);
1432 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 99);
1433 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1435 TEST_PRINTERINFO_INT(2, starttime
, 2, starttime
, __LINE__
);
1436 TEST_PRINTERINFO_INT(2, untiltime
, 2, untiltime
, __LINE__
);
1439 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1440 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1443 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1444 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1446 /* FIXME: gd also test devmode and secdesc behavior */
1449 /* verify composition of level 1 description field */
1450 const char *description
;
1454 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1456 description
= talloc_strdup(tctx
, q0
.out
.info
->info1
.description
);
1459 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1461 tmp
= talloc_asprintf(tctx
, "%s,%s,%s",
1462 q0
.out
.info
->info2
.printername
,
1463 q0
.out
.info
->info2
.drivername
,
1464 q0
.out
.info
->info2
.location
);
1466 do { STRING_EQUAL(description
, tmp
, "description")} while (0);
1473 static bool test_ClosePrinter(struct torture_context
*tctx
,
1474 struct dcerpc_pipe
*p
,
1475 struct policy_handle
*handle
)
1478 struct spoolss_ClosePrinter r
;
1480 r
.in
.handle
= handle
;
1481 r
.out
.handle
= handle
;
1483 torture_comment(tctx
, "Testing ClosePrinter\n");
1485 status
= dcerpc_spoolss_ClosePrinter(p
, tctx
, &r
);
1486 torture_assert_ntstatus_ok(tctx
, status
, "ClosePrinter failed");
1487 torture_assert_werr_ok(tctx
, r
.out
.result
, "ClosePrinter failed");
1492 static bool test_GetForm(struct torture_context
*tctx
,
1493 struct dcerpc_pipe
*p
,
1494 struct policy_handle
*handle
,
1495 const char *form_name
,
1499 struct spoolss_GetForm r
;
1502 r
.in
.handle
= handle
;
1503 r
.in
.form_name
= form_name
;
1507 r
.out
.needed
= &needed
;
1509 torture_comment(tctx
, "Testing GetForm level %d\n", r
.in
.level
);
1511 status
= dcerpc_spoolss_GetForm(p
, tctx
, &r
);
1512 torture_assert_ntstatus_ok(tctx
, status
, "GetForm failed");
1514 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1515 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1516 data_blob_clear(&blob
);
1517 r
.in
.buffer
= &blob
;
1518 r
.in
.offered
= needed
;
1519 status
= dcerpc_spoolss_GetForm(p
, tctx
, &r
);
1520 torture_assert_ntstatus_ok(tctx
, status
, "GetForm failed");
1522 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetForm failed");
1524 torture_assert(tctx
, r
.out
.info
, "No form info returned");
1527 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetForm failed");
1529 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
1534 static bool test_EnumForms(struct torture_context
*tctx
,
1535 struct dcerpc_pipe
*p
,
1536 struct policy_handle
*handle
, bool print_server
)
1539 struct spoolss_EnumForms r
;
1543 uint32_t levels
[] = { 1, 2 };
1546 for (i
=0; i
<ARRAY_SIZE(levels
); i
++) {
1548 union spoolss_FormInfo
*info
;
1550 r
.in
.handle
= handle
;
1551 r
.in
.level
= levels
[i
];
1554 r
.out
.needed
= &needed
;
1555 r
.out
.count
= &count
;
1558 torture_comment(tctx
, "Testing EnumForms level %d\n", levels
[i
]);
1560 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &r
);
1561 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
1563 if ((r
.in
.level
== 2) && (W_ERROR_EQUAL(r
.out
.result
, WERR_UNKNOWN_LEVEL
))) {
1567 if (print_server
&& W_ERROR_EQUAL(r
.out
.result
, WERR_BADFID
))
1568 torture_fail(tctx
, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1570 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1572 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1573 data_blob_clear(&blob
);
1574 r
.in
.buffer
= &blob
;
1575 r
.in
.offered
= needed
;
1577 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &r
);
1579 torture_assert(tctx
, info
, "No forms returned");
1581 for (j
= 0; j
< count
; j
++) {
1583 ret
&= test_GetForm(tctx
, p
, handle
, info
[j
].info1
.form_name
, levels
[i
]);
1587 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
1589 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumForms failed");
1591 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
1597 static bool test_DeleteForm(struct torture_context
*tctx
,
1598 struct dcerpc_pipe
*p
,
1599 struct policy_handle
*handle
,
1600 const char *form_name
)
1603 struct spoolss_DeleteForm r
;
1605 r
.in
.handle
= handle
;
1606 r
.in
.form_name
= form_name
;
1608 status
= dcerpc_spoolss_DeleteForm(p
, tctx
, &r
);
1610 torture_assert_ntstatus_ok(tctx
, status
, "DeleteForm failed");
1612 torture_assert_werr_ok(tctx
, r
.out
.result
, "DeleteForm failed");
1617 static bool test_AddForm(struct torture_context
*tctx
,
1618 struct dcerpc_pipe
*p
,
1619 struct policy_handle
*handle
, bool print_server
)
1621 struct spoolss_AddForm r
;
1622 struct spoolss_AddFormInfo1 addform
;
1623 const char *form_name
= "testform3";
1627 r
.in
.handle
= handle
;
1629 r
.in
.info
.info1
= &addform
;
1630 addform
.flags
= SPOOLSS_FORM_USER
;
1631 addform
.form_name
= form_name
;
1632 addform
.size
.width
= 50;
1633 addform
.size
.height
= 25;
1634 addform
.area
.left
= 5;
1635 addform
.area
.top
= 10;
1636 addform
.area
.right
= 45;
1637 addform
.area
.bottom
= 15;
1639 status
= dcerpc_spoolss_AddForm(p
, tctx
, &r
);
1641 torture_assert_ntstatus_ok(tctx
, status
, "AddForm failed");
1643 torture_assert_werr_ok(tctx
, r
.out
.result
, "AddForm failed");
1645 if (!print_server
) ret
&= test_GetForm(tctx
, p
, handle
, form_name
, 1);
1648 struct spoolss_SetForm sf
;
1649 struct spoolss_AddFormInfo1 setform
;
1651 sf
.in
.handle
= handle
;
1652 sf
.in
.form_name
= form_name
;
1654 sf
.in
.info
.info1
= &setform
;
1655 setform
.flags
= addform
.flags
;
1656 setform
.form_name
= addform
.form_name
;
1657 setform
.size
= addform
.size
;
1658 setform
.area
= addform
.area
;
1660 setform
.size
.width
= 1234;
1662 status
= dcerpc_spoolss_SetForm(p
, tctx
, &sf
);
1664 torture_assert_ntstatus_ok(tctx
, status
, "SetForm failed");
1666 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetForm failed");
1669 if (!print_server
) ret
&= test_GetForm(tctx
, p
, handle
, form_name
, 1);
1672 struct spoolss_EnumForms e
;
1673 union spoolss_FormInfo
*info
;
1678 e
.in
.handle
= handle
;
1682 e
.out
.needed
= &needed
;
1683 e
.out
.count
= &count
;
1686 torture_comment(tctx
, "Testing EnumForms level 1\n");
1688 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &e
);
1689 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
1691 if (print_server
&& W_ERROR_EQUAL(e
.out
.result
, WERR_BADFID
))
1692 torture_fail(tctx
, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1694 if (W_ERROR_EQUAL(e
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1696 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1697 data_blob_clear(&blob
);
1698 e
.in
.buffer
= &blob
;
1699 e
.in
.offered
= needed
;
1701 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &e
);
1703 torture_assert(tctx
, info
, "No forms returned");
1705 for (j
= 0; j
< count
; j
++) {
1706 if (strequal(form_name
, info
[j
].info1
.form_name
)) {
1712 torture_assert(tctx
, found
, "Newly added form not found in enum call");
1715 if (!test_DeleteForm(tctx
, p
, handle
, form_name
)) {
1722 static bool test_EnumPorts_old(struct torture_context
*tctx
,
1723 struct dcerpc_pipe
*p
)
1726 struct spoolss_EnumPorts r
;
1729 union spoolss_PortInfo
*info
;
1731 r
.in
.servername
= talloc_asprintf(tctx
, "\\\\%s",
1732 dcerpc_server_name(p
));
1736 r
.out
.needed
= &needed
;
1737 r
.out
.count
= &count
;
1740 torture_comment(tctx
, "Testing EnumPorts\n");
1742 status
= dcerpc_spoolss_EnumPorts(p
, tctx
, &r
);
1744 torture_assert_ntstatus_ok(tctx
, status
, "EnumPorts failed");
1746 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1747 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1748 data_blob_clear(&blob
);
1749 r
.in
.buffer
= &blob
;
1750 r
.in
.offered
= needed
;
1752 status
= dcerpc_spoolss_EnumPorts(p
, tctx
, &r
);
1753 torture_assert_ntstatus_ok(tctx
, status
, "EnumPorts failed");
1754 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
1756 torture_assert(tctx
, info
, "No ports returned");
1759 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
1761 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts
, info
, 2, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
1766 static bool test_AddPort(struct torture_context
*tctx
,
1767 struct dcerpc_pipe
*p
)
1770 struct spoolss_AddPort r
;
1772 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s",
1773 dcerpc_server_name(p
));
1775 r
.in
.monitor_name
= "foo";
1777 torture_comment(tctx
, "Testing AddPort\n");
1779 status
= dcerpc_spoolss_AddPort(p
, tctx
, &r
);
1781 torture_assert_ntstatus_ok(tctx
, status
, "AddPort failed");
1783 /* win2k3 returns WERR_NOT_SUPPORTED */
1787 if (!W_ERROR_IS_OK(r
.out
.result
)) {
1788 printf("AddPort failed - %s\n", win_errstr(r
.out
.result
));
1797 static bool test_GetJob(struct torture_context
*tctx
,
1798 struct dcerpc_pipe
*p
,
1799 struct policy_handle
*handle
, uint32_t job_id
)
1802 struct spoolss_GetJob r
;
1803 union spoolss_JobInfo info
;
1805 uint32_t levels
[] = {1, 2 /* 3, 4 */};
1808 r
.in
.handle
= handle
;
1809 r
.in
.job_id
= job_id
;
1813 r
.out
.needed
= &needed
;
1816 torture_comment(tctx
, "Testing GetJob level %d\n", r
.in
.level
);
1818 status
= dcerpc_spoolss_GetJob(p
, tctx
, &r
);
1819 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
, "Unexpected return code");
1821 for (i
= 0; i
< ARRAY_SIZE(levels
); i
++) {
1823 torture_comment(tctx
, "Testing GetJob level %d\n", r
.in
.level
);
1827 r
.in
.level
= levels
[i
];
1831 status
= dcerpc_spoolss_GetJob(p
, tctx
, &r
);
1832 torture_assert_ntstatus_ok(tctx
, status
, "GetJob failed");
1834 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1835 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1836 data_blob_clear(&blob
);
1837 r
.in
.buffer
= &blob
;
1838 r
.in
.offered
= needed
;
1840 status
= dcerpc_spoolss_GetJob(p
, tctx
, &r
);
1841 torture_assert_ntstatus_ok(tctx
, status
, "GetJob failed");
1844 torture_assert(tctx
, r
.out
.info
, "No job info returned");
1845 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetJob failed");
1847 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
1853 static bool test_SetJob(struct torture_context
*tctx
,
1854 struct dcerpc_pipe
*p
,
1855 struct policy_handle
*handle
, uint32_t job_id
,
1856 enum spoolss_JobControl command
)
1859 struct spoolss_SetJob r
;
1861 r
.in
.handle
= handle
;
1862 r
.in
.job_id
= job_id
;
1864 r
.in
.command
= command
;
1867 case SPOOLSS_JOB_CONTROL_PAUSE
:
1868 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1870 case SPOOLSS_JOB_CONTROL_RESUME
:
1871 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1873 case SPOOLSS_JOB_CONTROL_CANCEL
:
1874 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1876 case SPOOLSS_JOB_CONTROL_RESTART
:
1877 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1879 case SPOOLSS_JOB_CONTROL_DELETE
:
1880 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1882 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER
:
1883 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1885 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED
:
1886 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1888 case SPOOLSS_JOB_CONTROL_RETAIN
:
1889 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1891 case SPOOLSS_JOB_CONTROL_RELEASE
:
1892 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1895 torture_comment(tctx
, "Testing SetJob\n");
1899 status
= dcerpc_spoolss_SetJob(p
, tctx
, &r
);
1900 torture_assert_ntstatus_ok(tctx
, status
, "SetJob failed");
1901 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetJob failed");
1906 static bool test_AddJob(struct torture_context
*tctx
,
1907 struct dcerpc_pipe
*p
,
1908 struct policy_handle
*handle
)
1911 struct spoolss_AddJob r
;
1915 r
.in
.handle
= handle
;
1917 r
.out
.needed
= &needed
;
1918 r
.in
.buffer
= r
.out
.buffer
= NULL
;
1920 torture_comment(tctx
, "Testing AddJob\n");
1922 status
= dcerpc_spoolss_AddJob(p
, tctx
, &r
);
1923 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
, "AddJob failed");
1927 status
= dcerpc_spoolss_AddJob(p
, tctx
, &r
);
1928 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
, "AddJob failed");
1934 static bool test_EnumJobs(struct torture_context
*tctx
,
1935 struct dcerpc_pipe
*p
,
1936 struct policy_handle
*handle
)
1939 struct spoolss_EnumJobs r
;
1942 union spoolss_JobInfo
*info
;
1944 r
.in
.handle
= handle
;
1946 r
.in
.numjobs
= 0xffffffff;
1950 r
.out
.needed
= &needed
;
1951 r
.out
.count
= &count
;
1954 torture_comment(tctx
, "Testing EnumJobs\n");
1956 status
= dcerpc_spoolss_EnumJobs(p
, tctx
, &r
);
1958 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
1960 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1962 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1963 data_blob_clear(&blob
);
1964 r
.in
.buffer
= &blob
;
1965 r
.in
.offered
= needed
;
1967 status
= dcerpc_spoolss_EnumJobs(p
, tctx
, &r
);
1969 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
1970 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumJobs failed");
1971 torture_assert(tctx
, info
, "No jobs returned");
1973 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs
, *r
.out
.info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
1975 for (j
= 0; j
< count
; j
++) {
1977 torture_assert(tctx
, test_GetJob(tctx
, p
, handle
, info
[j
].info1
.job_id
),
1978 "failed to call test_GetJob");
1981 if (!torture_setting_bool(tctx
, "samba3", false)) {
1982 test_SetJob(tctx
, p
, handle
, info
[j
].info1
.job_id
, SPOOLSS_JOB_CONTROL_PAUSE
);
1983 test_SetJob(tctx
, p
, handle
, info
[j
].info1
.job_id
, SPOOLSS_JOB_CONTROL_RESUME
);
1988 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumJobs failed");
1994 static bool test_DoPrintTest(struct torture_context
*tctx
,
1995 struct dcerpc_pipe
*p
,
1996 struct policy_handle
*handle
)
2000 struct spoolss_StartDocPrinter s
;
2001 struct spoolss_DocumentInfo1 info1
;
2002 struct spoolss_StartPagePrinter sp
;
2003 struct spoolss_WritePrinter w
;
2004 struct spoolss_EndPagePrinter ep
;
2005 struct spoolss_EndDocPrinter e
;
2008 uint32_t num_written
;
2010 torture_comment(tctx
, "Testing StartDocPrinter\n");
2012 s
.in
.handle
= handle
;
2014 s
.in
.info
.info1
= &info1
;
2015 s
.out
.job_id
= &job_id
;
2016 info1
.document_name
= "TorturePrintJob";
2017 info1
.output_file
= NULL
;
2018 info1
.datatype
= "RAW";
2020 status
= dcerpc_spoolss_StartDocPrinter(p
, tctx
, &s
);
2021 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_StartDocPrinter failed");
2022 torture_assert_werr_ok(tctx
, s
.out
.result
, "StartDocPrinter failed");
2024 for (i
=1; i
< 4; i
++) {
2025 torture_comment(tctx
, "Testing StartPagePrinter: Page[%d]\n", i
);
2027 sp
.in
.handle
= handle
;
2029 status
= dcerpc_spoolss_StartPagePrinter(p
, tctx
, &sp
);
2030 torture_assert_ntstatus_ok(tctx
, status
,
2031 "dcerpc_spoolss_StartPagePrinter failed");
2032 torture_assert_werr_ok(tctx
, sp
.out
.result
, "StartPagePrinter failed");
2034 torture_comment(tctx
, "Testing WritePrinter: Page[%d]\n", i
);
2036 w
.in
.handle
= handle
;
2037 w
.in
.data
= data_blob_string_const(talloc_asprintf(tctx
,"TortureTestPage: %d\nData\n",i
));
2038 w
.out
.num_written
= &num_written
;
2040 status
= dcerpc_spoolss_WritePrinter(p
, tctx
, &w
);
2041 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_WritePrinter failed");
2042 torture_assert_werr_ok(tctx
, w
.out
.result
, "WritePrinter failed");
2044 torture_comment(tctx
, "Testing EndPagePrinter: Page[%d]\n", i
);
2046 ep
.in
.handle
= handle
;
2048 status
= dcerpc_spoolss_EndPagePrinter(p
, tctx
, &ep
);
2049 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndPagePrinter failed");
2050 torture_assert_werr_ok(tctx
, ep
.out
.result
, "EndPagePrinter failed");
2053 torture_comment(tctx
, "Testing EndDocPrinter\n");
2055 e
.in
.handle
= handle
;
2057 status
= dcerpc_spoolss_EndDocPrinter(p
, tctx
, &e
);
2058 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndDocPrinter failed");
2059 torture_assert_werr_ok(tctx
, e
.out
.result
, "EndDocPrinter failed");
2061 ret
&= test_AddJob(tctx
, p
, handle
);
2062 ret
&= test_EnumJobs(tctx
, p
, handle
);
2064 ret
&= test_SetJob(tctx
, p
, handle
, job_id
, SPOOLSS_JOB_CONTROL_DELETE
);
2069 static bool test_PausePrinter(struct torture_context
*tctx
,
2070 struct dcerpc_pipe
*p
,
2071 struct policy_handle
*handle
)
2074 struct spoolss_SetPrinter r
;
2075 struct spoolss_SetPrinterInfoCtr info_ctr
;
2076 struct spoolss_DevmodeContainer devmode_ctr
;
2077 struct sec_desc_buf secdesc_ctr
;
2080 info_ctr
.info
.info0
= NULL
;
2082 ZERO_STRUCT(devmode_ctr
);
2083 ZERO_STRUCT(secdesc_ctr
);
2085 r
.in
.handle
= handle
;
2086 r
.in
.info_ctr
= &info_ctr
;
2087 r
.in
.devmode_ctr
= &devmode_ctr
;
2088 r
.in
.secdesc_ctr
= &secdesc_ctr
;
2089 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
2091 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
2093 status
= dcerpc_spoolss_SetPrinter(p
, tctx
, &r
);
2095 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
2097 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
2102 static bool test_ResumePrinter(struct torture_context
*tctx
,
2103 struct dcerpc_pipe
*p
,
2104 struct policy_handle
*handle
)
2107 struct spoolss_SetPrinter r
;
2108 struct spoolss_SetPrinterInfoCtr info_ctr
;
2109 struct spoolss_DevmodeContainer devmode_ctr
;
2110 struct sec_desc_buf secdesc_ctr
;
2113 info_ctr
.info
.info0
= NULL
;
2115 ZERO_STRUCT(devmode_ctr
);
2116 ZERO_STRUCT(secdesc_ctr
);
2118 r
.in
.handle
= handle
;
2119 r
.in
.info_ctr
= &info_ctr
;
2120 r
.in
.devmode_ctr
= &devmode_ctr
;
2121 r
.in
.secdesc_ctr
= &secdesc_ctr
;
2122 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
2124 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2126 status
= dcerpc_spoolss_SetPrinter(p
, tctx
, &r
);
2128 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
2130 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
2135 static bool test_GetPrinterData(struct torture_context
*tctx
,
2136 struct dcerpc_pipe
*p
,
2137 struct policy_handle
*handle
,
2138 const char *value_name
,
2139 enum winreg_Type
*type_p
,
2140 union spoolss_PrinterData
*data_p
)
2143 struct spoolss_GetPrinterData r
;
2145 enum winreg_Type type
;
2146 union spoolss_PrinterData data
;
2148 r
.in
.handle
= handle
;
2149 r
.in
.value_name
= value_name
;
2151 r
.out
.needed
= &needed
;
2155 torture_comment(tctx
, "Testing GetPrinterData(%s)\n", r
.in
.value_name
);
2157 status
= dcerpc_spoolss_GetPrinterData(p
, tctx
, &r
);
2158 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
2160 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
2161 r
.in
.offered
= needed
;
2163 status
= dcerpc_spoolss_GetPrinterData(p
, tctx
, &r
);
2164 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
2167 torture_assert_werr_ok(tctx
, r
.out
.result
,
2168 talloc_asprintf(tctx
, "GetPrinterData(%s) failed", r
.in
.value_name
));
2170 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData
, &data
, type
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 1);
2183 static bool test_GetPrinterDataEx(struct torture_context
*tctx
,
2184 struct dcerpc_pipe
*p
,
2185 struct policy_handle
*handle
,
2186 const char *key_name
,
2187 const char *value_name
,
2188 enum winreg_Type
*type_p
,
2189 union spoolss_PrinterData
*data_p
)
2192 struct spoolss_GetPrinterDataEx r
;
2193 enum winreg_Type type
;
2195 union spoolss_PrinterData data
;
2197 r
.in
.handle
= handle
;
2198 r
.in
.key_name
= key_name
;
2199 r
.in
.value_name
= value_name
;
2202 r
.out
.needed
= &needed
;
2205 torture_comment(tctx
, "Testing GetPrinterDataEx(%s - %s)\n",
2206 r
.in
.key_name
, r
.in
.value_name
);
2208 status
= dcerpc_spoolss_GetPrinterDataEx(p
, tctx
, &r
);
2209 if (!NT_STATUS_IS_OK(status
)) {
2210 if (NT_STATUS_EQUAL(status
,NT_STATUS_NET_WRITE_FAULT
) &&
2211 p
->last_fault_code
== DCERPC_FAULT_OP_RNG_ERROR
) {
2212 torture_skip(tctx
, "GetPrinterDataEx not supported by server\n");
2214 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
2217 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
2218 r
.in
.offered
= needed
;
2219 status
= dcerpc_spoolss_GetPrinterDataEx(p
, tctx
, &r
);
2220 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
2223 torture_assert_werr_ok(tctx
, r
.out
.result
,
2224 talloc_asprintf(tctx
, "GetPrinterDataEx(%s - %s) failed", r
.in
.key_name
, r
.in
.value_name
));
2226 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData
, &data
, type
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 1);
2239 static bool test_GetPrinterData_list(struct torture_context
*tctx
,
2240 struct dcerpc_pipe
*p
,
2241 struct policy_handle
*handle
)
2243 const char *list
[] = {
2247 /* "NetPopup", not on w2k8 */
2248 /* "NetPopupToComputer", not on w2k8 */
2251 "DefaultSpoolDirectory",
2255 /* "OSVersionEx", not on s3 */
2260 for (i
=0; i
< ARRAY_SIZE(list
); i
++) {
2261 enum winreg_Type type
, type_ex
;
2262 union spoolss_PrinterData data
, data_ex
;
2264 torture_assert(tctx
, test_GetPrinterData(tctx
, p
, handle
, list
[i
], &type
, &data
),
2265 talloc_asprintf(tctx
, "GetPrinterData failed on %s\n", list
[i
]));
2266 torture_assert(tctx
, test_GetPrinterDataEx(tctx
, p
, handle
, "random_string", list
[i
], &type_ex
, &data_ex
),
2267 talloc_asprintf(tctx
, "GetPrinterDataEx failed on %s\n", list
[i
]));
2268 torture_assert_int_equal(tctx
, type
, type_ex
, "type mismatch");
2271 torture_assert_str_equal(tctx
, data
.string
, data_ex
.string
, "REG_SZ mismatch");
2274 torture_assert_int_equal(tctx
, data
.value
, data_ex
.value
, "REG_DWORD mismatch");
2277 torture_assert_data_blob_equal(tctx
, data
.binary
, data_ex
.binary
, "REG_BINARY mismatch");
2287 static bool test_EnumPrinterData(struct torture_context
*tctx
, struct dcerpc_pipe
*p
,
2288 struct policy_handle
*handle
)
2291 struct spoolss_EnumPrinterData r
;
2294 r
.in
.handle
= handle
;
2295 r
.in
.enum_index
= 0;
2298 uint32_t value_size
= 0;
2299 uint32_t data_size
= 0;
2300 enum winreg_Type type
= 0;
2302 r
.in
.value_offered
= value_size
;
2303 r
.out
.value_needed
= &value_size
;
2304 r
.in
.data_offered
= data_size
;
2305 r
.out
.data_needed
= &data_size
;
2308 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, 0);
2310 torture_comment(tctx
, "Testing EnumPrinterData\n");
2312 status
= dcerpc_spoolss_EnumPrinterData(p
, tctx
, &r
);
2314 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterData failed");
2315 if (W_ERROR_EQUAL(r
.out
.result
, WERR_NO_MORE_ITEMS
)) {
2318 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterData");
2320 r
.in
.value_offered
= value_size
;
2321 r
.out
.value_name
= talloc_zero_array(tctx
, const char, value_size
);
2322 r
.in
.data_offered
= data_size
;
2323 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, data_size
);
2325 status
= dcerpc_spoolss_EnumPrinterData(p
, tctx
, &r
);
2327 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterData failed");
2328 if (W_ERROR_EQUAL(r
.out
.result
, WERR_NO_MORE_ITEMS
)) {
2332 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterData failed");
2334 torture_assert(tctx
, test_GetPrinterData(tctx
, p
, handle
, r
.out
.value_name
, NULL
, NULL
),
2335 talloc_asprintf(tctx
, "failed to call GetPrinterData for %s\n", r
.out
.value_name
));
2337 torture_assert(tctx
, test_GetPrinterDataEx(tctx
, p
, handle
, "PrinterDriverData", r
.out
.value_name
, NULL
, NULL
),
2338 talloc_asprintf(tctx
, "failed to call GetPrinterDataEx on PrinterDriverData for %s\n", r
.out
.value_name
));
2342 } while (W_ERROR_IS_OK(r
.out
.result
));
2347 static bool test_EnumPrinterDataEx(struct torture_context
*tctx
,
2348 struct dcerpc_pipe
*p
,
2349 struct policy_handle
*handle
,
2350 const char *key_name
)
2352 struct spoolss_EnumPrinterDataEx r
;
2353 struct spoolss_PrinterEnumValues
*info
;
2357 r
.in
.handle
= handle
;
2358 r
.in
.key_name
= key_name
;
2360 r
.out
.needed
= &needed
;
2361 r
.out
.count
= &count
;
2364 torture_comment(tctx
, "Testing EnumPrinterDataEx(%s)\n", key_name
);
2366 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterDataEx(p
, tctx
, &r
),
2367 "EnumPrinterDataEx failed");
2368 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
2369 r
.in
.offered
= needed
;
2370 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterDataEx(p
, tctx
, &r
),
2371 "EnumPrinterDataEx failed");
2374 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDataEx failed");
2376 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx
, info
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 1);
2382 static bool test_DeletePrinterData(struct torture_context
*tctx
,
2383 struct dcerpc_pipe
*p
,
2384 struct policy_handle
*handle
,
2385 const char *value_name
)
2388 struct spoolss_DeletePrinterData r
;
2390 r
.in
.handle
= handle
;
2391 r
.in
.value_name
= value_name
;
2393 torture_comment(tctx
, "Testing DeletePrinterData(%s)\n",
2396 status
= dcerpc_spoolss_DeletePrinterData(p
, tctx
, &r
);
2398 torture_assert_ntstatus_ok(tctx
, status
, "DeletePrinterData failed");
2399 torture_assert_werr_ok(tctx
, r
.out
.result
, "DeletePrinterData failed");
2404 static bool test_DeletePrinterDataEx(struct torture_context
*tctx
,
2405 struct dcerpc_pipe
*p
,
2406 struct policy_handle
*handle
,
2407 const char *key_name
,
2408 const char *value_name
)
2410 struct spoolss_DeletePrinterDataEx r
;
2412 r
.in
.handle
= handle
;
2413 r
.in
.key_name
= key_name
;
2414 r
.in
.value_name
= value_name
;
2416 torture_comment(tctx
, "Testing DeletePrinterDataEx(%s - %s)\n",
2417 r
.in
.key_name
, r
.in
.value_name
);
2419 torture_assert_ntstatus_ok(tctx
,
2420 dcerpc_spoolss_DeletePrinterDataEx(p
, tctx
, &r
),
2421 "DeletePrinterDataEx failed");
2422 torture_assert_werr_ok(tctx
, r
.out
.result
,
2423 "DeletePrinterDataEx failed");
2428 static bool test_DeletePrinterKey(struct torture_context
*tctx
,
2429 struct dcerpc_pipe
*p
,
2430 struct policy_handle
*handle
,
2431 const char *key_name
)
2433 struct spoolss_DeletePrinterKey r
;
2435 r
.in
.handle
= handle
;
2436 r
.in
.key_name
= key_name
;
2438 torture_comment(tctx
, "Testing DeletePrinterKey(%s)\n", r
.in
.key_name
);
2440 if (strequal(key_name
, "") && !torture_setting_bool(tctx
, "dangerous", false)) {
2441 torture_skip(tctx
, "not wiping out printer registry - enable dangerous tests to use\n");
2445 torture_assert_ntstatus_ok(tctx
,
2446 dcerpc_spoolss_DeletePrinterKey(p
, tctx
, &r
),
2447 "DeletePrinterKey failed");
2448 torture_assert_werr_ok(tctx
, r
.out
.result
,
2449 "DeletePrinterKey failed");
2454 static bool test_SetPrinterData(struct torture_context
*tctx
,
2455 struct dcerpc_pipe
*p
,
2456 struct policy_handle
*handle
)
2459 struct spoolss_SetPrinterData r
;
2460 const char *values
[] = {
2464 /* FIXME: not working with s3 atm. */
2470 /* FIXME: not working with s3 atm. */
2477 for (i
=0; i
< ARRAY_SIZE(values
); i
++) {
2479 enum winreg_Type type
;
2480 union spoolss_PrinterData data
;
2482 r
.in
.handle
= handle
;
2483 r
.in
.value_name
= values
[i
];
2485 r
.in
.data
.string
= "dog";
2487 torture_comment(tctx
, "Testing SetPrinterData(%s)\n",
2490 status
= dcerpc_spoolss_SetPrinterData(p
, tctx
, &r
);
2492 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinterData failed");
2493 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinterData failed");
2495 if (!test_GetPrinterData(tctx
, p
, handle
, r
.in
.value_name
, &type
, &data
)) {
2499 torture_assert_int_equal(tctx
, r
.in
.type
, type
, "type mismatch");
2500 torture_assert_str_equal(tctx
, r
.in
.data
.string
, data
.string
, "data mismatch");
2502 if (!test_DeletePrinterData(tctx
, p
, handle
, r
.in
.value_name
)) {
2510 static bool test_EnumPrinterKey(struct torture_context
*tctx
,
2511 struct dcerpc_pipe
*p
,
2512 struct policy_handle
*handle
,
2513 const char *key_name
,
2514 const char ***array
);
2516 static bool test_SetPrinterDataEx(struct torture_context
*tctx
,
2517 struct dcerpc_pipe
*p
,
2518 struct policy_handle
*handle
)
2521 struct spoolss_SetPrinterDataEx r
;
2522 const char *value_name
= "dog";
2523 const char *keys
[] = {
2527 /* FIXME: not working with s3 atm. */
2528 "torturedataex_with_subkey\\subkey",
2529 "torturedataex_with_subkey\\subkey:0",
2530 "torturedataex_with_subkey\\subkey:1",
2531 "torturedataex_with_subkey\\subkey\\subsubkey",
2532 "torturedataex_with_subkey\\subkey\\subsubkey:0",
2533 "torturedataex_with_subkey\\subkey\\subsubkey:1",
2537 /* FIXME: not working with s3 atm. */
2545 DATA_BLOB blob
= data_blob_string_const("catfoobar");
2548 for (i
=0; i
< ARRAY_SIZE(keys
); i
++) {
2552 enum winreg_Type type
;
2553 const char **subkeys
;
2554 union spoolss_PrinterData data
;
2556 r
.in
.handle
= handle
;
2557 r
.in
.key_name
= keys
[i
];
2558 r
.in
.value_name
= value_name
;
2559 r
.in
.type
= REG_BINARY
;
2560 r
.in
.data
.binary
= blob
;
2562 torture_comment(tctx
, "Testing SetPrinterDataEx(%s - %s)\n", r
.in
.key_name
, value_name
);
2564 status
= dcerpc_spoolss_SetPrinterDataEx(p
, tctx
, &r
);
2566 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinterDataEx failed");
2567 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinterDataEx failed");
2569 key
= talloc_strdup(tctx
, r
.in
.key_name
);
2571 if (!test_GetPrinterDataEx(tctx
, p
, handle
, r
.in
.key_name
, value_name
, &type
, &data
)) {
2575 torture_assert_int_equal(tctx
, r
.in
.type
, type
, "type mismatch");
2576 torture_assert_data_blob_equal(tctx
, blob
, data
.binary
, "data mismatch");
2578 if (!test_EnumPrinterDataEx(tctx
, p
, handle
, r
.in
.key_name
)) {
2582 if (!test_DeletePrinterDataEx(tctx
, p
, handle
, r
.in
.key_name
, value_name
)) {
2586 c
= strchr(key
, '\\');
2590 /* we have subkeys */
2594 if (!test_EnumPrinterKey(tctx
, p
, handle
, key
, &subkeys
)) {
2598 for (i
=0; subkeys
&& subkeys
[i
]; i
++) {
2600 const char *current_key
= talloc_asprintf(tctx
, "%s\\%s", key
, subkeys
[i
]);
2602 if (!test_DeletePrinterKey(tctx
, p
, handle
, current_key
)) {
2607 if (!test_DeletePrinterKey(tctx
, p
, handle
, key
)) {
2612 if (!test_DeletePrinterKey(tctx
, p
, handle
, key
)) {
2622 static bool test_SecondaryClosePrinter(struct torture_context
*tctx
,
2623 struct dcerpc_pipe
*p
,
2624 struct policy_handle
*handle
)
2627 struct dcerpc_binding
*b
;
2628 struct dcerpc_pipe
*p2
;
2629 struct spoolss_ClosePrinter cp
;
2631 /* only makes sense on SMB */
2632 if (p
->conn
->transport
.transport
!= NCACN_NP
) {
2636 torture_comment(tctx
, "testing close on secondary pipe\n");
2638 status
= dcerpc_parse_binding(tctx
, p
->conn
->binding_string
, &b
);
2639 torture_assert_ntstatus_ok(tctx
, status
, "Failed to parse dcerpc binding");
2641 status
= dcerpc_secondary_connection(p
, &p2
, b
);
2642 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create secondary connection");
2644 status
= dcerpc_bind_auth_none(p2
, &ndr_table_spoolss
);
2645 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create bind on secondary connection");
2647 cp
.in
.handle
= handle
;
2648 cp
.out
.handle
= handle
;
2650 status
= dcerpc_spoolss_ClosePrinter(p2
, tctx
, &cp
);
2651 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_NET_WRITE_FAULT
,
2652 "ERROR: Allowed close on secondary connection");
2654 torture_assert_int_equal(tctx
, p2
->last_fault_code
, DCERPC_FAULT_CONTEXT_MISMATCH
,
2655 "Unexpected fault code");
2662 static bool test_OpenPrinter_badname(struct torture_context
*tctx
,
2663 struct dcerpc_pipe
*p
, const char *name
)
2666 struct spoolss_OpenPrinter op
;
2667 struct spoolss_OpenPrinterEx opEx
;
2668 struct policy_handle handle
;
2671 op
.in
.printername
= name
;
2672 op
.in
.datatype
= NULL
;
2673 op
.in
.devmode_ctr
.devmode
= NULL
;
2674 op
.in
.access_mask
= 0;
2675 op
.out
.handle
= &handle
;
2677 torture_comment(tctx
, "\nTesting OpenPrinter(%s) with bad name\n", op
.in
.printername
);
2679 status
= dcerpc_spoolss_OpenPrinter(p
, tctx
, &op
);
2680 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
2681 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME
,op
.out
.result
)) {
2682 torture_comment(tctx
, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
2683 name
, win_errstr(op
.out
.result
));
2686 if (W_ERROR_IS_OK(op
.out
.result
)) {
2687 ret
&=test_ClosePrinter(tctx
, p
, &handle
);
2690 opEx
.in
.printername
= name
;
2691 opEx
.in
.datatype
= NULL
;
2692 opEx
.in
.devmode_ctr
.devmode
= NULL
;
2693 opEx
.in
.access_mask
= 0;
2695 opEx
.in
.userlevel
.level1
= NULL
;
2696 opEx
.out
.handle
= &handle
;
2698 torture_comment(tctx
, "Testing OpenPrinterEx(%s) with bad name\n", opEx
.in
.printername
);
2700 status
= dcerpc_spoolss_OpenPrinterEx(p
, tctx
, &opEx
);
2701 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinterEx failed");
2702 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM
,opEx
.out
.result
)) {
2703 torture_comment(tctx
, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
2704 name
, win_errstr(opEx
.out
.result
));
2707 if (W_ERROR_IS_OK(opEx
.out
.result
)) {
2708 ret
&=test_ClosePrinter(tctx
, p
, &handle
);
2714 static bool test_OpenPrinter(struct torture_context
*tctx
,
2715 struct dcerpc_pipe
*p
,
2719 struct spoolss_OpenPrinter r
;
2720 struct policy_handle handle
;
2723 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s\\%s", dcerpc_server_name(p
), name
);
2724 r
.in
.datatype
= NULL
;
2725 r
.in
.devmode_ctr
.devmode
= NULL
;
2726 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
2727 r
.out
.handle
= &handle
;
2729 torture_comment(tctx
, "Testing OpenPrinter(%s)\n", r
.in
.printername
);
2731 status
= dcerpc_spoolss_OpenPrinter(p
, tctx
, &r
);
2733 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
2735 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenPrinter failed");
2737 if (!test_GetPrinter(tctx
, p
, &handle
)) {
2741 if (!torture_setting_bool(tctx
, "samba3", false)) {
2742 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
2747 if (!test_ClosePrinter(tctx
, p
, &handle
)) {
2754 static bool call_OpenPrinterEx(struct torture_context
*tctx
,
2755 struct dcerpc_pipe
*p
,
2756 const char *name
, struct policy_handle
*handle
)
2758 struct spoolss_OpenPrinterEx r
;
2759 struct spoolss_UserLevel1 userlevel1
;
2762 if (name
&& name
[0]) {
2763 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s\\%s",
2764 dcerpc_server_name(p
), name
);
2766 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s",
2767 dcerpc_server_name(p
));
2770 r
.in
.datatype
= NULL
;
2771 r
.in
.devmode_ctr
.devmode
= NULL
;
2772 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
2774 r
.in
.userlevel
.level1
= &userlevel1
;
2775 r
.out
.handle
= handle
;
2777 userlevel1
.size
= 1234;
2778 userlevel1
.client
= "hello";
2779 userlevel1
.user
= "spottyfoot!";
2780 userlevel1
.build
= 1;
2781 userlevel1
.major
= 2;
2782 userlevel1
.minor
= 3;
2783 userlevel1
.processor
= 4;
2785 torture_comment(tctx
, "Testing OpenPrinterEx(%s)\n", r
.in
.printername
);
2787 status
= dcerpc_spoolss_OpenPrinterEx(p
, tctx
, &r
);
2789 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinterEx failed");
2791 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenPrinterEx failed");
2796 static bool test_OpenPrinterEx(struct torture_context
*tctx
,
2797 struct dcerpc_pipe
*p
,
2800 struct policy_handle handle
;
2803 if (!call_OpenPrinterEx(tctx
, p
, name
, &handle
)) {
2807 if (!test_GetPrinter(tctx
, p
, &handle
)) {
2811 if (!test_EnumForms(tctx
, p
, &handle
, false)) {
2815 if (!test_AddForm(tctx
, p
, &handle
, false)) {
2819 if (!test_EnumPrinterData(tctx
, p
, &handle
)) {
2823 if (!test_EnumPrinterDataEx(tctx
, p
, &handle
, "PrinterDriverData")) {
2827 if (!test_printer_keys(tctx
, p
, &handle
)) {
2831 if (!test_PausePrinter(tctx
, p
, &handle
)) {
2835 if (!test_DoPrintTest(tctx
, p
, &handle
)) {
2839 if (!test_ResumePrinter(tctx
, p
, &handle
)) {
2843 if (!test_SetPrinterData(tctx
, p
, &handle
)) {
2847 if (!test_SetPrinterDataEx(tctx
, p
, &handle
)) {
2851 if (!torture_setting_bool(tctx
, "samba3", false)) {
2852 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
2857 if (!test_ClosePrinter(tctx
, p
, &handle
)) {
2864 static bool test_EnumPrinters_old(struct torture_context
*tctx
, struct dcerpc_pipe
*p
)
2866 struct spoolss_EnumPrinters r
;
2868 uint16_t levels
[] = {1, 2, 4, 5};
2872 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
2873 union spoolss_PrinterInfo
*info
;
2878 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
2880 r
.in
.level
= levels
[i
];
2883 r
.out
.needed
= &needed
;
2884 r
.out
.count
= &count
;
2887 torture_comment(tctx
, "Testing EnumPrinters level %u\n", r
.in
.level
);
2889 status
= dcerpc_spoolss_EnumPrinters(p
, tctx
, &r
);
2890 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
2892 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2893 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2894 data_blob_clear(&blob
);
2895 r
.in
.buffer
= &blob
;
2896 r
.in
.offered
= needed
;
2897 status
= dcerpc_spoolss_EnumPrinters(p
, tctx
, &r
);
2900 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
2902 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
2904 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
2907 torture_comment(tctx
, "No printers returned\n");
2911 for (j
=0;j
<count
;j
++) {
2912 if (r
.in
.level
== 1) {
2913 char *unc
= talloc_strdup(tctx
, info
[j
].info1
.name
);
2916 if (unc
[0] == '\\' && unc
[1] == '\\') {
2919 slash
= strchr(unc
, '\\');
2924 if (!test_OpenPrinter(tctx
, p
, name
)) {
2927 if (!test_OpenPrinterEx(tctx
, p
, name
)) {
2937 static bool test_GetPrinterDriver(struct torture_context
*tctx
,
2938 struct dcerpc_pipe
*p
,
2939 struct policy_handle
*handle
,
2940 const char *driver_name
)
2942 struct spoolss_GetPrinterDriver r
;
2945 r
.in
.handle
= handle
;
2946 r
.in
.architecture
= "W32X86";
2950 r
.out
.needed
= &needed
;
2952 torture_comment(tctx
, "Testing GetPrinterDriver level %d\n", r
.in
.level
);
2954 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver(p
, tctx
, &r
),
2955 "failed to call GetPrinterDriver");
2956 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2957 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2958 data_blob_clear(&blob
);
2959 r
.in
.buffer
= &blob
;
2960 r
.in
.offered
= needed
;
2961 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver(p
, tctx
, &r
),
2962 "failed to call GetPrinterDriver");
2965 torture_assert_werr_ok(tctx
, r
.out
.result
,
2966 "failed to call GetPrinterDriver");
2968 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
2973 static bool test_GetPrinterDriver2(struct torture_context
*tctx
,
2974 struct dcerpc_pipe
*p
,
2975 struct policy_handle
*handle
,
2976 const char *driver_name
)
2978 struct spoolss_GetPrinterDriver2 r
;
2979 uint16_t levels
[] = {1, 2, 3, 4, 5, 6, 8, 101 };
2981 uint32_t server_major_version
;
2982 uint32_t server_minor_version
;
2985 r
.in
.handle
= handle
;
2986 r
.in
.architecture
= SPOOLSS_ARCHITECTURE_NT_X86
;
2987 r
.in
.client_major_version
= 3;
2988 r
.in
.client_minor_version
= 0;
2989 r
.out
.needed
= &needed
;
2990 r
.out
.server_major_version
= &server_major_version
;
2991 r
.out
.server_minor_version
= &server_minor_version
;
2993 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
2997 r
.in
.level
= levels
[i
];
2999 torture_comment(tctx
, "Testing GetPrinterDriver2(%s) level %d\n",
3000 driver_name
, r
.in
.level
);
3002 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver2(p
, tctx
, &r
),
3003 "failed to call GetPrinterDriver2");
3004 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
3005 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
3006 data_blob_clear(&blob
);
3007 r
.in
.buffer
= &blob
;
3008 r
.in
.offered
= needed
;
3009 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver2(p
, tctx
, &r
),
3010 "failed to call GetPrinterDriver2");
3013 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INVALID_LEVEL
)) {
3014 switch (r
.in
.level
) {
3023 torture_assert_werr_ok(tctx
, r
.out
.result
,
3024 "failed to call GetPrinterDriver2");
3026 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
3032 static bool test_EnumPrinterDrivers_old(struct torture_context
*tctx
,
3033 struct dcerpc_pipe
*p
)
3035 struct spoolss_EnumPrinterDrivers r
;
3037 uint16_t levels
[] = {1, 2, 3, 4, 5, 6};
3040 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
3044 union spoolss_DriverInfo
*info
;
3046 r
.in
.server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
3047 r
.in
.environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
3048 r
.in
.level
= levels
[i
];
3051 r
.out
.needed
= &needed
;
3052 r
.out
.count
= &count
;
3055 torture_comment(tctx
, "Testing EnumPrinterDrivers level %u\n", r
.in
.level
);
3057 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, tctx
, &r
);
3059 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterDrivers failed");
3061 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
3062 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
3063 data_blob_clear(&blob
);
3064 r
.in
.buffer
= &blob
;
3065 r
.in
.offered
= needed
;
3066 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, tctx
, &r
);
3069 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterDrivers failed");
3071 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDrivers failed");
3074 torture_comment(tctx
, "No printer drivers returned\n");
3078 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
3084 static bool test_DeletePrinter(struct torture_context
*tctx
,
3085 struct dcerpc_pipe
*p
,
3086 struct policy_handle
*handle
)
3088 struct spoolss_DeletePrinter r
;
3090 torture_comment(tctx
, "Testing DeletePrinter\n");
3092 r
.in
.handle
= handle
;
3094 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_DeletePrinter(p
, tctx
, &r
),
3095 "failed to delete printer");
3096 torture_assert_werr_ok(tctx
, r
.out
.result
,
3097 "failed to delete printer");
3102 static bool test_EnumPrinters_findname(struct torture_context
*tctx
,
3103 struct dcerpc_pipe
*p
,
3109 struct spoolss_EnumPrinters e
;
3111 union spoolss_PrinterInfo
*info
;
3122 e
.out
.count
= &count
;
3124 e
.out
.needed
= &needed
;
3126 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters(p
, tctx
, &e
),
3127 "failed to enum printers");
3129 if (W_ERROR_EQUAL(e
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
3130 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
3131 data_blob_clear(&blob
);
3132 e
.in
.buffer
= &blob
;
3133 e
.in
.offered
= needed
;
3135 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters(p
, tctx
, &e
),
3136 "failed to enum printers");
3139 torture_assert_werr_ok(tctx
, e
.out
.result
,
3140 "failed to enum printers");
3142 for (i
=0; i
< count
; i
++) {
3144 const char *current
= NULL
;
3148 current
= info
[i
].info1
.name
;
3152 if (strequal(current
, name
)) {
3161 static bool test_AddPrinter_wellknown(struct torture_context
*tctx
,
3162 struct dcerpc_pipe
*p
,
3163 const char *printername
,
3167 struct spoolss_AddPrinter r
;
3168 struct spoolss_AddPrinterEx rex
;
3169 struct spoolss_SetPrinterInfoCtr info_ctr
;
3170 struct spoolss_SetPrinterInfo1 info1
;
3171 struct spoolss_DevmodeContainer devmode_ctr
;
3172 struct sec_desc_buf secdesc_ctr
;
3173 struct spoolss_UserLevelCtr userlevel_ctr
;
3174 struct policy_handle handle
;
3177 ZERO_STRUCT(devmode_ctr
);
3178 ZERO_STRUCT(secdesc_ctr
);
3179 ZERO_STRUCT(userlevel_ctr
);
3182 torture_comment(tctx
, "Testing AddPrinter%s level 1\n", ex
? "Ex":"");
3184 /* try to add printer to wellknown printer list (level 1) */
3186 userlevel_ctr
.level
= 1;
3188 info_ctr
.info
.info1
= &info1
;
3191 rex
.in
.server
= NULL
;
3192 rex
.in
.info_ctr
= &info_ctr
;
3193 rex
.in
.devmode_ctr
= &devmode_ctr
;
3194 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
3195 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
3196 rex
.out
.handle
= &handle
;
3199 r
.in
.info_ctr
= &info_ctr
;
3200 r
.in
.devmode_ctr
= &devmode_ctr
;
3201 r
.in
.secdesc_ctr
= &secdesc_ctr
;
3202 r
.out
.handle
= &handle
;
3204 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3205 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3206 "failed to add printer");
3207 result
= ex
? rex
.out
.result
: r
.out
.result
;
3208 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
3209 "unexpected result code");
3211 info1
.name
= printername
;
3212 info1
.flags
= PRINTER_ATTRIBUTE_SHARED
;
3214 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3215 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3216 "failed to add printer");
3217 result
= ex
? rex
.out
.result
: r
.out
.result
;
3218 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
3219 "unexpected result code");
3221 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
3222 better do a real check to see the printer is really there */
3224 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, p
,
3225 PRINTER_ENUM_NETWORK
, 1,
3228 "failed to enum printers");
3230 torture_assert(tctx
, found
, "failed to find newly added printer");
3234 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3235 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3236 "failed to add printer");
3237 result
= ex
? rex
.out
.result
: r
.out
.result
;
3238 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
3239 "unexpected result code");
3241 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
3242 better do a real check to see the printer has really been removed
3243 from the well known printer list */
3247 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, p
,
3248 PRINTER_ENUM_NETWORK
, 1,
3251 "failed to enum printers");
3253 torture_assert(tctx
, !found
, "printer still in well known printer list");
3258 static bool test_AddPrinter_normal(struct torture_context
*tctx
,
3259 struct dcerpc_pipe
*p
,
3260 struct policy_handle
*handle_p
,
3261 const char *printername
,
3262 const char *drivername
,
3263 const char *portname
,
3267 struct spoolss_AddPrinter r
;
3268 struct spoolss_AddPrinterEx rex
;
3269 struct spoolss_SetPrinterInfoCtr info_ctr
;
3270 struct spoolss_SetPrinterInfo2 info2
;
3271 struct spoolss_DevmodeContainer devmode_ctr
;
3272 struct sec_desc_buf secdesc_ctr
;
3273 struct spoolss_UserLevelCtr userlevel_ctr
;
3274 struct policy_handle handle
;
3277 ZERO_STRUCT(devmode_ctr
);
3278 ZERO_STRUCT(secdesc_ctr
);
3279 ZERO_STRUCT(userlevel_ctr
);
3281 torture_comment(tctx
, "Testing AddPrinter%s level 2\n", ex
? "Ex":"");
3283 userlevel_ctr
.level
= 1;
3285 rex
.in
.server
= NULL
;
3286 rex
.in
.info_ctr
= &info_ctr
;
3287 rex
.in
.devmode_ctr
= &devmode_ctr
;
3288 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
3289 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
3290 rex
.out
.handle
= &handle
;
3293 r
.in
.info_ctr
= &info_ctr
;
3294 r
.in
.devmode_ctr
= &devmode_ctr
;
3295 r
.in
.secdesc_ctr
= &secdesc_ctr
;
3296 r
.out
.handle
= &handle
;
3300 /* try to add printer to printer list (level 2) */
3304 info_ctr
.info
.info2
= &info2
;
3307 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3308 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3309 "failed to add printer");
3310 result
= ex
? rex
.out
.result
: r
.out
.result
;
3311 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
3312 "unexpected result code");
3314 info2
.printername
= printername
;
3316 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3317 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3318 "failed to add printer");
3319 result
= ex
? rex
.out
.result
: r
.out
.result
;
3321 if (W_ERROR_EQUAL(result
, WERR_PRINTER_ALREADY_EXISTS
)) {
3322 struct policy_handle printer_handle
;
3324 torture_assert(tctx
, call_OpenPrinterEx(tctx
, p
, printername
, &printer_handle
),
3325 "failed to open printer handle");
3327 torture_assert(tctx
, test_DeletePrinter(tctx
, p
, &printer_handle
),
3328 "failed to delete printer");
3330 torture_assert(tctx
, test_ClosePrinter(tctx
, p
, &printer_handle
),
3331 "failed to close server handle");
3336 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PORT
,
3337 "unexpected result code");
3339 info2
.portname
= portname
;
3341 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3342 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3343 "failed to add printer");
3344 result
= ex
? rex
.out
.result
: r
.out
.result
;
3345 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTER_DRIVER
,
3346 "unexpected result code");
3348 info2
.drivername
= drivername
;
3350 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3351 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3352 "failed to add printer");
3353 result
= ex
? rex
.out
.result
: r
.out
.result
;
3354 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTPROCESSOR
,
3355 "unexpected result code");
3357 info2
.printprocessor
= "winprint";
3359 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3360 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3361 "failed to add printer");
3362 result
= ex
? rex
.out
.result
: r
.out
.result
;
3363 torture_assert_werr_ok(tctx
, result
,
3364 "failed to add printer");
3368 /* we are paranoid, really check if the printer is there now */
3370 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, p
,
3371 PRINTER_ENUM_LOCAL
, 1,
3374 "failed to enum printers");
3375 torture_assert(tctx
, found
, "failed to find newly added printer");
3377 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3378 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3379 "failed to add printer");
3380 result
= ex
? rex
.out
.result
: r
.out
.result
;
3381 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
3382 "unexpected result code");
3387 static bool test_AddPrinterEx(struct torture_context
*tctx
,
3388 struct dcerpc_pipe
*p
,
3389 struct policy_handle
*handle_p
,
3390 const char *printername
,
3391 const char *drivername
,
3392 const char *portname
)
3396 if (!torture_setting_bool(tctx
, "samba3", false)) {
3397 if (!test_AddPrinter_wellknown(tctx
, p
, TORTURE_WELLKNOWN_PRINTER_EX
, true)) {
3398 torture_comment(tctx
, "failed to add printer to well known list\n");
3403 if (!test_AddPrinter_normal(tctx
, p
, handle_p
,
3404 printername
, drivername
, portname
,
3406 torture_comment(tctx
, "failed to add printer to printer list\n");
3413 static bool test_AddPrinter(struct torture_context
*tctx
,
3414 struct dcerpc_pipe
*p
,
3415 struct policy_handle
*handle_p
,
3416 const char *printername
,
3417 const char *drivername
,
3418 const char *portname
)
3422 if (!torture_setting_bool(tctx
, "samba3", false)) {
3423 if (!test_AddPrinter_wellknown(tctx
, p
, TORTURE_WELLKNOWN_PRINTER
, false)) {
3424 torture_comment(tctx
, "failed to add printer to well known list\n");
3429 if (!test_AddPrinter_normal(tctx
, p
, handle_p
,
3430 printername
, drivername
, portname
,
3432 torture_comment(tctx
, "failed to add printer to printer list\n");
3439 static bool test_printer_info(struct torture_context
*tctx
,
3440 struct dcerpc_pipe
*p
,
3441 struct policy_handle
*handle
)
3445 if (!test_PrinterInfo(tctx
, p
, handle
)) {
3449 if (!test_SetPrinter_errors(tctx
, p
, handle
)) {
3456 static bool test_EnumPrinterKey(struct torture_context
*tctx
,
3457 struct dcerpc_pipe
*p
,
3458 struct policy_handle
*handle
,
3459 const char *key_name
,
3460 const char ***array
)
3462 struct spoolss_EnumPrinterKey r
;
3463 uint32_t needed
= 0;
3464 union spoolss_KeyNames key_buffer
;
3465 int32_t offered
[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
3469 r
.in
.handle
= handle
;
3470 r
.in
.key_name
= key_name
;
3471 r
.out
.key_buffer
= &key_buffer
;
3472 r
.out
.needed
= &needed
;
3473 r
.out
._ndr_size
= &_ndr_size
;
3475 for (i
=0; i
< ARRAY_SIZE(offered
); i
++) {
3477 if (offered
[i
] < 0 && needed
) {
3481 r
.in
.offered
= needed
+ offered
[i
];
3483 r
.in
.offered
= offered
[i
];
3486 ZERO_STRUCT(key_buffer
);
3488 torture_comment(tctx
, "Testing EnumPrinterKey(%s) with %d offered\n", r
.in
.key_name
, r
.in
.offered
);
3490 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterKey(p
, tctx
, &r
),
3491 "failed to call EnumPrinterKey");
3492 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
3494 torture_assert(tctx
, (_ndr_size
== r
.in
.offered
/2),
3495 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
3496 _ndr_size
, r
.in
.offered
/2));
3498 r
.in
.offered
= needed
;
3499 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterKey(p
, tctx
, &r
),
3500 "failed to call EnumPrinterKey");
3503 if (offered
[i
] > 0) {
3504 torture_assert_werr_ok(tctx
, r
.out
.result
,
3505 "failed to call EnumPrinterKey");
3508 torture_assert(tctx
, (_ndr_size
== r
.in
.offered
/2),
3509 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
3510 _ndr_size
, r
.in
.offered
/2));
3512 torture_assert(tctx
, (*r
.out
.needed
<= r
.in
.offered
),
3513 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r
.out
.needed
, r
.in
.offered
));
3515 torture_assert(tctx
, (*r
.out
.needed
<= _ndr_size
* 2),
3516 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r
.out
.needed
, _ndr_size
));
3518 if (key_buffer
.string_array
) {
3519 uint32_t calc_needed
= 0;
3521 for (s
=0; key_buffer
.string_array
[s
]; s
++) {
3522 calc_needed
+= strlen_m_term(key_buffer
.string_array
[s
])*2;
3524 if (!key_buffer
.string_array
[0]) {
3529 torture_assert_int_equal(tctx
, *r
.out
.needed
, calc_needed
,
3530 "EnumPrinterKey unexpected size");
3535 *array
= key_buffer
.string_array
;
3541 bool test_printer_keys(struct torture_context
*tctx
,
3542 struct dcerpc_pipe
*p
,
3543 struct policy_handle
*handle
)
3545 const char **key_array
= NULL
;
3548 torture_assert(tctx
, test_EnumPrinterKey(tctx
, p
, handle
, "", &key_array
),
3549 "failed to call test_EnumPrinterKey");
3551 for (i
=0; key_array
&& key_array
[i
]; i
++) {
3552 torture_assert(tctx
, test_EnumPrinterKey(tctx
, p
, handle
, key_array
[i
], NULL
),
3553 "failed to call test_EnumPrinterKey");
3555 for (i
=0; key_array
&& key_array
[i
]; i
++) {
3556 torture_assert(tctx
, test_EnumPrinterDataEx(tctx
, p
, handle
, key_array
[i
]),
3557 "failed to call test_EnumPrinterDataEx");
3563 static bool test_printer(struct torture_context
*tctx
,
3564 struct dcerpc_pipe
*p
)
3567 struct policy_handle handle
[2];
3569 const char *drivername
= "Microsoft XPS Document Writer";
3570 const char *portname
= "LPT1:";
3572 /* test printer created via AddPrinter */
3574 if (!test_AddPrinter(tctx
, p
, &handle
[0], TORTURE_PRINTER
, drivername
, portname
)) {
3578 if (!test_printer_info(tctx
, p
, &handle
[0])) {
3582 if (!test_printer_keys(tctx
, p
, &handle
[0])) {
3586 if (!test_DeletePrinter(tctx
, p
, &handle
[0])) {
3590 if (!test_EnumPrinters_findname(tctx
, p
, PRINTER_ENUM_LOCAL
, 1,
3591 TORTURE_PRINTER
, &found
)) {
3595 torture_assert(tctx
, !found
, "deleted printer still there");
3597 /* test printer created via AddPrinterEx */
3599 if (!test_AddPrinterEx(tctx
, p
, &handle
[1], TORTURE_PRINTER_EX
, drivername
, portname
)) {
3603 if (!test_printer_info(tctx
, p
, &handle
[1])) {
3607 if (!test_printer_keys(tctx
, p
, &handle
[1])) {
3611 if (!test_DeletePrinter(tctx
, p
, &handle
[1])) {
3615 if (!test_EnumPrinters_findname(tctx
, p
, PRINTER_ENUM_LOCAL
, 1,
3616 TORTURE_PRINTER_EX
, &found
)) {
3620 torture_assert(tctx
, !found
, "deleted printer still there");
3625 bool torture_rpc_spoolss(struct torture_context
*torture
)
3628 struct dcerpc_pipe
*p
;
3630 struct test_spoolss_context
*ctx
;
3632 status
= torture_rpc_connection(torture
, &p
, &ndr_table_spoolss
);
3633 if (!NT_STATUS_IS_OK(status
)) {
3637 ctx
= talloc_zero(torture
, struct test_spoolss_context
);
3639 ret
&= test_OpenPrinter_server(torture
, p
, &ctx
->server_handle
);
3640 ret
&= test_GetPrinterData_list(torture
, p
, &ctx
->server_handle
);
3641 ret
&= test_EnumForms(torture
, p
, &ctx
->server_handle
, true);
3642 ret
&= test_AddForm(torture
, p
, &ctx
->server_handle
, true);
3643 ret
&= test_EnumPorts(torture
, p
, ctx
);
3644 ret
&= test_GetPrinterDriverDirectory(torture
, p
, ctx
);
3645 ret
&= test_GetPrintProcessorDirectory(torture
, p
, ctx
);
3646 ret
&= test_EnumPrinterDrivers(torture
, p
, ctx
, SPOOLSS_ARCHITECTURE_NT_X86
);
3647 ret
&= test_EnumPrinterDrivers(torture
, p
, ctx
, SPOOLSS_ARCHITECTURE_ALL
);
3648 ret
&= test_EnumMonitors(torture
, p
, ctx
);
3649 ret
&= test_EnumPrintProcessors(torture
, p
, ctx
);
3650 ret
&= test_EnumPrintProcDataTypes(torture
, p
, ctx
);
3651 ret
&= test_EnumPrinters(torture
, p
, ctx
);
3652 ret
&= test_OpenPrinter_badname(torture
, p
, "__INVALID_PRINTER__");
3653 ret
&= test_OpenPrinter_badname(torture
, p
, "\\\\__INVALID_HOST__");
3654 ret
&= test_OpenPrinter_badname(torture
, p
, "");
3655 ret
&= test_OpenPrinter_badname(torture
, p
, "\\\\\\");
3656 ret
&= test_OpenPrinter_badname(torture
, p
, "\\\\\\__INVALID_PRINTER__");
3657 ret
&= test_OpenPrinter_badname(torture
, p
, talloc_asprintf(torture
, "\\\\%s\\", dcerpc_server_name(p
)));
3658 ret
&= test_OpenPrinter_badname(torture
, p
,
3659 talloc_asprintf(torture
, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p
)));
3662 ret
&= test_AddPort(torture
, p
);
3663 ret
&= test_EnumPorts_old(torture
, p
);
3664 ret
&= test_EnumPrinters_old(torture
, p
);
3665 ret
&= test_EnumPrinterDrivers_old(torture
, p
);
3670 struct torture_suite
*torture_rpc_spoolss_printer(TALLOC_CTX
*mem_ctx
)
3672 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "SPOOLSS-PRINTER");
3674 struct torture_rpc_tcase
*tcase
= torture_suite_add_rpc_iface_tcase(suite
,
3675 "printer", &ndr_table_spoolss
);
3677 torture_rpc_tcase_add_test(tcase
, "printer", test_printer
);