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_spoolss_c.h"
29 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
30 #define TORTURE_PRINTER "torture_printer"
31 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
32 #define TORTURE_PRINTER_EX "torture_printer_ex"
34 struct test_spoolss_context
{
35 /* print server handle */
36 struct policy_handle server_handle
;
39 uint32_t port_count
[3];
40 union spoolss_PortInfo
*ports
[3];
42 /* for EnumPrinterDrivers */
43 uint32_t driver_count
[7];
44 union spoolss_DriverInfo
*drivers
[7];
46 /* for EnumMonitors */
47 uint32_t monitor_count
[3];
48 union spoolss_MonitorInfo
*monitors
[3];
50 /* for EnumPrintProcessors */
51 uint32_t print_processor_count
[2];
52 union spoolss_PrintProcessorInfo
*print_processors
[2];
54 /* for EnumPrinters */
55 uint32_t printer_count
[6];
56 union spoolss_PrinterInfo
*printers
[6];
59 #define COMPARE_STRING(tctx, c,r,e) \
60 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
62 /* not every compiler supports __typeof__() */
64 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
65 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
66 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
68 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
69 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
73 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
76 #define COMPARE_UINT32(tctx, c, r, e) do {\
77 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
78 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
81 #define COMPARE_STRING_ARRAY(tctx, c,r,e)
83 static bool test_OpenPrinter_server(struct torture_context
*tctx
,
84 struct dcerpc_pipe
*p
,
85 struct policy_handle
*server_handle
)
88 struct spoolss_OpenPrinter op
;
90 op
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
91 op
.in
.datatype
= NULL
;
92 op
.in
.devmode_ctr
.devmode
= NULL
;
93 op
.in
.access_mask
= 0;
94 op
.out
.handle
= server_handle
;
96 torture_comment(tctx
, "Testing OpenPrinter(%s)\n", op
.in
.printername
);
98 status
= dcerpc_spoolss_OpenPrinter(p
, tctx
, &op
);
99 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_OpenPrinter failed");
100 torture_assert_werr_ok(tctx
, op
.out
.result
, "dcerpc_spoolss_OpenPrinter failed");
105 static bool test_EnumPorts(struct torture_context
*tctx
,
106 struct dcerpc_pipe
*p
,
107 struct test_spoolss_context
*ctx
)
110 struct spoolss_EnumPorts r
;
111 uint16_t levels
[] = { 1, 2 };
114 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
115 int level
= levels
[i
];
119 union spoolss_PortInfo
*info
;
121 r
.in
.servername
= "";
125 r
.out
.needed
= &needed
;
126 r
.out
.count
= &count
;
129 torture_comment(tctx
, "Testing EnumPorts level %u\n", r
.in
.level
);
131 status
= dcerpc_spoolss_EnumPorts(p
, ctx
, &r
);
132 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPorts failed");
133 if (W_ERROR_IS_OK(r
.out
.result
)) {
134 /* TODO: do some more checks here */
137 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
138 "EnumPorts unexpected return code");
140 blob
= data_blob_talloc(ctx
, NULL
, needed
);
141 data_blob_clear(&blob
);
143 r
.in
.offered
= needed
;
145 status
= dcerpc_spoolss_EnumPorts(p
, ctx
, &r
);
146 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPorts failed");
148 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
150 torture_assert(tctx
, info
, "EnumPorts returned no info");
152 ctx
->port_count
[level
] = count
;
153 ctx
->ports
[level
] = info
;
156 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
157 int level
= levels
[i
];
158 int old_level
= levels
[i
-1];
159 torture_assert_int_equal(tctx
, ctx
->port_count
[level
], ctx
->port_count
[old_level
],
160 "EnumPorts invalid value");
162 /* if the array sizes are not the same we would maybe segfault in the following code */
164 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
165 int level
= levels
[i
];
166 for (j
=0;j
<ctx
->port_count
[level
];j
++) {
167 union spoolss_PortInfo
*cur
= &ctx
->ports
[level
][j
];
168 union spoolss_PortInfo
*ref
= &ctx
->ports
[2][j
];
171 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, port_name
);
174 /* level 2 is our reference, and it makes no sense to compare it to itself */
183 static bool test_GetPrintProcessorDirectory(struct torture_context
*tctx
,
184 struct dcerpc_pipe
*p
,
185 struct test_spoolss_context
*ctx
)
188 struct spoolss_GetPrintProcessorDirectory r
;
203 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
206 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
212 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
213 int level
= levels
[i
].level
;
216 r
.in
.server
= levels
[i
].server
;
217 r
.in
.environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
221 r
.out
.needed
= &needed
;
223 torture_comment(tctx
, "Testing GetPrintProcessorDirectory level %u\n", r
.in
.level
);
225 status
= dcerpc_spoolss_GetPrintProcessorDirectory(p
, ctx
, &r
);
226 torture_assert_ntstatus_ok(tctx
, status
,
227 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
228 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
229 "GetPrintProcessorDirectory unexpected return code");
231 blob
= data_blob_talloc(ctx
, NULL
, needed
);
232 data_blob_clear(&blob
);
234 r
.in
.offered
= needed
;
236 status
= dcerpc_spoolss_GetPrintProcessorDirectory(p
, ctx
, &r
);
237 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
239 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrintProcessorDirectory failed");
246 static bool test_GetPrinterDriverDirectory(struct torture_context
*tctx
,
247 struct dcerpc_pipe
*p
,
248 struct test_spoolss_context
*ctx
)
251 struct spoolss_GetPrinterDriverDirectory r
;
266 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
269 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
275 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
276 int level
= levels
[i
].level
;
279 r
.in
.server
= levels
[i
].server
;
280 r
.in
.environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
284 r
.out
.needed
= &needed
;
286 torture_comment(tctx
, "Testing GetPrinterDriverDirectory level %u\n", r
.in
.level
);
288 status
= dcerpc_spoolss_GetPrinterDriverDirectory(p
, ctx
, &r
);
289 torture_assert_ntstatus_ok(tctx
, status
,
290 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
291 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
292 "GetPrinterDriverDirectory unexpected return code");
294 blob
= data_blob_talloc(ctx
, NULL
, needed
);
295 data_blob_clear(&blob
);
297 r
.in
.offered
= needed
;
299 status
= dcerpc_spoolss_GetPrinterDriverDirectory(p
, ctx
, &r
);
300 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
302 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrinterDriverDirectory failed");
308 static bool test_EnumPrinterDrivers(struct torture_context
*tctx
,
309 struct dcerpc_pipe
*p
,
310 struct test_spoolss_context
*ctx
)
313 struct spoolss_EnumPrinterDrivers r
;
314 uint16_t levels
[] = { 1, 2, 3, 4, 5, 6 };
316 const char *architectures
[] = {
317 SPOOLSS_ARCHITECTURE_NT_X86
,
318 SPOOLSS_ARCHITECTURE_ALL
321 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
322 for (a
=0;a
<ARRAY_SIZE(architectures
);a
++) {
323 int level
= levels
[i
];
327 union spoolss_DriverInfo
*info
;
329 /* FIXME: gd, come back and fix "" as server, and handle
330 * priority of returned error codes in torture test and samba 3
333 r
.in
.server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
334 r
.in
.environment
= architectures
[a
];
338 r
.out
.needed
= &needed
;
339 r
.out
.count
= &count
;
342 torture_comment(tctx
, "Testing EnumPrinterDrivers level %u (%s)\n", r
.in
.level
, r
.in
.environment
);
344 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, ctx
, &r
);
345 torture_assert_ntstatus_ok(tctx
, status
,
346 "dcerpc_spoolss_EnumPrinterDrivers failed");
347 if (W_ERROR_IS_OK(r
.out
.result
)) {
348 /* TODO: do some more checks here */
351 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
352 blob
= data_blob_talloc(ctx
, NULL
, needed
);
353 data_blob_clear(&blob
);
355 r
.in
.offered
= needed
;
357 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, ctx
, &r
);
358 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinterDrivers failed");
361 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDrivers failed");
363 /* don't do cross-architecture comparison */
364 if (strequal(r
.in
.environment
, SPOOLSS_ARCHITECTURE_ALL
)) {
368 ctx
->driver_count
[level
] = count
;
369 ctx
->drivers
[level
] = info
;
373 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
374 int level
= levels
[i
];
375 int old_level
= levels
[i
-1];
377 /* don't do cross-architecture comparison */
378 if (strequal(r
.in
.environment
, SPOOLSS_ARCHITECTURE_ALL
)) {
382 torture_assert_int_equal(tctx
, ctx
->driver_count
[level
], ctx
->driver_count
[old_level
],
383 "EnumPrinterDrivers invalid value");
386 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
387 int level
= levels
[i
];
389 /* don't do cross-architecture comparison */
390 if (strequal(r
.in
.environment
, SPOOLSS_ARCHITECTURE_ALL
)) {
394 for (j
=0;j
<ctx
->driver_count
[level
];j
++) {
395 union spoolss_DriverInfo
*cur
= &ctx
->drivers
[level
][j
];
396 union spoolss_DriverInfo
*ref
= &ctx
->drivers
[6][j
];
399 COMPARE_STRING(tctx
, cur
->info1
, ref
->info6
, driver_name
);
402 COMPARE_UINT32(tctx
, cur
->info2
, ref
->info6
, version
);
403 COMPARE_STRING(tctx
, cur
->info2
, ref
->info6
, driver_name
);
404 COMPARE_STRING(tctx
, cur
->info2
, ref
->info6
, architecture
);
405 COMPARE_STRING(tctx
, cur
->info2
, ref
->info6
, driver_path
);
406 COMPARE_STRING(tctx
, cur
->info2
, ref
->info6
, data_file
);
407 COMPARE_STRING(tctx
, cur
->info2
, ref
->info6
, config_file
);
410 COMPARE_UINT32(tctx
, cur
->info3
, ref
->info6
, version
);
411 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, driver_name
);
412 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, architecture
);
413 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, driver_path
);
414 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, data_file
);
415 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, config_file
);
416 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, help_file
);
417 COMPARE_STRING_ARRAY(tctx
, cur
->info3
, ref
->info6
, dependent_files
);
418 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, monitor_name
);
419 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, default_datatype
);
422 COMPARE_UINT32(tctx
, cur
->info4
, ref
->info6
, version
);
423 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, driver_name
);
424 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, architecture
);
425 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, driver_path
);
426 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, data_file
);
427 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, config_file
);
428 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, help_file
);
429 COMPARE_STRING_ARRAY(tctx
, cur
->info4
, ref
->info6
, dependent_files
);
430 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, monitor_name
);
431 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, default_datatype
);
432 COMPARE_STRING_ARRAY(tctx
, cur
->info4
, ref
->info6
, previous_names
);
435 COMPARE_UINT32(tctx
, cur
->info5
, ref
->info6
, version
);
436 COMPARE_STRING(tctx
, cur
->info5
, ref
->info6
, driver_name
);
437 COMPARE_STRING(tctx
, cur
->info5
, ref
->info6
, architecture
);
438 COMPARE_STRING(tctx
, cur
->info5
, ref
->info6
, driver_path
);
439 COMPARE_STRING(tctx
, cur
->info5
, ref
->info6
, data_file
);
440 COMPARE_STRING(tctx
, cur
->info5
, ref
->info6
, config_file
);
441 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_attributes);*/
442 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, config_version);*/
443 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_version); */
446 /* level 6 is our reference, and it makes no sense to compare it to itself */
455 static bool test_EnumMonitors(struct torture_context
*tctx
,
456 struct dcerpc_pipe
*p
,
457 struct test_spoolss_context
*ctx
)
460 struct spoolss_EnumMonitors r
;
461 uint16_t levels
[] = { 1, 2 };
464 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
465 int level
= levels
[i
];
469 union spoolss_MonitorInfo
*info
;
471 r
.in
.servername
= "";
475 r
.out
.needed
= &needed
;
476 r
.out
.count
= &count
;
479 torture_comment(tctx
, "Testing EnumMonitors level %u\n", r
.in
.level
);
481 status
= dcerpc_spoolss_EnumMonitors(p
, ctx
, &r
);
482 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumMonitors failed");
483 if (W_ERROR_IS_OK(r
.out
.result
)) {
484 /* TODO: do some more checks here */
487 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
488 "EnumMonitors failed");
490 blob
= data_blob_talloc(ctx
, NULL
, needed
);
491 data_blob_clear(&blob
);
493 r
.in
.offered
= needed
;
495 status
= dcerpc_spoolss_EnumMonitors(p
, ctx
, &r
);
496 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumMonitors failed");
498 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumMonitors failed");
500 ctx
->monitor_count
[level
] = count
;
501 ctx
->monitors
[level
] = info
;
504 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
505 int level
= levels
[i
];
506 int old_level
= levels
[i
-1];
507 torture_assert_int_equal(tctx
, ctx
->monitor_count
[level
], ctx
->monitor_count
[old_level
],
508 "EnumMonitors invalid value");
511 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
512 int level
= levels
[i
];
513 for (j
=0;j
<ctx
->monitor_count
[level
];j
++) {
514 union spoolss_MonitorInfo
*cur
= &ctx
->monitors
[level
][j
];
515 union spoolss_MonitorInfo
*ref
= &ctx
->monitors
[2][j
];
518 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, monitor_name
);
521 /* level 2 is our reference, and it makes no sense to compare it to itself */
530 static bool test_EnumPrintProcessors(struct torture_context
*tctx
,
531 struct dcerpc_pipe
*p
,
532 struct test_spoolss_context
*ctx
)
535 struct spoolss_EnumPrintProcessors r
;
536 uint16_t levels
[] = { 1 };
539 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
540 int level
= levels
[i
];
544 union spoolss_PrintProcessorInfo
*info
;
546 r
.in
.servername
= "";
547 r
.in
.environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
551 r
.out
.needed
= &needed
;
552 r
.out
.count
= &count
;
555 torture_comment(tctx
, "Testing EnumPrintProcessors level %u\n", r
.in
.level
);
557 status
= dcerpc_spoolss_EnumPrintProcessors(p
, ctx
, &r
);
558 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcessors failed");
559 if (W_ERROR_IS_OK(r
.out
.result
)) {
560 /* TODO: do some more checks here */
563 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
564 "EnumPrintProcessors unexpected return code");
566 blob
= data_blob_talloc(ctx
, NULL
, needed
);
567 data_blob_clear(&blob
);
569 r
.in
.offered
= needed
;
571 status
= dcerpc_spoolss_EnumPrintProcessors(p
, ctx
, &r
);
572 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcessors failed");
574 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrintProcessors failed");
576 ctx
->print_processor_count
[level
] = count
;
577 ctx
->print_processors
[level
] = info
;
580 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
581 int level
= levels
[i
];
582 int old_level
= levels
[i
-1];
583 torture_assert_int_equal(tctx
, ctx
->print_processor_count
[level
], ctx
->print_processor_count
[old_level
],
584 "EnumPrintProcessors failed");
587 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
588 int level
= levels
[i
];
589 for (j
=0;j
<ctx
->print_processor_count
[level
];j
++) {
591 union spoolss_PrintProcessorInfo
*cur
= &ctx
->print_processors
[level
][j
];
592 union spoolss_PrintProcessorInfo
*ref
= &ctx
->print_processors
[1][j
];
596 /* level 1 is our reference, and it makes no sense to compare it to itself */
605 static bool test_EnumPrintProcDataTypes(struct torture_context
*tctx
,
606 struct dcerpc_pipe
*p
,
607 struct test_spoolss_context
*ctx
)
610 struct spoolss_EnumPrintProcDataTypes r
;
611 uint16_t levels
[] = { 1 };
614 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
615 int level
= levels
[i
];
619 union spoolss_PrintProcDataTypesInfo
*info
;
621 r
.in
.servername
= "";
622 r
.in
.print_processor_name
= "winprint";
626 r
.out
.needed
= &needed
;
627 r
.out
.count
= &count
;
630 torture_comment(tctx
, "Testing EnumPrintProcDataTypes level %u\n", r
.in
.level
);
632 status
= dcerpc_spoolss_EnumPrintProcDataTypes(p
, ctx
, &r
);
633 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcDataType failed");
634 if (W_ERROR_IS_OK(r
.out
.result
)) {
635 /* TODO: do some more checks here */
638 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
639 "EnumPrintProcDataTypes unexpected return code");
641 blob
= data_blob_talloc(ctx
, NULL
, needed
);
642 data_blob_clear(&blob
);
644 r
.in
.offered
= needed
;
646 status
= dcerpc_spoolss_EnumPrintProcDataTypes(p
, ctx
, &r
);
647 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
649 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrintProcDataTypes failed");
656 static bool test_EnumPrinters(struct torture_context
*tctx
,
657 struct dcerpc_pipe
*p
,
658 struct test_spoolss_context
*ctx
)
660 struct spoolss_EnumPrinters r
;
662 uint16_t levels
[] = { 0, 1, 2, 4, 5 };
665 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
666 int level
= levels
[i
];
670 union spoolss_PrinterInfo
*info
;
672 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
677 r
.out
.needed
= &needed
;
678 r
.out
.count
= &count
;
681 torture_comment(tctx
, "Testing EnumPrinters level %u\n", r
.in
.level
);
683 status
= dcerpc_spoolss_EnumPrinters(p
, ctx
, &r
);
684 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinters failed");
685 if (W_ERROR_IS_OK(r
.out
.result
)) {
686 /* TODO: do some more checks here */
689 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
690 "EnumPrinters unexpected return code");
692 blob
= data_blob_talloc(ctx
, NULL
, needed
);
693 data_blob_clear(&blob
);
695 r
.in
.offered
= needed
;
697 status
= dcerpc_spoolss_EnumPrinters(p
, ctx
, &r
);
698 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinters failed");
700 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
702 ctx
->printer_count
[level
] = count
;
703 ctx
->printers
[level
] = info
;
706 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
707 int level
= levels
[i
];
708 int old_level
= levels
[i
-1];
709 torture_assert_int_equal(tctx
, ctx
->printer_count
[level
], ctx
->printer_count
[old_level
],
710 "EnumPrinters invalid value");
713 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
714 int level
= levels
[i
];
715 for (j
=0;j
<ctx
->printer_count
[level
];j
++) {
716 union spoolss_PrinterInfo
*cur
= &ctx
->printers
[level
][j
];
717 union spoolss_PrinterInfo
*ref
= &ctx
->printers
[2][j
];
720 COMPARE_STRING(tctx
, cur
->info0
, ref
->info2
, printername
);
721 COMPARE_STRING(tctx
, cur
->info0
, ref
->info2
, servername
);
722 COMPARE_UINT32(tctx
, cur
->info0
, ref
->info2
, cjobs
);
723 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
724 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
725 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
726 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
727 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
728 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
729 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
730 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
731 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
732 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
733 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
734 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
735 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
736 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
737 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
738 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
739 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
740 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
741 COMPARE_UINT32(tctx
, cur
->info0
, ref
->info2
, status
);
742 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
743 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
744 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
745 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
746 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
747 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
748 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
751 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
752 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
753 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
754 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, comment
);
757 /* level 2 is our reference, and it makes no sense to compare it to itself */
760 COMPARE_STRING(tctx
, cur
->info4
, ref
->info2
, printername
);
761 COMPARE_STRING(tctx
, cur
->info4
, ref
->info2
, servername
);
762 COMPARE_UINT32(tctx
, cur
->info4
, ref
->info2
, attributes
);
765 COMPARE_STRING(tctx
, cur
->info5
, ref
->info2
, printername
);
766 COMPARE_STRING(tctx
, cur
->info5
, ref
->info2
, portname
);
767 COMPARE_UINT32(tctx
, cur
->info5
, ref
->info2
, attributes
);
768 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
769 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
776 * - verify that the port of a printer was in the list returned by EnumPorts
782 static bool test_GetPrinter(struct torture_context
*tctx
,
783 struct dcerpc_pipe
*p
,
784 struct policy_handle
*handle
)
787 struct spoolss_GetPrinter r
;
788 uint16_t levels
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
792 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
793 r
.in
.handle
= handle
;
794 r
.in
.level
= levels
[i
];
797 r
.out
.needed
= &needed
;
799 torture_comment(tctx
, "Testing GetPrinter level %u\n", r
.in
.level
);
801 status
= dcerpc_spoolss_GetPrinter(p
, tctx
, &r
);
802 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinter failed");
804 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
805 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
806 data_blob_clear(&blob
);
808 r
.in
.offered
= needed
;
809 status
= dcerpc_spoolss_GetPrinter(p
, tctx
, &r
);
812 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinter failed");
814 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrinter failed");
820 static bool test_SetPrinter_errors(struct torture_context
*tctx
,
821 struct dcerpc_pipe
*p
,
822 struct policy_handle
*handle
)
824 struct spoolss_SetPrinter r
;
825 uint16_t levels
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
828 struct spoolss_SetPrinterInfoCtr info_ctr
;
829 struct spoolss_DevmodeContainer devmode_ctr
;
830 struct sec_desc_buf secdesc_ctr
;
833 info_ctr
.info
.info0
= NULL
;
835 ZERO_STRUCT(devmode_ctr
);
836 ZERO_STRUCT(secdesc_ctr
);
838 r
.in
.handle
= handle
;
839 r
.in
.info_ctr
= &info_ctr
;
840 r
.in
.devmode_ctr
= &devmode_ctr
;
841 r
.in
.secdesc_ctr
= &secdesc_ctr
;
844 torture_comment(tctx
, "Testing SetPrinter all zero\n");
846 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter(p
, tctx
, &r
),
847 "failed to call SetPrinter");
848 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
849 "failed to call SetPrinter");
852 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
854 struct spoolss_SetPrinterInfo0 info0
;
855 struct spoolss_SetPrinterInfo1 info1
;
856 struct spoolss_SetPrinterInfo2 info2
;
857 struct spoolss_SetPrinterInfo3 info3
;
858 struct spoolss_SetPrinterInfo4 info4
;
859 struct spoolss_SetPrinterInfo5 info5
;
860 struct spoolss_SetPrinterInfo6 info6
;
861 struct spoolss_SetPrinterInfo7 info7
;
862 struct spoolss_DeviceModeInfo info8
;
863 struct spoolss_DeviceModeInfo info9
;
866 info_ctr
.level
= levels
[i
];
870 info_ctr
.info
.info0
= &info0
;
874 info_ctr
.info
.info1
= &info1
;
878 info_ctr
.info
.info2
= &info2
;
882 info_ctr
.info
.info3
= &info3
;
886 info_ctr
.info
.info4
= &info4
;
890 info_ctr
.info
.info5
= &info5
;
894 info_ctr
.info
.info6
= &info6
;
898 info_ctr
.info
.info7
= &info7
;
902 info_ctr
.info
.info8
= &info8
;
906 info_ctr
.info
.info9
= &info9
;
910 torture_comment(tctx
, "Testing SetPrinter level %d, command %d\n",
911 info_ctr
.level
, r
.in
.command
);
913 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter(p
, tctx
, &r
),
914 "failed to call SetPrinter");
916 switch (r
.in
.command
) {
917 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
: /* 0 */
918 /* is ignored for all levels other then 0 */
919 if (info_ctr
.level
> 0) {
923 case SPOOLSS_PRINTER_CONTROL_PAUSE
: /* 1 */
924 case SPOOLSS_PRINTER_CONTROL_RESUME
: /* 2 */
925 case SPOOLSS_PRINTER_CONTROL_PURGE
: /* 3 */
926 if (info_ctr
.level
> 0) {
927 /* is invalid for all levels other then 0 */
928 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PRINTER_COMMAND
,
929 "unexpected error code returned");
932 torture_assert_werr_ok(tctx
, r
.out
.result
,
933 "failed to call SetPrinter with non 0 command");
938 case SPOOLSS_PRINTER_CONTROL_SET_STATUS
: /* 4 */
939 /* FIXME: gd needs further investigation */
941 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PRINTER_COMMAND
,
942 "unexpected error code returned");
946 switch (info_ctr
.level
) {
948 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
,
949 "unexpected error code returned");
952 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_PRINTER_DRIVER
,
953 "unexpected error code returned");
959 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
960 "unexpected error code returned");
963 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_NOT_SUPPORTED
,
964 "unexpected error code returned");
967 torture_assert_werr_ok(tctx
, r
.out
.result
,
968 "failed to call SetPrinter");
973 if (r
.in
.command
< 5) {
981 static void clear_info2(struct spoolss_SetPrinterInfoCtr
*r
)
983 if ((r
->level
== 2) && (r
->info
.info2
)) {
984 r
->info
.info2
->secdesc
= NULL
;
985 r
->info
.info2
->devmode
= NULL
;
989 static bool test_PrinterInfo(struct torture_context
*tctx
,
990 struct dcerpc_pipe
*p
,
991 struct policy_handle
*handle
)
994 struct spoolss_SetPrinter s
;
995 struct spoolss_GetPrinter q
;
996 struct spoolss_GetPrinter q0
;
997 struct spoolss_SetPrinterInfoCtr info_ctr
;
998 union spoolss_PrinterInfo info
;
999 struct spoolss_DevmodeContainer devmode_ctr
;
1000 struct sec_desc_buf secdesc_ctr
;
1005 uint32_t status_list
[] = {
1006 /* these do not stick
1007 PRINTER_STATUS_PAUSED,
1008 PRINTER_STATUS_ERROR,
1009 PRINTER_STATUS_PENDING_DELETION, */
1010 PRINTER_STATUS_PAPER_JAM
,
1011 PRINTER_STATUS_PAPER_OUT
,
1012 PRINTER_STATUS_MANUAL_FEED
,
1013 PRINTER_STATUS_PAPER_PROBLEM
,
1014 PRINTER_STATUS_OFFLINE
,
1015 PRINTER_STATUS_IO_ACTIVE
,
1016 PRINTER_STATUS_BUSY
,
1017 PRINTER_STATUS_PRINTING
,
1018 PRINTER_STATUS_OUTPUT_BIN_FULL
,
1019 PRINTER_STATUS_NOT_AVAILABLE
,
1020 PRINTER_STATUS_WAITING
,
1021 PRINTER_STATUS_PROCESSING
,
1022 PRINTER_STATUS_INITIALIZING
,
1023 PRINTER_STATUS_WARMING_UP
,
1024 PRINTER_STATUS_TONER_LOW
,
1025 PRINTER_STATUS_NO_TONER
,
1026 PRINTER_STATUS_PAGE_PUNT
,
1027 PRINTER_STATUS_USER_INTERVENTION
,
1028 PRINTER_STATUS_OUT_OF_MEMORY
,
1029 PRINTER_STATUS_DOOR_OPEN
,
1030 PRINTER_STATUS_SERVER_UNKNOWN
,
1031 PRINTER_STATUS_POWER_SAVE
,
1032 /* these do not stick
1041 uint32_t default_attribute
= PRINTER_ATTRIBUTE_LOCAL
;
1042 uint32_t attribute_list
[] = {
1043 PRINTER_ATTRIBUTE_QUEUED
,
1044 /* fails with WERR_INVALID_DATATYPE:
1045 PRINTER_ATTRIBUTE_DIRECT, */
1047 PRINTER_ATTRIBUTE_DEFAULT, */
1048 PRINTER_ATTRIBUTE_SHARED
,
1050 PRINTER_ATTRIBUTE_NETWORK, */
1051 PRINTER_ATTRIBUTE_HIDDEN
,
1052 PRINTER_ATTRIBUTE_LOCAL
,
1053 PRINTER_ATTRIBUTE_ENABLE_DEVQ
,
1054 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
,
1055 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST
,
1056 PRINTER_ATTRIBUTE_WORK_OFFLINE
,
1058 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1059 /* fails with WERR_INVALID_DATATYPE:
1060 PRINTER_ATTRIBUTE_RAW_ONLY, */
1061 /* these do not stick
1062 PRINTER_ATTRIBUTE_PUBLISHED,
1063 PRINTER_ATTRIBUTE_FAX,
1064 PRINTER_ATTRIBUTE_TS,
1083 ZERO_STRUCT(devmode_ctr
);
1084 ZERO_STRUCT(secdesc_ctr
);
1086 s
.in
.handle
= handle
;
1088 s
.in
.info_ctr
= &info_ctr
;
1089 s
.in
.devmode_ctr
= &devmode_ctr
;
1090 s
.in
.secdesc_ctr
= &secdesc_ctr
;
1092 q
.in
.handle
= handle
;
1096 #define TESTGETCALL(call, r) \
1097 r.in.buffer = NULL; \
1099 r.out.needed = &needed; \
1100 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1101 if (!NT_STATUS_IS_OK(status)) { \
1102 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1103 r.in.level, nt_errstr(status), __location__); \
1107 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1108 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1109 data_blob_clear(&blob); \
1110 r.in.buffer = &blob; \
1111 r.in.offered = needed; \
1113 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1114 if (!NT_STATUS_IS_OK(status)) { \
1115 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1116 r.in.level, nt_errstr(status), __location__); \
1120 if (!W_ERROR_IS_OK(r.out.result)) { \
1121 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1122 r.in.level, win_errstr(r.out.result), __location__); \
1128 #define TESTSETCALL_EXP(call, r, err) \
1129 clear_info2(&info_ctr);\
1130 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1131 if (!NT_STATUS_IS_OK(status)) { \
1132 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1133 r.in.info_ctr->level, nt_errstr(status), __location__); \
1137 if (!W_ERROR_IS_OK(err)) { \
1138 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1139 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1140 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1145 if (!W_ERROR_IS_OK(r.out.result)) { \
1146 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1147 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1152 #define TESTSETCALL(call, r) \
1153 TESTSETCALL_EXP(call, r, WERR_OK)
1155 #define STRING_EQUAL(s1, s2, field) \
1156 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1157 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1158 #field, s2, __location__); \
1163 #define MEM_EQUAL(s1, s2, length, field) \
1164 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1165 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1166 #field, (const char *)s2, __location__); \
1171 #define INT_EQUAL(i1, i2, field) \
1173 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1174 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1179 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1180 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1181 q.in.level = lvl1; \
1182 TESTGETCALL(GetPrinter, q) \
1183 info_ctr.level = lvl1; \
1184 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1185 info_ctr.info.info ## lvl1->field1 = value;\
1186 TESTSETCALL_EXP(SetPrinter, s, err) \
1187 info_ctr.info.info ## lvl1->field1 = ""; \
1188 TESTGETCALL(GetPrinter, q) \
1189 info_ctr.info.info ## lvl1->field1 = value; \
1190 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1191 q.in.level = lvl2; \
1192 TESTGETCALL(GetPrinter, q) \
1193 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1194 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1197 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1198 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1201 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1202 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1203 q.in.level = lvl1; \
1204 TESTGETCALL(GetPrinter, q) \
1205 info_ctr.level = lvl1; \
1206 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1207 info_ctr.info.info ## lvl1->field1 = value; \
1208 TESTSETCALL(SetPrinter, s) \
1209 info_ctr.info.info ## lvl1->field1 = 0; \
1210 TESTGETCALL(GetPrinter, q) \
1211 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1212 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1213 q.in.level = lvl2; \
1214 TESTGETCALL(GetPrinter, q) \
1215 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1216 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1219 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1220 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1224 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1226 TEST_PRINTERINFO_STRING(2, comment
, 1, comment
, "xx2-1 comment");
1227 TEST_PRINTERINFO_STRING(2, comment
, 2, comment
, "xx2-2 comment");
1229 /* level 0 printername does not stick */
1230 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1231 TEST_PRINTERINFO_STRING(2, printername
, 1, name
, "xx2-1 printer");
1232 TEST_PRINTERINFO_STRING(2, printername
, 2, printername
, "xx2-2 printer");
1233 TEST_PRINTERINFO_STRING(2, printername
, 4, printername
, "xx2-4 printer");
1234 TEST_PRINTERINFO_STRING(2, printername
, 5, printername
, "xx2-5 printer");
1235 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1236 TEST_PRINTERINFO_STRING(4, printername
, 1, name
, "xx4-1 printer");
1237 TEST_PRINTERINFO_STRING(4, printername
, 2, printername
, "xx4-2 printer");
1238 TEST_PRINTERINFO_STRING(4, printername
, 4, printername
, "xx4-4 printer");
1239 TEST_PRINTERINFO_STRING(4, printername
, 5, printername
, "xx4-5 printer");
1240 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1241 TEST_PRINTERINFO_STRING(5, printername
, 1, name
, "xx5-1 printer");
1242 TEST_PRINTERINFO_STRING(5, printername
, 2, printername
, "xx5-2 printer");
1243 TEST_PRINTERINFO_STRING(5, printername
, 4, printername
, "xx5-4 printer");
1244 TEST_PRINTERINFO_STRING(5, printername
, 5, printername
, "xx5-5 printer");
1246 /* servername can be set but does not stick
1247 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1248 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1249 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1252 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1253 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname
, 2, portname
, "xx2-2 portname", WERR_UNKNOWN_PORT
);
1254 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname
, 5, portname
, "xx2-5 portname", WERR_UNKNOWN_PORT
);
1255 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname
, 2, portname
, "xx5-2 portname", WERR_UNKNOWN_PORT
);
1256 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname
, 5, portname
, "xx5-5 portname", WERR_UNKNOWN_PORT
);
1258 TEST_PRINTERINFO_STRING(2, sharename
, 2, sharename
, "xx2-2 sharename");
1259 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1260 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername
, 2, drivername
, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER
);
1261 TEST_PRINTERINFO_STRING(2, location
, 2, location
, "xx2-2 location");
1262 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1263 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile
, 2, sepfile
, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE
);
1264 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1265 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor
, 2, printprocessor
, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR
);
1266 TEST_PRINTERINFO_STRING(2, datatype
, 2, datatype
, "xx2-2 datatype");
1267 TEST_PRINTERINFO_STRING(2, parameters
, 2, parameters
, "xx2-2 parameters");
1269 for (i
=0; i
< ARRAY_SIZE(attribute_list
); i
++) {
1270 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1272 (attribute_list[i] | default_attribute)
1274 TEST_PRINTERINFO_INT_EXP(2, attributes
, 2, attributes
,
1276 (attribute_list
[i
] | default_attribute
)
1278 TEST_PRINTERINFO_INT_EXP(2, attributes
, 4, attributes
,
1280 (attribute_list
[i
] | default_attribute
)
1282 TEST_PRINTERINFO_INT_EXP(2, attributes
, 5, attributes
,
1284 (attribute_list
[i
] | default_attribute
)
1286 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1288 (attribute_list[i] | default_attribute)
1290 TEST_PRINTERINFO_INT_EXP(4, attributes
, 2, attributes
,
1292 (attribute_list
[i
] | default_attribute
)
1294 TEST_PRINTERINFO_INT_EXP(4, attributes
, 4, attributes
,
1296 (attribute_list
[i
] | default_attribute
)
1298 TEST_PRINTERINFO_INT_EXP(4, attributes
, 5, attributes
,
1300 (attribute_list
[i
] | default_attribute
)
1302 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1304 (attribute_list[i] | default_attribute)
1306 TEST_PRINTERINFO_INT_EXP(5, attributes
, 2, attributes
,
1308 (attribute_list
[i
] | default_attribute
)
1310 TEST_PRINTERINFO_INT_EXP(5, attributes
, 4, attributes
,
1312 (attribute_list
[i
] | default_attribute
)
1314 TEST_PRINTERINFO_INT_EXP(5, attributes
, 5, attributes
,
1316 (attribute_list
[i
] | default_attribute
)
1320 for (i
=0; i
< ARRAY_SIZE(status_list
); i
++) {
1321 /* level 2 sets do not stick
1322 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1323 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1324 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1325 TEST_PRINTERINFO_INT(6, status
, 0, status
, status_list
[i
]);
1326 TEST_PRINTERINFO_INT(6, status
, 2, status
, status_list
[i
]);
1327 TEST_PRINTERINFO_INT(6, status
, 6, status
, status_list
[i
]);
1330 /* priorities need to be between 0 and 99
1331 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1332 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 0);
1333 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 1);
1334 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 99);
1335 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1336 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 0);
1337 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 1);
1338 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 99);
1339 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1341 TEST_PRINTERINFO_INT(2, starttime
, 2, starttime
, __LINE__
);
1342 TEST_PRINTERINFO_INT(2, untiltime
, 2, untiltime
, __LINE__
);
1345 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1346 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1349 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1350 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1352 /* FIXME: gd also test devmode and secdesc behavior */
1355 /* verify composition of level 1 description field */
1356 const char *description
;
1360 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1362 description
= talloc_strdup(tctx
, q0
.out
.info
->info1
.description
);
1365 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1367 tmp
= talloc_asprintf(tctx
, "%s,%s,%s",
1368 q0
.out
.info
->info2
.printername
,
1369 q0
.out
.info
->info2
.drivername
,
1370 q0
.out
.info
->info2
.location
);
1372 do { STRING_EQUAL(description
, tmp
, "description")} while (0);
1379 static bool test_ClosePrinter(struct torture_context
*tctx
,
1380 struct dcerpc_pipe
*p
,
1381 struct policy_handle
*handle
)
1384 struct spoolss_ClosePrinter r
;
1386 r
.in
.handle
= handle
;
1387 r
.out
.handle
= handle
;
1389 torture_comment(tctx
, "Testing ClosePrinter\n");
1391 status
= dcerpc_spoolss_ClosePrinter(p
, tctx
, &r
);
1392 torture_assert_ntstatus_ok(tctx
, status
, "ClosePrinter failed");
1397 static bool test_GetForm(struct torture_context
*tctx
,
1398 struct dcerpc_pipe
*p
,
1399 struct policy_handle
*handle
,
1400 const char *form_name
,
1404 struct spoolss_GetForm r
;
1407 r
.in
.handle
= handle
;
1408 r
.in
.form_name
= form_name
;
1412 r
.out
.needed
= &needed
;
1414 torture_comment(tctx
, "Testing GetForm level %d\n", r
.in
.level
);
1416 status
= dcerpc_spoolss_GetForm(p
, tctx
, &r
);
1417 torture_assert_ntstatus_ok(tctx
, status
, "GetForm failed");
1419 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1420 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1421 data_blob_clear(&blob
);
1422 r
.in
.buffer
= &blob
;
1423 r
.in
.offered
= needed
;
1424 status
= dcerpc_spoolss_GetForm(p
, tctx
, &r
);
1425 torture_assert_ntstatus_ok(tctx
, status
, "GetForm failed");
1427 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetForm failed");
1429 torture_assert(tctx
, r
.out
.info
, "No form info returned");
1432 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetForm failed");
1437 static bool test_EnumForms(struct torture_context
*tctx
,
1438 struct dcerpc_pipe
*p
,
1439 struct policy_handle
*handle
, bool print_server
)
1442 struct spoolss_EnumForms r
;
1446 uint32_t levels
[] = { 1, 2 };
1449 for (i
=0; i
<ARRAY_SIZE(levels
); i
++) {
1451 union spoolss_FormInfo
*info
;
1453 r
.in
.handle
= handle
;
1454 r
.in
.level
= levels
[i
];
1457 r
.out
.needed
= &needed
;
1458 r
.out
.count
= &count
;
1461 torture_comment(tctx
, "Testing EnumForms level %d\n", levels
[i
]);
1463 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &r
);
1464 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
1466 if ((r
.in
.level
== 2) && (W_ERROR_EQUAL(r
.out
.result
, WERR_UNKNOWN_LEVEL
))) {
1470 if (print_server
&& W_ERROR_EQUAL(r
.out
.result
, WERR_BADFID
))
1471 torture_fail(tctx
, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1473 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1475 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1476 data_blob_clear(&blob
);
1477 r
.in
.buffer
= &blob
;
1478 r
.in
.offered
= needed
;
1480 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &r
);
1482 torture_assert(tctx
, info
, "No forms returned");
1484 for (j
= 0; j
< count
; j
++) {
1486 ret
&= test_GetForm(tctx
, p
, handle
, info
[j
].info1
.form_name
, levels
[i
]);
1490 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
1492 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumForms failed");
1498 static bool test_DeleteForm(struct torture_context
*tctx
,
1499 struct dcerpc_pipe
*p
,
1500 struct policy_handle
*handle
,
1501 const char *form_name
)
1504 struct spoolss_DeleteForm r
;
1506 r
.in
.handle
= handle
;
1507 r
.in
.form_name
= form_name
;
1509 status
= dcerpc_spoolss_DeleteForm(p
, tctx
, &r
);
1511 torture_assert_ntstatus_ok(tctx
, status
, "DeleteForm failed");
1513 torture_assert_werr_ok(tctx
, r
.out
.result
, "DeleteForm failed");
1518 static bool test_AddForm(struct torture_context
*tctx
,
1519 struct dcerpc_pipe
*p
,
1520 struct policy_handle
*handle
, bool print_server
)
1522 struct spoolss_AddForm r
;
1523 struct spoolss_AddFormInfo1 addform
;
1524 const char *form_name
= "testform3";
1528 r
.in
.handle
= handle
;
1530 r
.in
.info
.info1
= &addform
;
1531 addform
.flags
= SPOOLSS_FORM_USER
;
1532 addform
.form_name
= form_name
;
1533 addform
.size
.width
= 50;
1534 addform
.size
.height
= 25;
1535 addform
.area
.left
= 5;
1536 addform
.area
.top
= 10;
1537 addform
.area
.right
= 45;
1538 addform
.area
.bottom
= 15;
1540 status
= dcerpc_spoolss_AddForm(p
, tctx
, &r
);
1542 torture_assert_ntstatus_ok(tctx
, status
, "AddForm failed");
1544 torture_assert_werr_ok(tctx
, r
.out
.result
, "AddForm failed");
1546 if (!print_server
) ret
&= test_GetForm(tctx
, p
, handle
, form_name
, 1);
1549 struct spoolss_SetForm sf
;
1550 struct spoolss_AddFormInfo1 setform
;
1552 sf
.in
.handle
= handle
;
1553 sf
.in
.form_name
= form_name
;
1555 sf
.in
.info
.info1
= &setform
;
1556 setform
.flags
= addform
.flags
;
1557 setform
.form_name
= addform
.form_name
;
1558 setform
.size
= addform
.size
;
1559 setform
.area
= addform
.area
;
1561 setform
.size
.width
= 1234;
1563 status
= dcerpc_spoolss_SetForm(p
, tctx
, &sf
);
1565 torture_assert_ntstatus_ok(tctx
, status
, "SetForm failed");
1567 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetForm failed");
1570 if (!print_server
) ret
&= test_GetForm(tctx
, p
, handle
, form_name
, 1);
1573 struct spoolss_EnumForms e
;
1574 union spoolss_FormInfo
*info
;
1579 e
.in
.handle
= handle
;
1583 e
.out
.needed
= &needed
;
1584 e
.out
.count
= &count
;
1587 torture_comment(tctx
, "Testing EnumForms level 1\n");
1589 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &e
);
1590 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
1592 if (print_server
&& W_ERROR_EQUAL(e
.out
.result
, WERR_BADFID
))
1593 torture_fail(tctx
, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1595 if (W_ERROR_EQUAL(e
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1597 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1598 data_blob_clear(&blob
);
1599 e
.in
.buffer
= &blob
;
1600 e
.in
.offered
= needed
;
1602 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &e
);
1604 torture_assert(tctx
, info
, "No forms returned");
1606 for (j
= 0; j
< count
; j
++) {
1607 if (strequal(form_name
, info
[j
].info1
.form_name
)) {
1613 torture_assert(tctx
, found
, "Newly added form not found in enum call");
1616 if (!test_DeleteForm(tctx
, p
, handle
, form_name
)) {
1623 static bool test_EnumPorts_old(struct torture_context
*tctx
,
1624 struct dcerpc_pipe
*p
)
1627 struct spoolss_EnumPorts r
;
1630 union spoolss_PortInfo
*info
;
1632 r
.in
.servername
= talloc_asprintf(tctx
, "\\\\%s",
1633 dcerpc_server_name(p
));
1637 r
.out
.needed
= &needed
;
1638 r
.out
.count
= &count
;
1641 torture_comment(tctx
, "Testing EnumPorts\n");
1643 status
= dcerpc_spoolss_EnumPorts(p
, tctx
, &r
);
1645 torture_assert_ntstatus_ok(tctx
, status
, "EnumPorts failed");
1647 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1648 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1649 data_blob_clear(&blob
);
1650 r
.in
.buffer
= &blob
;
1651 r
.in
.offered
= needed
;
1653 status
= dcerpc_spoolss_EnumPorts(p
, tctx
, &r
);
1654 torture_assert_ntstatus_ok(tctx
, status
, "EnumPorts failed");
1656 torture_assert(tctx
, info
, "No ports returned");
1662 static bool test_AddPort(struct torture_context
*tctx
,
1663 struct dcerpc_pipe
*p
)
1666 struct spoolss_AddPort r
;
1668 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s",
1669 dcerpc_server_name(p
));
1671 r
.in
.monitor_name
= "foo";
1673 torture_comment(tctx
, "Testing AddPort\n");
1675 status
= dcerpc_spoolss_AddPort(p
, tctx
, &r
);
1677 torture_assert_ntstatus_ok(tctx
, status
, "AddPort failed");
1679 /* win2k3 returns WERR_NOT_SUPPORTED */
1683 if (!W_ERROR_IS_OK(r
.out
.result
)) {
1684 printf("AddPort failed - %s\n", win_errstr(r
.out
.result
));
1693 static bool test_GetJob(struct torture_context
*tctx
,
1694 struct dcerpc_pipe
*p
,
1695 struct policy_handle
*handle
, uint32_t job_id
)
1698 struct spoolss_GetJob r
;
1699 union spoolss_JobInfo info
;
1701 uint32_t levels
[] = {1, 2 /* 3, 4 */};
1704 r
.in
.handle
= handle
;
1705 r
.in
.job_id
= job_id
;
1709 r
.out
.needed
= &needed
;
1712 torture_comment(tctx
, "Testing GetJob level %d\n", r
.in
.level
);
1714 status
= dcerpc_spoolss_GetJob(p
, tctx
, &r
);
1715 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
, "Unexpected return code");
1717 for (i
= 0; i
< ARRAY_SIZE(levels
); i
++) {
1719 torture_comment(tctx
, "Testing GetJob level %d\n", r
.in
.level
);
1723 r
.in
.level
= levels
[i
];
1727 status
= dcerpc_spoolss_GetJob(p
, tctx
, &r
);
1728 torture_assert_ntstatus_ok(tctx
, status
, "GetJob failed");
1730 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1731 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1732 data_blob_clear(&blob
);
1733 r
.in
.buffer
= &blob
;
1734 r
.in
.offered
= needed
;
1736 status
= dcerpc_spoolss_GetJob(p
, tctx
, &r
);
1737 torture_assert_ntstatus_ok(tctx
, status
, "GetJob failed");
1740 torture_assert(tctx
, r
.out
.info
, "No job info returned");
1741 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetJob failed");
1747 static bool test_SetJob(struct torture_context
*tctx
,
1748 struct dcerpc_pipe
*p
,
1749 struct policy_handle
*handle
, uint32_t job_id
,
1750 enum spoolss_JobControl command
)
1753 struct spoolss_SetJob r
;
1755 r
.in
.handle
= handle
;
1756 r
.in
.job_id
= job_id
;
1758 r
.in
.command
= command
;
1761 case SPOOLSS_JOB_CONTROL_PAUSE
:
1762 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1764 case SPOOLSS_JOB_CONTROL_RESUME
:
1765 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1767 case SPOOLSS_JOB_CONTROL_CANCEL
:
1768 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1770 case SPOOLSS_JOB_CONTROL_RESTART
:
1771 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1773 case SPOOLSS_JOB_CONTROL_DELETE
:
1774 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1776 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER
:
1777 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1779 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED
:
1780 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1782 case SPOOLSS_JOB_CONTROL_RETAIN
:
1783 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1785 case SPOOLSS_JOB_CONTROL_RELEASE
:
1786 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1789 torture_comment(tctx
, "Testing SetJob\n");
1793 status
= dcerpc_spoolss_SetJob(p
, tctx
, &r
);
1794 torture_assert_ntstatus_ok(tctx
, status
, "SetJob failed");
1795 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetJob failed");
1800 static bool test_AddJob(struct torture_context
*tctx
,
1801 struct dcerpc_pipe
*p
,
1802 struct policy_handle
*handle
)
1805 struct spoolss_AddJob r
;
1809 r
.in
.handle
= handle
;
1811 r
.out
.needed
= &needed
;
1812 r
.in
.buffer
= r
.out
.buffer
= NULL
;
1814 torture_comment(tctx
, "Testing AddJob\n");
1816 status
= dcerpc_spoolss_AddJob(p
, tctx
, &r
);
1817 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
, "AddJob failed");
1821 status
= dcerpc_spoolss_AddJob(p
, tctx
, &r
);
1822 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
, "AddJob failed");
1828 static bool test_EnumJobs(struct torture_context
*tctx
,
1829 struct dcerpc_pipe
*p
,
1830 struct policy_handle
*handle
)
1833 struct spoolss_EnumJobs r
;
1836 union spoolss_JobInfo
*info
;
1838 r
.in
.handle
= handle
;
1840 r
.in
.numjobs
= 0xffffffff;
1844 r
.out
.needed
= &needed
;
1845 r
.out
.count
= &count
;
1848 torture_comment(tctx
, "Testing EnumJobs\n");
1850 status
= dcerpc_spoolss_EnumJobs(p
, tctx
, &r
);
1852 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
1854 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1856 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1857 data_blob_clear(&blob
);
1858 r
.in
.buffer
= &blob
;
1859 r
.in
.offered
= needed
;
1861 status
= dcerpc_spoolss_EnumJobs(p
, tctx
, &r
);
1863 torture_assert(tctx
, info
, "No jobs returned");
1865 for (j
= 0; j
< count
; j
++) {
1867 test_GetJob(tctx
, p
, handle
, info
[j
].info1
.job_id
);
1870 if (!torture_setting_bool(tctx
, "samba3", false)) {
1871 test_SetJob(tctx
, p
, handle
, info
[j
].info1
.job_id
, SPOOLSS_JOB_CONTROL_PAUSE
);
1872 test_SetJob(tctx
, p
, handle
, info
[j
].info1
.job_id
, SPOOLSS_JOB_CONTROL_RESUME
);
1877 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumJobs failed");
1883 static bool test_DoPrintTest(struct torture_context
*tctx
,
1884 struct dcerpc_pipe
*p
,
1885 struct policy_handle
*handle
)
1889 struct spoolss_StartDocPrinter s
;
1890 struct spoolss_DocumentInfo1 info1
;
1891 struct spoolss_StartPagePrinter sp
;
1892 struct spoolss_WritePrinter w
;
1893 struct spoolss_EndPagePrinter ep
;
1894 struct spoolss_EndDocPrinter e
;
1897 uint32_t num_written
;
1899 torture_comment(tctx
, "Testing StartDocPrinter\n");
1901 s
.in
.handle
= handle
;
1903 s
.in
.info
.info1
= &info1
;
1904 s
.out
.job_id
= &job_id
;
1905 info1
.document_name
= "TorturePrintJob";
1906 info1
.output_file
= NULL
;
1907 info1
.datatype
= "RAW";
1909 status
= dcerpc_spoolss_StartDocPrinter(p
, tctx
, &s
);
1910 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_StartDocPrinter failed");
1911 torture_assert_werr_ok(tctx
, s
.out
.result
, "StartDocPrinter failed");
1913 for (i
=1; i
< 4; i
++) {
1914 torture_comment(tctx
, "Testing StartPagePrinter: Page[%d]\n", i
);
1916 sp
.in
.handle
= handle
;
1918 status
= dcerpc_spoolss_StartPagePrinter(p
, tctx
, &sp
);
1919 torture_assert_ntstatus_ok(tctx
, status
,
1920 "dcerpc_spoolss_StartPagePrinter failed");
1921 torture_assert_werr_ok(tctx
, sp
.out
.result
, "StartPagePrinter failed");
1923 torture_comment(tctx
, "Testing WritePrinter: Page[%d]\n", i
);
1925 w
.in
.handle
= handle
;
1926 w
.in
.data
= data_blob_string_const(talloc_asprintf(tctx
,"TortureTestPage: %d\nData\n",i
));
1927 w
.out
.num_written
= &num_written
;
1929 status
= dcerpc_spoolss_WritePrinter(p
, tctx
, &w
);
1930 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_WritePrinter failed");
1931 torture_assert_werr_ok(tctx
, w
.out
.result
, "WritePrinter failed");
1933 torture_comment(tctx
, "Testing EndPagePrinter: Page[%d]\n", i
);
1935 ep
.in
.handle
= handle
;
1937 status
= dcerpc_spoolss_EndPagePrinter(p
, tctx
, &ep
);
1938 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndPagePrinter failed");
1939 torture_assert_werr_ok(tctx
, ep
.out
.result
, "EndPagePrinter failed");
1942 torture_comment(tctx
, "Testing EndDocPrinter\n");
1944 e
.in
.handle
= handle
;
1946 status
= dcerpc_spoolss_EndDocPrinter(p
, tctx
, &e
);
1947 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndDocPrinter failed");
1948 torture_assert_werr_ok(tctx
, e
.out
.result
, "EndDocPrinter failed");
1950 ret
&= test_AddJob(tctx
, p
, handle
);
1951 ret
&= test_EnumJobs(tctx
, p
, handle
);
1953 ret
&= test_SetJob(tctx
, p
, handle
, job_id
, SPOOLSS_JOB_CONTROL_DELETE
);
1958 static bool test_PausePrinter(struct torture_context
*tctx
,
1959 struct dcerpc_pipe
*p
,
1960 struct policy_handle
*handle
)
1963 struct spoolss_SetPrinter r
;
1964 struct spoolss_SetPrinterInfoCtr info_ctr
;
1965 struct spoolss_DevmodeContainer devmode_ctr
;
1966 struct sec_desc_buf secdesc_ctr
;
1969 info_ctr
.info
.info0
= NULL
;
1971 ZERO_STRUCT(devmode_ctr
);
1972 ZERO_STRUCT(secdesc_ctr
);
1974 r
.in
.handle
= handle
;
1975 r
.in
.info_ctr
= &info_ctr
;
1976 r
.in
.devmode_ctr
= &devmode_ctr
;
1977 r
.in
.secdesc_ctr
= &secdesc_ctr
;
1978 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
1980 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1982 status
= dcerpc_spoolss_SetPrinter(p
, tctx
, &r
);
1984 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
1986 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
1991 static bool test_ResumePrinter(struct torture_context
*tctx
,
1992 struct dcerpc_pipe
*p
,
1993 struct policy_handle
*handle
)
1996 struct spoolss_SetPrinter r
;
1997 struct spoolss_SetPrinterInfoCtr info_ctr
;
1998 struct spoolss_DevmodeContainer devmode_ctr
;
1999 struct sec_desc_buf secdesc_ctr
;
2002 info_ctr
.info
.info0
= NULL
;
2004 ZERO_STRUCT(devmode_ctr
);
2005 ZERO_STRUCT(secdesc_ctr
);
2007 r
.in
.handle
= handle
;
2008 r
.in
.info_ctr
= &info_ctr
;
2009 r
.in
.devmode_ctr
= &devmode_ctr
;
2010 r
.in
.secdesc_ctr
= &secdesc_ctr
;
2011 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
2013 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2015 status
= dcerpc_spoolss_SetPrinter(p
, tctx
, &r
);
2017 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
2019 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
2024 static bool test_GetPrinterData(struct torture_context
*tctx
,
2025 struct dcerpc_pipe
*p
,
2026 struct policy_handle
*handle
,
2027 const char *value_name
)
2030 struct spoolss_GetPrinterData r
;
2032 enum winreg_Type type
;
2033 union spoolss_PrinterData data
;
2035 r
.in
.handle
= handle
;
2036 r
.in
.value_name
= value_name
;
2038 r
.out
.needed
= &needed
;
2042 torture_comment(tctx
, "Testing GetPrinterData\n");
2044 status
= dcerpc_spoolss_GetPrinterData(p
, tctx
, &r
);
2045 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
2047 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
2048 r
.in
.offered
= needed
;
2050 status
= dcerpc_spoolss_GetPrinterData(p
, tctx
, &r
);
2051 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
2053 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrinterData failed");
2059 static bool test_GetPrinterDataEx(struct torture_context
*tctx
,
2060 struct dcerpc_pipe
*p
,
2061 struct policy_handle
*handle
,
2062 const char *key_name
,
2063 const char *value_name
)
2066 struct spoolss_GetPrinterDataEx r
;
2067 enum winreg_Type type
;
2070 r
.in
.handle
= handle
;
2071 r
.in
.key_name
= key_name
;
2072 r
.in
.value_name
= value_name
;
2075 r
.out
.needed
= &needed
;
2076 r
.out
.buffer
= NULL
;
2078 torture_comment(tctx
, "Testing GetPrinterDataEx\n");
2080 status
= dcerpc_spoolss_GetPrinterDataEx(p
, tctx
, &r
);
2081 if (!NT_STATUS_IS_OK(status
)) {
2082 if (NT_STATUS_EQUAL(status
,NT_STATUS_NET_WRITE_FAULT
) &&
2083 p
->last_fault_code
== DCERPC_FAULT_OP_RNG_ERROR
) {
2084 torture_skip(tctx
, "GetPrinterDataEx not supported by server\n");
2086 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
2089 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
2090 r
.in
.offered
= needed
;
2091 r
.out
.buffer
= talloc_array(tctx
, uint8_t, needed
);
2093 status
= dcerpc_spoolss_GetPrinterDataEx(p
, tctx
, &r
);
2094 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
2096 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrinterDataEx failed");
2102 static bool test_EnumPrinterData(struct torture_context
*tctx
, struct dcerpc_pipe
*p
,
2103 struct policy_handle
*handle
)
2106 struct spoolss_EnumPrinterData r
;
2109 r
.in
.handle
= handle
;
2110 r
.in
.enum_index
= 0;
2113 uint32_t value_size
= 0;
2114 uint32_t data_size
= 0;
2115 enum winreg_Type type
= 0;
2117 r
.in
.value_offered
= value_size
;
2118 r
.out
.value_needed
= &value_size
;
2119 r
.in
.data_offered
= data_size
;
2120 r
.out
.data_needed
= &data_size
;
2123 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, 0);
2125 torture_comment(tctx
, "Testing EnumPrinterData\n");
2127 status
= dcerpc_spoolss_EnumPrinterData(p
, tctx
, &r
);
2129 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterData failed");
2131 r
.in
.value_offered
= value_size
;
2132 r
.out
.value_name
= talloc_zero_array(tctx
, const char, value_size
);
2133 r
.in
.data_offered
= data_size
;
2134 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, data_size
);
2136 status
= dcerpc_spoolss_EnumPrinterData(p
, tctx
, &r
);
2138 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterData failed");
2140 test_GetPrinterData(tctx
, p
, handle
, r
.out
.value_name
);
2142 test_GetPrinterDataEx(tctx
,
2143 p
, handle
, "PrinterDriverData",
2148 } while (W_ERROR_IS_OK(r
.out
.result
));
2153 static bool test_EnumPrinterDataEx(struct torture_context
*tctx
,
2154 struct dcerpc_pipe
*p
,
2155 struct policy_handle
*handle
)
2158 struct spoolss_EnumPrinterDataEx r
;
2159 struct spoolss_PrinterEnumValues
*info
;
2163 r
.in
.handle
= handle
;
2164 r
.in
.key_name
= "PrinterDriverData";
2166 r
.out
.needed
= &needed
;
2167 r
.out
.count
= &count
;
2170 torture_comment(tctx
, "Testing EnumPrinterDataEx\n");
2172 status
= dcerpc_spoolss_EnumPrinterDataEx(p
, tctx
, &r
);
2173 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterDataEx failed");
2175 r
.in
.offered
= needed
;
2177 status
= dcerpc_spoolss_EnumPrinterDataEx(p
, tctx
, &r
);
2179 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterDataEx failed");
2185 static bool test_DeletePrinterData(struct torture_context
*tctx
,
2186 struct dcerpc_pipe
*p
,
2187 struct policy_handle
*handle
,
2188 const char *value_name
)
2191 struct spoolss_DeletePrinterData r
;
2193 r
.in
.handle
= handle
;
2194 r
.in
.value_name
= value_name
;
2196 torture_comment(tctx
, "Testing DeletePrinterData\n");
2198 status
= dcerpc_spoolss_DeletePrinterData(p
, tctx
, &r
);
2200 torture_assert_ntstatus_ok(tctx
, status
, "DeletePrinterData failed");
2205 static bool test_SetPrinterData(struct torture_context
*tctx
,
2206 struct dcerpc_pipe
*p
,
2207 struct policy_handle
*handle
)
2210 struct spoolss_SetPrinterData r
;
2211 const char *value_name
= "spottyfoot";
2213 r
.in
.handle
= handle
;
2214 r
.in
.value_name
= value_name
;
2216 r
.in
.data
.string
= "dog";
2218 torture_comment(tctx
, "Testing SetPrinterData\n");
2220 status
= dcerpc_spoolss_SetPrinterData(p
, tctx
, &r
);
2222 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinterData failed");
2224 if (!test_GetPrinterData(tctx
, p
, handle
, value_name
)) {
2228 if (!test_DeletePrinterData(tctx
, p
, handle
, value_name
)) {
2235 static bool test_SecondaryClosePrinter(struct torture_context
*tctx
,
2236 struct dcerpc_pipe
*p
,
2237 struct policy_handle
*handle
)
2240 struct dcerpc_binding
*b
;
2241 struct dcerpc_pipe
*p2
;
2242 struct spoolss_ClosePrinter cp
;
2244 /* only makes sense on SMB */
2245 if (p
->conn
->transport
.transport
!= NCACN_NP
) {
2249 torture_comment(tctx
, "testing close on secondary pipe\n");
2251 status
= dcerpc_parse_binding(tctx
, p
->conn
->binding_string
, &b
);
2252 torture_assert_ntstatus_ok(tctx
, status
, "Failed to parse dcerpc binding");
2254 status
= dcerpc_secondary_connection(p
, &p2
, b
);
2255 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create secondary connection");
2257 status
= dcerpc_bind_auth_none(p2
, &ndr_table_spoolss
);
2258 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create bind on secondary connection");
2260 cp
.in
.handle
= handle
;
2261 cp
.out
.handle
= handle
;
2263 status
= dcerpc_spoolss_ClosePrinter(p2
, tctx
, &cp
);
2264 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_NET_WRITE_FAULT
,
2265 "ERROR: Allowed close on secondary connection");
2267 torture_assert_int_equal(tctx
, p2
->last_fault_code
, DCERPC_FAULT_CONTEXT_MISMATCH
,
2268 "Unexpected fault code");
2275 static bool test_OpenPrinter_badname(struct torture_context
*tctx
,
2276 struct dcerpc_pipe
*p
, const char *name
)
2279 struct spoolss_OpenPrinter op
;
2280 struct spoolss_OpenPrinterEx opEx
;
2281 struct policy_handle handle
;
2284 op
.in
.printername
= name
;
2285 op
.in
.datatype
= NULL
;
2286 op
.in
.devmode_ctr
.devmode
= NULL
;
2287 op
.in
.access_mask
= 0;
2288 op
.out
.handle
= &handle
;
2290 torture_comment(tctx
, "\nTesting OpenPrinter(%s) with bad name\n", op
.in
.printername
);
2292 status
= dcerpc_spoolss_OpenPrinter(p
, tctx
, &op
);
2293 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
2294 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME
,op
.out
.result
)) {
2295 torture_comment(tctx
, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
2296 name
, win_errstr(op
.out
.result
));
2299 if (W_ERROR_IS_OK(op
.out
.result
)) {
2300 ret
&=test_ClosePrinter(tctx
, p
, &handle
);
2303 opEx
.in
.printername
= name
;
2304 opEx
.in
.datatype
= NULL
;
2305 opEx
.in
.devmode_ctr
.devmode
= NULL
;
2306 opEx
.in
.access_mask
= 0;
2308 opEx
.in
.userlevel
.level1
= NULL
;
2309 opEx
.out
.handle
= &handle
;
2311 torture_comment(tctx
, "Testing OpenPrinterEx(%s) with bad name\n", opEx
.in
.printername
);
2313 status
= dcerpc_spoolss_OpenPrinterEx(p
, tctx
, &opEx
);
2314 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinterEx failed");
2315 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM
,opEx
.out
.result
)) {
2316 torture_comment(tctx
, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
2317 name
, win_errstr(opEx
.out
.result
));
2320 if (W_ERROR_IS_OK(opEx
.out
.result
)) {
2321 ret
&=test_ClosePrinter(tctx
, p
, &handle
);
2327 static bool test_OpenPrinter(struct torture_context
*tctx
,
2328 struct dcerpc_pipe
*p
,
2332 struct spoolss_OpenPrinter r
;
2333 struct policy_handle handle
;
2336 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s\\%s", dcerpc_server_name(p
), name
);
2337 r
.in
.datatype
= NULL
;
2338 r
.in
.devmode_ctr
.devmode
= NULL
;
2339 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
2340 r
.out
.handle
= &handle
;
2342 torture_comment(tctx
, "Testing OpenPrinter(%s)\n", r
.in
.printername
);
2344 status
= dcerpc_spoolss_OpenPrinter(p
, tctx
, &r
);
2346 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
2348 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenPrinter failed");
2350 if (!test_GetPrinter(tctx
, p
, &handle
)) {
2354 if (!torture_setting_bool(tctx
, "samba3", false)) {
2355 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
2360 if (!test_ClosePrinter(tctx
, p
, &handle
)) {
2367 static bool call_OpenPrinterEx(struct torture_context
*tctx
,
2368 struct dcerpc_pipe
*p
,
2369 const char *name
, struct policy_handle
*handle
)
2371 struct spoolss_OpenPrinterEx r
;
2372 struct spoolss_UserLevel1 userlevel1
;
2375 if (name
&& name
[0]) {
2376 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s\\%s",
2377 dcerpc_server_name(p
), name
);
2379 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s",
2380 dcerpc_server_name(p
));
2383 r
.in
.datatype
= NULL
;
2384 r
.in
.devmode_ctr
.devmode
= NULL
;
2385 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
2387 r
.in
.userlevel
.level1
= &userlevel1
;
2388 r
.out
.handle
= handle
;
2390 userlevel1
.size
= 1234;
2391 userlevel1
.client
= "hello";
2392 userlevel1
.user
= "spottyfoot!";
2393 userlevel1
.build
= 1;
2394 userlevel1
.major
= 2;
2395 userlevel1
.minor
= 3;
2396 userlevel1
.processor
= 4;
2398 torture_comment(tctx
, "Testing OpenPrinterEx(%s)\n", r
.in
.printername
);
2400 status
= dcerpc_spoolss_OpenPrinterEx(p
, tctx
, &r
);
2402 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinterEx failed");
2404 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenPrinterEx failed");
2409 static bool test_OpenPrinterEx(struct torture_context
*tctx
,
2410 struct dcerpc_pipe
*p
,
2413 struct policy_handle handle
;
2416 if (!call_OpenPrinterEx(tctx
, p
, name
, &handle
)) {
2420 if (!test_GetPrinter(tctx
, p
, &handle
)) {
2424 if (!test_EnumForms(tctx
, p
, &handle
, false)) {
2428 if (!test_AddForm(tctx
, p
, &handle
, false)) {
2432 if (!test_EnumPrinterData(tctx
, p
, &handle
)) {
2436 if (!test_EnumPrinterDataEx(tctx
, p
, &handle
)) {
2440 if (!test_PausePrinter(tctx
, p
, &handle
)) {
2444 if (!test_DoPrintTest(tctx
, p
, &handle
)) {
2448 if (!test_ResumePrinter(tctx
, p
, &handle
)) {
2452 if (!test_SetPrinterData(tctx
, p
, &handle
)) {
2456 if (!torture_setting_bool(tctx
, "samba3", false)) {
2457 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
2462 if (!test_ClosePrinter(tctx
, p
, &handle
)) {
2469 static bool test_EnumPrinters_old(struct torture_context
*tctx
, struct dcerpc_pipe
*p
)
2471 struct spoolss_EnumPrinters r
;
2473 uint16_t levels
[] = {1, 2, 4, 5};
2477 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
2478 union spoolss_PrinterInfo
*info
;
2483 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
2485 r
.in
.level
= levels
[i
];
2488 r
.out
.needed
= &needed
;
2489 r
.out
.count
= &count
;
2492 torture_comment(tctx
, "Testing EnumPrinters level %u\n", r
.in
.level
);
2494 status
= dcerpc_spoolss_EnumPrinters(p
, tctx
, &r
);
2495 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
2497 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2498 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2499 data_blob_clear(&blob
);
2500 r
.in
.buffer
= &blob
;
2501 r
.in
.offered
= needed
;
2502 status
= dcerpc_spoolss_EnumPrinters(p
, tctx
, &r
);
2505 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
2507 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
2510 torture_comment(tctx
, "No printers returned\n");
2514 for (j
=0;j
<count
;j
++) {
2515 if (r
.in
.level
== 1) {
2516 char *unc
= talloc_strdup(tctx
, info
[j
].info1
.name
);
2519 if (unc
[0] == '\\' && unc
[1] == '\\') {
2522 slash
= strchr(unc
, '\\');
2527 if (!test_OpenPrinter(tctx
, p
, name
)) {
2530 if (!test_OpenPrinterEx(tctx
, p
, name
)) {
2540 static bool test_GetPrinterDriver(struct torture_context
*tctx
,
2541 struct dcerpc_pipe
*p
,
2542 struct policy_handle
*handle
,
2543 const char *driver_name
)
2545 struct spoolss_GetPrinterDriver r
;
2548 r
.in
.handle
= handle
;
2549 r
.in
.architecture
= "W32X86";
2553 r
.out
.needed
= &needed
;
2555 torture_comment(tctx
, "Testing GetPrinterDriver level %d\n", r
.in
.level
);
2557 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver(p
, tctx
, &r
),
2558 "failed to call GetPrinterDriver");
2559 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2560 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2561 data_blob_clear(&blob
);
2562 r
.in
.buffer
= &blob
;
2563 r
.in
.offered
= needed
;
2564 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver(p
, tctx
, &r
),
2565 "failed to call GetPrinterDriver");
2568 torture_assert_werr_ok(tctx
, r
.out
.result
,
2569 "failed to call GetPrinterDriver");
2574 static bool test_GetPrinterDriver2(struct torture_context
*tctx
,
2575 struct dcerpc_pipe
*p
,
2576 struct policy_handle
*handle
,
2577 const char *driver_name
)
2579 struct spoolss_GetPrinterDriver2 r
;
2581 uint32_t server_major_version
;
2582 uint32_t server_minor_version
;
2584 r
.in
.handle
= handle
;
2585 r
.in
.architecture
= "W32X86";
2589 r
.in
.client_major_version
= 0;
2590 r
.in
.client_minor_version
= 0;
2591 r
.out
.needed
= &needed
;
2592 r
.out
.server_major_version
= &server_major_version
;
2593 r
.out
.server_minor_version
= &server_minor_version
;
2595 torture_comment(tctx
, "Testing GetPrinterDriver2 level %d\n", r
.in
.level
);
2597 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver2(p
, tctx
, &r
),
2598 "failed to call GetPrinterDriver2");
2599 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2600 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2601 data_blob_clear(&blob
);
2602 r
.in
.buffer
= &blob
;
2603 r
.in
.offered
= needed
;
2604 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver2(p
, tctx
, &r
),
2605 "failed to call GetPrinterDriver2");
2608 torture_assert_werr_ok(tctx
, r
.out
.result
,
2609 "failed to call GetPrinterDriver2");
2614 static bool test_EnumPrinterDrivers_old(struct torture_context
*tctx
,
2615 struct dcerpc_pipe
*p
)
2617 struct spoolss_EnumPrinterDrivers r
;
2619 uint16_t levels
[] = {1, 2, 3, 4, 5, 6};
2622 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
2626 union spoolss_DriverInfo
*info
;
2628 r
.in
.server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
2629 r
.in
.environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
2630 r
.in
.level
= levels
[i
];
2633 r
.out
.needed
= &needed
;
2634 r
.out
.count
= &count
;
2637 torture_comment(tctx
, "Testing EnumPrinterDrivers level %u\n", r
.in
.level
);
2639 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, tctx
, &r
);
2641 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterDrivers failed");
2643 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2644 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2645 data_blob_clear(&blob
);
2646 r
.in
.buffer
= &blob
;
2647 r
.in
.offered
= needed
;
2648 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, tctx
, &r
);
2651 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterDrivers failed");
2653 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDrivers failed");
2656 torture_comment(tctx
, "No printer drivers returned\n");
2664 static bool test_DeletePrinter(struct torture_context
*tctx
,
2665 struct dcerpc_pipe
*p
,
2666 struct policy_handle
*handle
)
2668 struct spoolss_DeletePrinter r
;
2670 torture_comment(tctx
, "Testing DeletePrinter\n");
2672 r
.in
.handle
= handle
;
2674 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_DeletePrinter(p
, tctx
, &r
),
2675 "failed to delete printer");
2676 torture_assert_werr_ok(tctx
, r
.out
.result
,
2677 "failed to delete printer");
2682 static bool test_EnumPrinters_findname(struct torture_context
*tctx
,
2683 struct dcerpc_pipe
*p
,
2689 struct spoolss_EnumPrinters e
;
2691 union spoolss_PrinterInfo
*info
;
2702 e
.out
.count
= &count
;
2704 e
.out
.needed
= &needed
;
2706 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters(p
, tctx
, &e
),
2707 "failed to enum printers");
2709 if (W_ERROR_EQUAL(e
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2710 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2711 data_blob_clear(&blob
);
2712 e
.in
.buffer
= &blob
;
2713 e
.in
.offered
= needed
;
2715 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters(p
, tctx
, &e
),
2716 "failed to enum printers");
2719 torture_assert_werr_ok(tctx
, e
.out
.result
,
2720 "failed to enum printers");
2722 for (i
=0; i
< count
; i
++) {
2724 const char *current
= NULL
;
2728 current
= info
[i
].info1
.name
;
2732 if (strequal(current
, name
)) {
2741 static bool test_AddPrinter_wellknown(struct torture_context
*tctx
,
2742 struct dcerpc_pipe
*p
,
2743 const char *printername
,
2747 struct spoolss_AddPrinter r
;
2748 struct spoolss_AddPrinterEx rex
;
2749 struct spoolss_SetPrinterInfoCtr info_ctr
;
2750 struct spoolss_SetPrinterInfo1 info1
;
2751 struct spoolss_DevmodeContainer devmode_ctr
;
2752 struct sec_desc_buf secdesc_ctr
;
2753 struct spoolss_UserLevelCtr userlevel_ctr
;
2754 struct policy_handle handle
;
2757 ZERO_STRUCT(devmode_ctr
);
2758 ZERO_STRUCT(secdesc_ctr
);
2759 ZERO_STRUCT(userlevel_ctr
);
2762 torture_comment(tctx
, "Testing AddPrinter%s level 1\n", ex
? "Ex":"");
2764 /* try to add printer to wellknown printer list (level 1) */
2766 userlevel_ctr
.level
= 1;
2768 info_ctr
.info
.info1
= &info1
;
2771 rex
.in
.server
= NULL
;
2772 rex
.in
.info_ctr
= &info_ctr
;
2773 rex
.in
.devmode_ctr
= &devmode_ctr
;
2774 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
2775 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
2776 rex
.out
.handle
= &handle
;
2779 r
.in
.info_ctr
= &info_ctr
;
2780 r
.in
.devmode_ctr
= &devmode_ctr
;
2781 r
.in
.secdesc_ctr
= &secdesc_ctr
;
2782 r
.out
.handle
= &handle
;
2784 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
2785 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
2786 "failed to add printer");
2787 result
= ex
? rex
.out
.result
: r
.out
.result
;
2788 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
2789 "unexpected result code");
2791 info1
.name
= printername
;
2792 info1
.flags
= PRINTER_ATTRIBUTE_SHARED
;
2794 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
2795 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
2796 "failed to add printer");
2797 result
= ex
? rex
.out
.result
: r
.out
.result
;
2798 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
2799 "unexpected result code");
2801 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
2802 better do a real check to see the printer is really there */
2804 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, p
,
2805 PRINTER_ENUM_NETWORK
, 1,
2808 "failed to enum printers");
2810 torture_assert(tctx
, found
, "failed to find newly added printer");
2814 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
2815 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
2816 "failed to add printer");
2817 result
= ex
? rex
.out
.result
: r
.out
.result
;
2818 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
2819 "unexpected result code");
2821 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
2822 better do a real check to see the printer has really been removed
2823 from the well known printer list */
2827 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, p
,
2828 PRINTER_ENUM_NETWORK
, 1,
2831 "failed to enum printers");
2833 torture_assert(tctx
, !found
, "printer still in well known printer list");
2838 static bool test_AddPrinter_normal(struct torture_context
*tctx
,
2839 struct dcerpc_pipe
*p
,
2840 struct policy_handle
*handle_p
,
2841 const char *printername
,
2842 const char *drivername
,
2843 const char *portname
,
2847 struct spoolss_AddPrinter r
;
2848 struct spoolss_AddPrinterEx rex
;
2849 struct spoolss_SetPrinterInfoCtr info_ctr
;
2850 struct spoolss_SetPrinterInfo2 info2
;
2851 struct spoolss_DevmodeContainer devmode_ctr
;
2852 struct sec_desc_buf secdesc_ctr
;
2853 struct spoolss_UserLevelCtr userlevel_ctr
;
2854 struct policy_handle handle
;
2857 ZERO_STRUCT(devmode_ctr
);
2858 ZERO_STRUCT(secdesc_ctr
);
2859 ZERO_STRUCT(userlevel_ctr
);
2861 torture_comment(tctx
, "Testing AddPrinter%s level 2\n", ex
? "Ex":"");
2863 userlevel_ctr
.level
= 1;
2865 rex
.in
.server
= NULL
;
2866 rex
.in
.info_ctr
= &info_ctr
;
2867 rex
.in
.devmode_ctr
= &devmode_ctr
;
2868 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
2869 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
2870 rex
.out
.handle
= &handle
;
2873 r
.in
.info_ctr
= &info_ctr
;
2874 r
.in
.devmode_ctr
= &devmode_ctr
;
2875 r
.in
.secdesc_ctr
= &secdesc_ctr
;
2876 r
.out
.handle
= &handle
;
2880 /* try to add printer to printer list (level 2) */
2884 info_ctr
.info
.info2
= &info2
;
2887 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
2888 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
2889 "failed to add printer");
2890 result
= ex
? rex
.out
.result
: r
.out
.result
;
2891 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
2892 "unexpected result code");
2894 info2
.printername
= printername
;
2896 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
2897 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
2898 "failed to add printer");
2899 result
= ex
? rex
.out
.result
: r
.out
.result
;
2901 if (W_ERROR_EQUAL(result
, WERR_PRINTER_ALREADY_EXISTS
)) {
2902 struct policy_handle printer_handle
;
2904 torture_assert(tctx
, call_OpenPrinterEx(tctx
, p
, printername
, &printer_handle
),
2905 "failed to open printer handle");
2907 torture_assert(tctx
, test_DeletePrinter(tctx
, p
, &printer_handle
),
2908 "failed to delete printer");
2910 torture_assert(tctx
, test_ClosePrinter(tctx
, p
, &printer_handle
),
2911 "failed to close server handle");
2916 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PORT
,
2917 "unexpected result code");
2919 info2
.portname
= portname
;
2921 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
2922 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
2923 "failed to add printer");
2924 result
= ex
? rex
.out
.result
: r
.out
.result
;
2925 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTER_DRIVER
,
2926 "unexpected result code");
2928 info2
.drivername
= drivername
;
2930 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
2931 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
2932 "failed to add printer");
2933 result
= ex
? rex
.out
.result
: r
.out
.result
;
2934 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTPROCESSOR
,
2935 "unexpected result code");
2937 info2
.printprocessor
= "winprint";
2939 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
2940 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
2941 "failed to add printer");
2942 result
= ex
? rex
.out
.result
: r
.out
.result
;
2943 torture_assert_werr_ok(tctx
, result
,
2944 "failed to add printer");
2948 /* we are paranoid, really check if the printer is there now */
2950 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, p
,
2951 PRINTER_ENUM_LOCAL
, 1,
2954 "failed to enum printers");
2955 torture_assert(tctx
, found
, "failed to find newly added printer");
2957 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
2958 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
2959 "failed to add printer");
2960 result
= ex
? rex
.out
.result
: r
.out
.result
;
2961 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
2962 "unexpected result code");
2967 static bool test_AddPrinterEx(struct torture_context
*tctx
,
2968 struct dcerpc_pipe
*p
,
2969 struct policy_handle
*handle_p
,
2970 const char *printername
,
2971 const char *drivername
,
2972 const char *portname
)
2976 if (!torture_setting_bool(tctx
, "samba3", false)) {
2977 if (!test_AddPrinter_wellknown(tctx
, p
, TORTURE_WELLKNOWN_PRINTER_EX
, true)) {
2978 torture_comment(tctx
, "failed to add printer to well known list\n");
2983 if (!test_AddPrinter_normal(tctx
, p
, handle_p
,
2984 printername
, drivername
, portname
,
2986 torture_comment(tctx
, "failed to add printer to printer list\n");
2993 static bool test_AddPrinter(struct torture_context
*tctx
,
2994 struct dcerpc_pipe
*p
,
2995 struct policy_handle
*handle_p
,
2996 const char *printername
,
2997 const char *drivername
,
2998 const char *portname
)
3002 if (!torture_setting_bool(tctx
, "samba3", false)) {
3003 if (!test_AddPrinter_wellknown(tctx
, p
, TORTURE_WELLKNOWN_PRINTER
, false)) {
3004 torture_comment(tctx
, "failed to add printer to well known list\n");
3009 if (!test_AddPrinter_normal(tctx
, p
, handle_p
,
3010 printername
, drivername
, portname
,
3012 torture_comment(tctx
, "failed to add printer to printer list\n");
3019 static bool test_printer_info(struct torture_context
*tctx
,
3020 struct dcerpc_pipe
*p
,
3021 struct policy_handle
*handle
)
3025 if (!test_PrinterInfo(tctx
, p
, handle
)) {
3029 if (!test_SetPrinter_errors(tctx
, p
, handle
)) {
3036 static bool test_printer(struct torture_context
*tctx
,
3037 struct dcerpc_pipe
*p
)
3040 struct policy_handle handle
[2];
3042 const char *drivername
= "Microsoft XPS Document Writer";
3043 const char *portname
= "LPT1:";
3045 /* test printer created via AddPrinter */
3047 if (!test_AddPrinter(tctx
, p
, &handle
[0], TORTURE_PRINTER
, drivername
, portname
)) {
3051 if (!test_printer_info(tctx
, p
, &handle
[0])) {
3055 if (!test_DeletePrinter(tctx
, p
, &handle
[0])) {
3059 if (!test_EnumPrinters_findname(tctx
, p
, PRINTER_ENUM_LOCAL
, 1,
3060 TORTURE_PRINTER
, &found
)) {
3064 torture_assert(tctx
, !found
, "deleted printer still there");
3066 /* test printer created via AddPrinterEx */
3068 if (!test_AddPrinterEx(tctx
, p
, &handle
[1], TORTURE_PRINTER_EX
, drivername
, portname
)) {
3072 if (!test_printer_info(tctx
, p
, &handle
[1])) {
3076 if (!test_DeletePrinter(tctx
, p
, &handle
[1])) {
3080 if (!test_EnumPrinters_findname(tctx
, p
, PRINTER_ENUM_LOCAL
, 1,
3081 TORTURE_PRINTER_EX
, &found
)) {
3085 torture_assert(tctx
, !found
, "deleted printer still there");
3090 bool torture_rpc_spoolss(struct torture_context
*torture
)
3093 struct dcerpc_pipe
*p
;
3095 struct test_spoolss_context
*ctx
;
3097 status
= torture_rpc_connection(torture
, &p
, &ndr_table_spoolss
);
3098 if (!NT_STATUS_IS_OK(status
)) {
3102 ctx
= talloc_zero(torture
, struct test_spoolss_context
);
3104 ret
&= test_OpenPrinter_server(torture
, p
, &ctx
->server_handle
);
3106 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "W3SvcInstalled");
3107 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "BeepEnabled");
3108 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "EventLog");
3109 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "NetPopup");
3110 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "NetPopupToComputer");
3111 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "MajorVersion");
3112 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "MinorVersion");
3113 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "DefaultSpoolDirectory");
3114 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "Architecture");
3115 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "DsPresent");
3116 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "OSVersion");
3117 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "OSVersionEx");
3118 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "DNSMachineName");
3119 ret
&= test_EnumForms(torture
, p
, &ctx
->server_handle
, true);
3120 ret
&= test_AddForm(torture
, p
, &ctx
->server_handle
, true);
3121 ret
&= test_EnumPorts(torture
, p
, ctx
);
3122 ret
&= test_GetPrinterDriverDirectory(torture
, p
, ctx
);
3123 ret
&= test_GetPrintProcessorDirectory(torture
, p
, ctx
);
3124 ret
&= test_EnumPrinterDrivers(torture
, p
, ctx
);
3125 ret
&= test_EnumMonitors(torture
, p
, ctx
);
3126 ret
&= test_EnumPrintProcessors(torture
, p
, ctx
);
3127 ret
&= test_EnumPrintProcDataTypes(torture
, p
, ctx
);
3128 ret
&= test_EnumPrinters(torture
, p
, ctx
);
3129 ret
&= test_OpenPrinter_badname(torture
, p
, "__INVALID_PRINTER__");
3130 ret
&= test_OpenPrinter_badname(torture
, p
, "\\\\__INVALID_HOST__");
3131 ret
&= test_OpenPrinter_badname(torture
, p
, "");
3132 ret
&= test_OpenPrinter_badname(torture
, p
, "\\\\\\");
3133 ret
&= test_OpenPrinter_badname(torture
, p
, "\\\\\\__INVALID_PRINTER__");
3134 ret
&= test_OpenPrinter_badname(torture
, p
, talloc_asprintf(torture
, "\\\\%s\\", dcerpc_server_name(p
)));
3135 ret
&= test_OpenPrinter_badname(torture
, p
,
3136 talloc_asprintf(torture
, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p
)));
3139 ret
&= test_AddPort(torture
, p
);
3140 ret
&= test_EnumPorts_old(torture
, p
);
3141 ret
&= test_EnumPrinters_old(torture
, p
);
3142 ret
&= test_EnumPrinterDrivers_old(torture
, p
);
3147 struct torture_suite
*torture_rpc_spoolss_printer(TALLOC_CTX
*mem_ctx
)
3149 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "SPOOLSS-PRINTER");
3151 struct torture_rpc_tcase
*tcase
= torture_suite_add_rpc_iface_tcase(suite
,
3152 "printer", &ndr_table_spoolss
);
3154 torture_rpc_tcase_add_test(tcase
, "printer", test_printer
);