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_c.h"
29 #include "param/param.h"
31 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
32 #define TORTURE_PRINTER "torture_printer"
33 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
34 #define TORTURE_PRINTER_EX "torture_printer_ex"
36 struct test_spoolss_context
{
37 /* print server handle */
38 struct policy_handle server_handle
;
41 uint32_t port_count
[3];
42 union spoolss_PortInfo
*ports
[3];
44 /* for EnumPrinterDrivers */
45 uint32_t driver_count
[7];
46 union spoolss_DriverInfo
*drivers
[7];
48 /* for EnumMonitors */
49 uint32_t monitor_count
[3];
50 union spoolss_MonitorInfo
*monitors
[3];
52 /* for EnumPrintProcessors */
53 uint32_t print_processor_count
[2];
54 union spoolss_PrintProcessorInfo
*print_processors
[2];
56 /* for EnumPrinters */
57 uint32_t printer_count
[6];
58 union spoolss_PrinterInfo
*printers
[6];
61 #define COMPARE_STRING(tctx, c,r,e) \
62 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
64 /* not every compiler supports __typeof__() */
66 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
67 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
68 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
70 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
71 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
75 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
78 #define COMPARE_UINT32(tctx, c, r, e) do {\
79 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
80 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
83 #define COMPARE_STRING_ARRAY(tctx, c,r,e)
85 static bool test_OpenPrinter_server(struct torture_context
*tctx
,
86 struct dcerpc_pipe
*p
,
87 struct policy_handle
*server_handle
)
90 struct spoolss_OpenPrinter op
;
92 op
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
93 op
.in
.datatype
= NULL
;
94 op
.in
.devmode_ctr
.devmode
= NULL
;
95 op
.in
.access_mask
= 0;
96 op
.out
.handle
= server_handle
;
98 torture_comment(tctx
, "Testing OpenPrinter(%s)\n", op
.in
.printername
);
100 status
= dcerpc_spoolss_OpenPrinter(p
, tctx
, &op
);
101 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_OpenPrinter failed");
102 torture_assert_werr_ok(tctx
, op
.out
.result
, "dcerpc_spoolss_OpenPrinter failed");
107 static bool test_EnumPorts(struct torture_context
*tctx
,
108 struct dcerpc_pipe
*p
,
109 struct test_spoolss_context
*ctx
)
112 struct spoolss_EnumPorts r
;
113 uint16_t levels
[] = { 1, 2 };
116 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
117 int level
= levels
[i
];
121 union spoolss_PortInfo
*info
;
123 r
.in
.servername
= "";
127 r
.out
.needed
= &needed
;
128 r
.out
.count
= &count
;
131 torture_comment(tctx
, "Testing EnumPorts level %u\n", r
.in
.level
);
133 status
= dcerpc_spoolss_EnumPorts(p
, ctx
, &r
);
134 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPorts failed");
135 if (W_ERROR_IS_OK(r
.out
.result
)) {
136 /* TODO: do some more checks here */
139 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
140 "EnumPorts unexpected return code");
142 blob
= data_blob_talloc(ctx
, NULL
, needed
);
143 data_blob_clear(&blob
);
145 r
.in
.offered
= needed
;
147 status
= dcerpc_spoolss_EnumPorts(p
, ctx
, &r
);
148 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPorts failed");
150 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
152 torture_assert(tctx
, info
, "EnumPorts returned no info");
154 ctx
->port_count
[level
] = count
;
155 ctx
->ports
[level
] = info
;
158 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
159 int level
= levels
[i
];
160 int old_level
= levels
[i
-1];
161 torture_assert_int_equal(tctx
, ctx
->port_count
[level
], ctx
->port_count
[old_level
],
162 "EnumPorts invalid value");
164 /* if the array sizes are not the same we would maybe segfault in the following code */
166 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
167 int level
= levels
[i
];
168 for (j
=0;j
<ctx
->port_count
[level
];j
++) {
169 union spoolss_PortInfo
*cur
= &ctx
->ports
[level
][j
];
170 union spoolss_PortInfo
*ref
= &ctx
->ports
[2][j
];
173 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, port_name
);
176 /* level 2 is our reference, and it makes no sense to compare it to itself */
185 static bool test_GetPrintProcessorDirectory(struct torture_context
*tctx
,
186 struct dcerpc_pipe
*p
,
187 struct test_spoolss_context
*ctx
)
190 struct spoolss_GetPrintProcessorDirectory r
;
205 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
208 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
214 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
215 int level
= levels
[i
].level
;
218 r
.in
.server
= levels
[i
].server
;
219 r
.in
.environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
223 r
.out
.needed
= &needed
;
225 torture_comment(tctx
, "Testing GetPrintProcessorDirectory level %u\n", r
.in
.level
);
227 status
= dcerpc_spoolss_GetPrintProcessorDirectory(p
, ctx
, &r
);
228 torture_assert_ntstatus_ok(tctx
, status
,
229 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
230 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
231 "GetPrintProcessorDirectory unexpected return code");
233 blob
= data_blob_talloc(ctx
, NULL
, needed
);
234 data_blob_clear(&blob
);
236 r
.in
.offered
= needed
;
238 status
= dcerpc_spoolss_GetPrintProcessorDirectory(p
, ctx
, &r
);
239 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
241 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrintProcessorDirectory failed");
248 static bool test_GetPrinterDriverDirectory(struct torture_context
*tctx
,
249 struct dcerpc_pipe
*p
,
250 struct test_spoolss_context
*ctx
)
253 struct spoolss_GetPrinterDriverDirectory r
;
268 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
271 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
277 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
278 int level
= levels
[i
].level
;
281 r
.in
.server
= levels
[i
].server
;
282 r
.in
.environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
286 r
.out
.needed
= &needed
;
288 torture_comment(tctx
, "Testing GetPrinterDriverDirectory level %u\n", r
.in
.level
);
290 status
= dcerpc_spoolss_GetPrinterDriverDirectory(p
, ctx
, &r
);
291 torture_assert_ntstatus_ok(tctx
, status
,
292 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
293 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
294 "GetPrinterDriverDirectory unexpected return code");
296 blob
= data_blob_talloc(ctx
, NULL
, needed
);
297 data_blob_clear(&blob
);
299 r
.in
.offered
= needed
;
301 status
= dcerpc_spoolss_GetPrinterDriverDirectory(p
, ctx
, &r
);
302 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
304 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrinterDriverDirectory failed");
310 static bool test_EnumPrinterDrivers(struct torture_context
*tctx
,
311 struct dcerpc_pipe
*p
,
312 struct test_spoolss_context
*ctx
)
315 struct spoolss_EnumPrinterDrivers r
;
316 uint16_t levels
[] = { 1, 2, 3, 4, 5, 6 };
318 const char *architectures
[] = {
319 SPOOLSS_ARCHITECTURE_NT_X86
,
320 SPOOLSS_ARCHITECTURE_ALL
323 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
324 for (a
=0;a
<ARRAY_SIZE(architectures
);a
++) {
325 int level
= levels
[i
];
329 union spoolss_DriverInfo
*info
;
331 /* FIXME: gd, come back and fix "" as server, and handle
332 * priority of returned error codes in torture test and samba 3
335 r
.in
.server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
336 r
.in
.environment
= architectures
[a
];
340 r
.out
.needed
= &needed
;
341 r
.out
.count
= &count
;
344 torture_comment(tctx
, "Testing EnumPrinterDrivers level %u (%s)\n", r
.in
.level
, r
.in
.environment
);
346 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, ctx
, &r
);
347 torture_assert_ntstatus_ok(tctx
, status
,
348 "dcerpc_spoolss_EnumPrinterDrivers failed");
349 if (W_ERROR_IS_OK(r
.out
.result
)) {
350 /* TODO: do some more checks here */
353 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
354 blob
= data_blob_talloc(ctx
, NULL
, needed
);
355 data_blob_clear(&blob
);
357 r
.in
.offered
= needed
;
359 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, ctx
, &r
);
360 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinterDrivers failed");
363 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDrivers failed");
365 /* don't do cross-architecture comparison */
366 if (strequal(r
.in
.environment
, SPOOLSS_ARCHITECTURE_ALL
)) {
370 ctx
->driver_count
[level
] = count
;
371 ctx
->drivers
[level
] = info
;
375 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
376 int level
= levels
[i
];
377 int old_level
= levels
[i
-1];
379 /* don't do cross-architecture comparison */
380 if (strequal(r
.in
.environment
, SPOOLSS_ARCHITECTURE_ALL
)) {
384 torture_assert_int_equal(tctx
, ctx
->driver_count
[level
], ctx
->driver_count
[old_level
],
385 "EnumPrinterDrivers invalid value");
388 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
389 int level
= levels
[i
];
391 /* don't do cross-architecture comparison */
392 if (strequal(r
.in
.environment
, SPOOLSS_ARCHITECTURE_ALL
)) {
396 for (j
=0;j
<ctx
->driver_count
[level
];j
++) {
397 union spoolss_DriverInfo
*cur
= &ctx
->drivers
[level
][j
];
398 union spoolss_DriverInfo
*ref
= &ctx
->drivers
[6][j
];
401 COMPARE_STRING(tctx
, cur
->info1
, ref
->info6
, driver_name
);
404 COMPARE_UINT32(tctx
, cur
->info2
, ref
->info6
, version
);
405 COMPARE_STRING(tctx
, cur
->info2
, ref
->info6
, driver_name
);
406 COMPARE_STRING(tctx
, cur
->info2
, ref
->info6
, architecture
);
407 COMPARE_STRING(tctx
, cur
->info2
, ref
->info6
, driver_path
);
408 COMPARE_STRING(tctx
, cur
->info2
, ref
->info6
, data_file
);
409 COMPARE_STRING(tctx
, cur
->info2
, ref
->info6
, config_file
);
412 COMPARE_UINT32(tctx
, cur
->info3
, ref
->info6
, version
);
413 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, driver_name
);
414 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, architecture
);
415 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, driver_path
);
416 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, data_file
);
417 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, config_file
);
418 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, help_file
);
419 COMPARE_STRING_ARRAY(tctx
, cur
->info3
, ref
->info6
, dependent_files
);
420 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, monitor_name
);
421 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, default_datatype
);
424 COMPARE_UINT32(tctx
, cur
->info4
, ref
->info6
, version
);
425 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, driver_name
);
426 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, architecture
);
427 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, driver_path
);
428 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, data_file
);
429 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, config_file
);
430 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, help_file
);
431 COMPARE_STRING_ARRAY(tctx
, cur
->info4
, ref
->info6
, dependent_files
);
432 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, monitor_name
);
433 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, default_datatype
);
434 COMPARE_STRING_ARRAY(tctx
, cur
->info4
, ref
->info6
, previous_names
);
437 COMPARE_UINT32(tctx
, cur
->info5
, ref
->info6
, version
);
438 COMPARE_STRING(tctx
, cur
->info5
, ref
->info6
, driver_name
);
439 COMPARE_STRING(tctx
, cur
->info5
, ref
->info6
, architecture
);
440 COMPARE_STRING(tctx
, cur
->info5
, ref
->info6
, driver_path
);
441 COMPARE_STRING(tctx
, cur
->info5
, ref
->info6
, data_file
);
442 COMPARE_STRING(tctx
, cur
->info5
, ref
->info6
, config_file
);
443 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_attributes);*/
444 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, config_version);*/
445 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_version); */
448 /* level 6 is our reference, and it makes no sense to compare it to itself */
457 static bool test_EnumMonitors(struct torture_context
*tctx
,
458 struct dcerpc_pipe
*p
,
459 struct test_spoolss_context
*ctx
)
462 struct spoolss_EnumMonitors r
;
463 uint16_t levels
[] = { 1, 2 };
466 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
467 int level
= levels
[i
];
471 union spoolss_MonitorInfo
*info
;
473 r
.in
.servername
= "";
477 r
.out
.needed
= &needed
;
478 r
.out
.count
= &count
;
481 torture_comment(tctx
, "Testing EnumMonitors level %u\n", r
.in
.level
);
483 status
= dcerpc_spoolss_EnumMonitors(p
, ctx
, &r
);
484 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumMonitors failed");
485 if (W_ERROR_IS_OK(r
.out
.result
)) {
486 /* TODO: do some more checks here */
489 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
490 "EnumMonitors failed");
492 blob
= data_blob_talloc(ctx
, NULL
, needed
);
493 data_blob_clear(&blob
);
495 r
.in
.offered
= needed
;
497 status
= dcerpc_spoolss_EnumMonitors(p
, ctx
, &r
);
498 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumMonitors failed");
500 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumMonitors failed");
502 ctx
->monitor_count
[level
] = count
;
503 ctx
->monitors
[level
] = info
;
506 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
507 int level
= levels
[i
];
508 int old_level
= levels
[i
-1];
509 torture_assert_int_equal(tctx
, ctx
->monitor_count
[level
], ctx
->monitor_count
[old_level
],
510 "EnumMonitors invalid value");
513 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
514 int level
= levels
[i
];
515 for (j
=0;j
<ctx
->monitor_count
[level
];j
++) {
516 union spoolss_MonitorInfo
*cur
= &ctx
->monitors
[level
][j
];
517 union spoolss_MonitorInfo
*ref
= &ctx
->monitors
[2][j
];
520 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, monitor_name
);
523 /* level 2 is our reference, and it makes no sense to compare it to itself */
532 static bool test_EnumPrintProcessors(struct torture_context
*tctx
,
533 struct dcerpc_pipe
*p
,
534 struct test_spoolss_context
*ctx
)
537 struct spoolss_EnumPrintProcessors r
;
538 uint16_t levels
[] = { 1 };
541 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
542 int level
= levels
[i
];
546 union spoolss_PrintProcessorInfo
*info
;
548 r
.in
.servername
= "";
549 r
.in
.environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
553 r
.out
.needed
= &needed
;
554 r
.out
.count
= &count
;
557 torture_comment(tctx
, "Testing EnumPrintProcessors level %u\n", r
.in
.level
);
559 status
= dcerpc_spoolss_EnumPrintProcessors(p
, ctx
, &r
);
560 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcessors failed");
561 if (W_ERROR_IS_OK(r
.out
.result
)) {
562 /* TODO: do some more checks here */
565 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
566 "EnumPrintProcessors unexpected return code");
568 blob
= data_blob_talloc(ctx
, NULL
, needed
);
569 data_blob_clear(&blob
);
571 r
.in
.offered
= needed
;
573 status
= dcerpc_spoolss_EnumPrintProcessors(p
, ctx
, &r
);
574 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcessors failed");
576 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrintProcessors failed");
578 ctx
->print_processor_count
[level
] = count
;
579 ctx
->print_processors
[level
] = info
;
582 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
583 int level
= levels
[i
];
584 int old_level
= levels
[i
-1];
585 torture_assert_int_equal(tctx
, ctx
->print_processor_count
[level
], ctx
->print_processor_count
[old_level
],
586 "EnumPrintProcessors failed");
589 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
590 int level
= levels
[i
];
591 for (j
=0;j
<ctx
->print_processor_count
[level
];j
++) {
593 union spoolss_PrintProcessorInfo
*cur
= &ctx
->print_processors
[level
][j
];
594 union spoolss_PrintProcessorInfo
*ref
= &ctx
->print_processors
[1][j
];
598 /* level 1 is our reference, and it makes no sense to compare it to itself */
607 static bool test_EnumPrintProcDataTypes(struct torture_context
*tctx
,
608 struct dcerpc_pipe
*p
,
609 struct test_spoolss_context
*ctx
)
612 struct spoolss_EnumPrintProcDataTypes r
;
613 uint16_t levels
[] = { 1 };
616 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
617 int level
= levels
[i
];
621 union spoolss_PrintProcDataTypesInfo
*info
;
623 r
.in
.servername
= "";
624 r
.in
.print_processor_name
= "winprint";
628 r
.out
.needed
= &needed
;
629 r
.out
.count
= &count
;
632 torture_comment(tctx
, "Testing EnumPrintProcDataTypes level %u\n", r
.in
.level
);
634 status
= dcerpc_spoolss_EnumPrintProcDataTypes(p
, ctx
, &r
);
635 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcDataType failed");
636 if (W_ERROR_IS_OK(r
.out
.result
)) {
637 /* TODO: do some more checks here */
640 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
641 "EnumPrintProcDataTypes unexpected return code");
643 blob
= data_blob_talloc(ctx
, NULL
, needed
);
644 data_blob_clear(&blob
);
646 r
.in
.offered
= needed
;
648 status
= dcerpc_spoolss_EnumPrintProcDataTypes(p
, ctx
, &r
);
649 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
651 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrintProcDataTypes failed");
658 static bool test_EnumPrinters(struct torture_context
*tctx
,
659 struct dcerpc_pipe
*p
,
660 struct test_spoolss_context
*ctx
)
662 struct spoolss_EnumPrinters r
;
664 uint16_t levels
[] = { 0, 1, 2, 4, 5 };
667 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
668 int level
= levels
[i
];
672 union spoolss_PrinterInfo
*info
;
674 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
679 r
.out
.needed
= &needed
;
680 r
.out
.count
= &count
;
683 torture_comment(tctx
, "Testing EnumPrinters level %u\n", r
.in
.level
);
685 status
= dcerpc_spoolss_EnumPrinters(p
, ctx
, &r
);
686 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinters failed");
687 if (W_ERROR_IS_OK(r
.out
.result
)) {
688 /* TODO: do some more checks here */
691 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
692 "EnumPrinters unexpected return code");
694 blob
= data_blob_talloc(ctx
, NULL
, needed
);
695 data_blob_clear(&blob
);
697 r
.in
.offered
= needed
;
699 status
= dcerpc_spoolss_EnumPrinters(p
, ctx
, &r
);
700 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinters failed");
702 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
704 ctx
->printer_count
[level
] = count
;
705 ctx
->printers
[level
] = info
;
708 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
709 int level
= levels
[i
];
710 int old_level
= levels
[i
-1];
711 torture_assert_int_equal(tctx
, ctx
->printer_count
[level
], ctx
->printer_count
[old_level
],
712 "EnumPrinters invalid value");
715 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
716 int level
= levels
[i
];
717 for (j
=0;j
<ctx
->printer_count
[level
];j
++) {
718 union spoolss_PrinterInfo
*cur
= &ctx
->printers
[level
][j
];
719 union spoolss_PrinterInfo
*ref
= &ctx
->printers
[2][j
];
722 COMPARE_STRING(tctx
, cur
->info0
, ref
->info2
, printername
);
723 COMPARE_STRING(tctx
, cur
->info0
, ref
->info2
, servername
);
724 COMPARE_UINT32(tctx
, cur
->info0
, ref
->info2
, cjobs
);
725 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
726 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
727 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
728 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
729 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
730 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
731 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
732 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
733 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
734 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
735 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
736 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
737 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
738 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
739 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
740 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
741 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
742 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
743 COMPARE_UINT32(tctx
, cur
->info0
, ref
->info2
, status
);
744 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
745 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
746 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
747 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
748 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
749 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
750 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
753 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
754 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
755 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
756 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, comment
);
759 /* level 2 is our reference, and it makes no sense to compare it to itself */
762 COMPARE_STRING(tctx
, cur
->info4
, ref
->info2
, printername
);
763 COMPARE_STRING(tctx
, cur
->info4
, ref
->info2
, servername
);
764 COMPARE_UINT32(tctx
, cur
->info4
, ref
->info2
, attributes
);
767 COMPARE_STRING(tctx
, cur
->info5
, ref
->info2
, printername
);
768 COMPARE_STRING(tctx
, cur
->info5
, ref
->info2
, portname
);
769 COMPARE_UINT32(tctx
, cur
->info5
, ref
->info2
, attributes
);
770 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
771 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
778 * - verify that the port of a printer was in the list returned by EnumPorts
784 static bool test_GetPrinter(struct torture_context
*tctx
,
785 struct dcerpc_pipe
*p
,
786 struct policy_handle
*handle
)
789 struct spoolss_GetPrinter r
;
790 uint16_t levels
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
794 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
795 r
.in
.handle
= handle
;
796 r
.in
.level
= levels
[i
];
799 r
.out
.needed
= &needed
;
801 torture_comment(tctx
, "Testing GetPrinter level %u\n", r
.in
.level
);
803 status
= dcerpc_spoolss_GetPrinter(p
, tctx
, &r
);
804 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinter failed");
806 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
807 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
808 data_blob_clear(&blob
);
810 r
.in
.offered
= needed
;
811 status
= dcerpc_spoolss_GetPrinter(p
, tctx
, &r
);
814 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinter failed");
816 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrinter failed");
822 static bool test_SetPrinter_errors(struct torture_context
*tctx
,
823 struct dcerpc_pipe
*p
,
824 struct policy_handle
*handle
)
826 struct spoolss_SetPrinter r
;
827 uint16_t levels
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
830 struct spoolss_SetPrinterInfoCtr info_ctr
;
831 struct spoolss_DevmodeContainer devmode_ctr
;
832 struct sec_desc_buf secdesc_ctr
;
835 info_ctr
.info
.info0
= NULL
;
837 ZERO_STRUCT(devmode_ctr
);
838 ZERO_STRUCT(secdesc_ctr
);
840 r
.in
.handle
= handle
;
841 r
.in
.info_ctr
= &info_ctr
;
842 r
.in
.devmode_ctr
= &devmode_ctr
;
843 r
.in
.secdesc_ctr
= &secdesc_ctr
;
846 torture_comment(tctx
, "Testing SetPrinter all zero\n");
848 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter(p
, tctx
, &r
),
849 "failed to call SetPrinter");
850 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
851 "failed to call SetPrinter");
854 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
856 struct spoolss_SetPrinterInfo0 info0
;
857 struct spoolss_SetPrinterInfo1 info1
;
858 struct spoolss_SetPrinterInfo2 info2
;
859 struct spoolss_SetPrinterInfo3 info3
;
860 struct spoolss_SetPrinterInfo4 info4
;
861 struct spoolss_SetPrinterInfo5 info5
;
862 struct spoolss_SetPrinterInfo6 info6
;
863 struct spoolss_SetPrinterInfo7 info7
;
864 struct spoolss_DeviceModeInfo info8
;
865 struct spoolss_DeviceModeInfo info9
;
868 info_ctr
.level
= levels
[i
];
872 info_ctr
.info
.info0
= &info0
;
876 info_ctr
.info
.info1
= &info1
;
880 info_ctr
.info
.info2
= &info2
;
884 info_ctr
.info
.info3
= &info3
;
888 info_ctr
.info
.info4
= &info4
;
892 info_ctr
.info
.info5
= &info5
;
896 info_ctr
.info
.info6
= &info6
;
900 info_ctr
.info
.info7
= &info7
;
904 info_ctr
.info
.info8
= &info8
;
908 info_ctr
.info
.info9
= &info9
;
912 torture_comment(tctx
, "Testing SetPrinter level %d, command %d\n",
913 info_ctr
.level
, r
.in
.command
);
915 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter(p
, tctx
, &r
),
916 "failed to call SetPrinter");
918 switch (r
.in
.command
) {
919 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
: /* 0 */
920 /* is ignored for all levels other then 0 */
921 if (info_ctr
.level
> 0) {
925 case SPOOLSS_PRINTER_CONTROL_PAUSE
: /* 1 */
926 case SPOOLSS_PRINTER_CONTROL_RESUME
: /* 2 */
927 case SPOOLSS_PRINTER_CONTROL_PURGE
: /* 3 */
928 if (info_ctr
.level
> 0) {
929 /* is invalid for all levels other then 0 */
930 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PRINTER_COMMAND
,
931 "unexpected error code returned");
934 torture_assert_werr_ok(tctx
, r
.out
.result
,
935 "failed to call SetPrinter with non 0 command");
940 case SPOOLSS_PRINTER_CONTROL_SET_STATUS
: /* 4 */
941 /* FIXME: gd needs further investigation */
943 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PRINTER_COMMAND
,
944 "unexpected error code returned");
948 switch (info_ctr
.level
) {
950 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
,
951 "unexpected error code returned");
954 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_PRINTER_DRIVER
,
955 "unexpected error code returned");
961 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
962 "unexpected error code returned");
965 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_NOT_SUPPORTED
,
966 "unexpected error code returned");
969 torture_assert_werr_ok(tctx
, r
.out
.result
,
970 "failed to call SetPrinter");
975 if (r
.in
.command
< 5) {
983 static void clear_info2(struct spoolss_SetPrinterInfoCtr
*r
)
985 if ((r
->level
== 2) && (r
->info
.info2
)) {
986 r
->info
.info2
->secdesc
= NULL
;
987 r
->info
.info2
->devmode
= NULL
;
991 static bool test_PrinterInfo(struct torture_context
*tctx
,
992 struct dcerpc_pipe
*p
,
993 struct policy_handle
*handle
)
996 struct spoolss_SetPrinter s
;
997 struct spoolss_GetPrinter q
;
998 struct spoolss_GetPrinter q0
;
999 struct spoolss_SetPrinterInfoCtr info_ctr
;
1000 union spoolss_PrinterInfo info
;
1001 struct spoolss_DevmodeContainer devmode_ctr
;
1002 struct sec_desc_buf secdesc_ctr
;
1007 uint32_t status_list
[] = {
1008 /* these do not stick
1009 PRINTER_STATUS_PAUSED,
1010 PRINTER_STATUS_ERROR,
1011 PRINTER_STATUS_PENDING_DELETION, */
1012 PRINTER_STATUS_PAPER_JAM
,
1013 PRINTER_STATUS_PAPER_OUT
,
1014 PRINTER_STATUS_MANUAL_FEED
,
1015 PRINTER_STATUS_PAPER_PROBLEM
,
1016 PRINTER_STATUS_OFFLINE
,
1017 PRINTER_STATUS_IO_ACTIVE
,
1018 PRINTER_STATUS_BUSY
,
1019 PRINTER_STATUS_PRINTING
,
1020 PRINTER_STATUS_OUTPUT_BIN_FULL
,
1021 PRINTER_STATUS_NOT_AVAILABLE
,
1022 PRINTER_STATUS_WAITING
,
1023 PRINTER_STATUS_PROCESSING
,
1024 PRINTER_STATUS_INITIALIZING
,
1025 PRINTER_STATUS_WARMING_UP
,
1026 PRINTER_STATUS_TONER_LOW
,
1027 PRINTER_STATUS_NO_TONER
,
1028 PRINTER_STATUS_PAGE_PUNT
,
1029 PRINTER_STATUS_USER_INTERVENTION
,
1030 PRINTER_STATUS_OUT_OF_MEMORY
,
1031 PRINTER_STATUS_DOOR_OPEN
,
1032 PRINTER_STATUS_SERVER_UNKNOWN
,
1033 PRINTER_STATUS_POWER_SAVE
,
1034 /* these do not stick
1043 uint32_t default_attribute
= PRINTER_ATTRIBUTE_LOCAL
;
1044 uint32_t attribute_list
[] = {
1045 PRINTER_ATTRIBUTE_QUEUED
,
1046 /* fails with WERR_INVALID_DATATYPE:
1047 PRINTER_ATTRIBUTE_DIRECT, */
1049 PRINTER_ATTRIBUTE_DEFAULT, */
1050 PRINTER_ATTRIBUTE_SHARED
,
1052 PRINTER_ATTRIBUTE_NETWORK, */
1053 PRINTER_ATTRIBUTE_HIDDEN
,
1054 PRINTER_ATTRIBUTE_LOCAL
,
1055 PRINTER_ATTRIBUTE_ENABLE_DEVQ
,
1056 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
,
1057 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST
,
1058 PRINTER_ATTRIBUTE_WORK_OFFLINE
,
1060 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1061 /* fails with WERR_INVALID_DATATYPE:
1062 PRINTER_ATTRIBUTE_RAW_ONLY, */
1063 /* these do not stick
1064 PRINTER_ATTRIBUTE_PUBLISHED,
1065 PRINTER_ATTRIBUTE_FAX,
1066 PRINTER_ATTRIBUTE_TS,
1085 ZERO_STRUCT(devmode_ctr
);
1086 ZERO_STRUCT(secdesc_ctr
);
1088 s
.in
.handle
= handle
;
1090 s
.in
.info_ctr
= &info_ctr
;
1091 s
.in
.devmode_ctr
= &devmode_ctr
;
1092 s
.in
.secdesc_ctr
= &secdesc_ctr
;
1094 q
.in
.handle
= handle
;
1098 #define TESTGETCALL(call, r) \
1099 r.in.buffer = NULL; \
1101 r.out.needed = &needed; \
1102 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1103 if (!NT_STATUS_IS_OK(status)) { \
1104 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1105 r.in.level, nt_errstr(status), __location__); \
1109 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1110 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1111 data_blob_clear(&blob); \
1112 r.in.buffer = &blob; \
1113 r.in.offered = needed; \
1115 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1116 if (!NT_STATUS_IS_OK(status)) { \
1117 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1118 r.in.level, nt_errstr(status), __location__); \
1122 if (!W_ERROR_IS_OK(r.out.result)) { \
1123 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1124 r.in.level, win_errstr(r.out.result), __location__); \
1130 #define TESTSETCALL_EXP(call, r, err) \
1131 clear_info2(&info_ctr);\
1132 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1133 if (!NT_STATUS_IS_OK(status)) { \
1134 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1135 r.in.info_ctr->level, nt_errstr(status), __location__); \
1139 if (!W_ERROR_IS_OK(err)) { \
1140 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1141 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1142 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1147 if (!W_ERROR_IS_OK(r.out.result)) { \
1148 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1149 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1154 #define TESTSETCALL(call, r) \
1155 TESTSETCALL_EXP(call, r, WERR_OK)
1157 #define STRING_EQUAL(s1, s2, field) \
1158 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1159 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1160 #field, s2, __location__); \
1165 #define MEM_EQUAL(s1, s2, length, field) \
1166 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1167 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1168 #field, (const char *)s2, __location__); \
1173 #define INT_EQUAL(i1, i2, field) \
1175 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1176 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1181 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1182 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1183 q.in.level = lvl1; \
1184 TESTGETCALL(GetPrinter, q) \
1185 info_ctr.level = lvl1; \
1186 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1187 info_ctr.info.info ## lvl1->field1 = value;\
1188 TESTSETCALL_EXP(SetPrinter, s, err) \
1189 info_ctr.info.info ## lvl1->field1 = ""; \
1190 TESTGETCALL(GetPrinter, q) \
1191 info_ctr.info.info ## lvl1->field1 = value; \
1192 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1193 q.in.level = lvl2; \
1194 TESTGETCALL(GetPrinter, q) \
1195 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1196 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1199 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1200 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1203 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1204 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1205 q.in.level = lvl1; \
1206 TESTGETCALL(GetPrinter, q) \
1207 info_ctr.level = lvl1; \
1208 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1209 info_ctr.info.info ## lvl1->field1 = value; \
1210 TESTSETCALL(SetPrinter, s) \
1211 info_ctr.info.info ## lvl1->field1 = 0; \
1212 TESTGETCALL(GetPrinter, q) \
1213 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1214 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1215 q.in.level = lvl2; \
1216 TESTGETCALL(GetPrinter, q) \
1217 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1218 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1221 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1222 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1226 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1228 TEST_PRINTERINFO_STRING(2, comment
, 1, comment
, "xx2-1 comment");
1229 TEST_PRINTERINFO_STRING(2, comment
, 2, comment
, "xx2-2 comment");
1231 /* level 0 printername does not stick */
1232 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1233 TEST_PRINTERINFO_STRING(2, printername
, 1, name
, "xx2-1 printer");
1234 TEST_PRINTERINFO_STRING(2, printername
, 2, printername
, "xx2-2 printer");
1235 TEST_PRINTERINFO_STRING(2, printername
, 4, printername
, "xx2-4 printer");
1236 TEST_PRINTERINFO_STRING(2, printername
, 5, printername
, "xx2-5 printer");
1237 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1238 TEST_PRINTERINFO_STRING(4, printername
, 1, name
, "xx4-1 printer");
1239 TEST_PRINTERINFO_STRING(4, printername
, 2, printername
, "xx4-2 printer");
1240 TEST_PRINTERINFO_STRING(4, printername
, 4, printername
, "xx4-4 printer");
1241 TEST_PRINTERINFO_STRING(4, printername
, 5, printername
, "xx4-5 printer");
1242 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1243 TEST_PRINTERINFO_STRING(5, printername
, 1, name
, "xx5-1 printer");
1244 TEST_PRINTERINFO_STRING(5, printername
, 2, printername
, "xx5-2 printer");
1245 TEST_PRINTERINFO_STRING(5, printername
, 4, printername
, "xx5-4 printer");
1246 TEST_PRINTERINFO_STRING(5, printername
, 5, printername
, "xx5-5 printer");
1248 /* servername can be set but does not stick
1249 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1250 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1251 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1254 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1255 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname
, 2, portname
, "xx2-2 portname", WERR_UNKNOWN_PORT
);
1256 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname
, 5, portname
, "xx2-5 portname", WERR_UNKNOWN_PORT
);
1257 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname
, 2, portname
, "xx5-2 portname", WERR_UNKNOWN_PORT
);
1258 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname
, 5, portname
, "xx5-5 portname", WERR_UNKNOWN_PORT
);
1260 TEST_PRINTERINFO_STRING(2, sharename
, 2, sharename
, "xx2-2 sharename");
1261 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1262 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername
, 2, drivername
, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER
);
1263 TEST_PRINTERINFO_STRING(2, location
, 2, location
, "xx2-2 location");
1264 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1265 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile
, 2, sepfile
, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE
);
1266 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1267 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor
, 2, printprocessor
, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR
);
1268 TEST_PRINTERINFO_STRING(2, datatype
, 2, datatype
, "xx2-2 datatype");
1269 TEST_PRINTERINFO_STRING(2, parameters
, 2, parameters
, "xx2-2 parameters");
1271 for (i
=0; i
< ARRAY_SIZE(attribute_list
); i
++) {
1272 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1274 (attribute_list[i] | default_attribute)
1276 TEST_PRINTERINFO_INT_EXP(2, attributes
, 2, attributes
,
1278 (attribute_list
[i
] | default_attribute
)
1280 TEST_PRINTERINFO_INT_EXP(2, attributes
, 4, attributes
,
1282 (attribute_list
[i
] | default_attribute
)
1284 TEST_PRINTERINFO_INT_EXP(2, attributes
, 5, attributes
,
1286 (attribute_list
[i
] | default_attribute
)
1288 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1290 (attribute_list[i] | default_attribute)
1292 TEST_PRINTERINFO_INT_EXP(4, attributes
, 2, attributes
,
1294 (attribute_list
[i
] | default_attribute
)
1296 TEST_PRINTERINFO_INT_EXP(4, attributes
, 4, attributes
,
1298 (attribute_list
[i
] | default_attribute
)
1300 TEST_PRINTERINFO_INT_EXP(4, attributes
, 5, attributes
,
1302 (attribute_list
[i
] | default_attribute
)
1304 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1306 (attribute_list[i] | default_attribute)
1308 TEST_PRINTERINFO_INT_EXP(5, attributes
, 2, attributes
,
1310 (attribute_list
[i
] | default_attribute
)
1312 TEST_PRINTERINFO_INT_EXP(5, attributes
, 4, attributes
,
1314 (attribute_list
[i
] | default_attribute
)
1316 TEST_PRINTERINFO_INT_EXP(5, attributes
, 5, attributes
,
1318 (attribute_list
[i
] | default_attribute
)
1322 for (i
=0; i
< ARRAY_SIZE(status_list
); i
++) {
1323 /* level 2 sets do not stick
1324 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1325 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1326 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1327 TEST_PRINTERINFO_INT(6, status
, 0, status
, status_list
[i
]);
1328 TEST_PRINTERINFO_INT(6, status
, 2, status
, status_list
[i
]);
1329 TEST_PRINTERINFO_INT(6, status
, 6, status
, status_list
[i
]);
1332 /* priorities need to be between 0 and 99
1333 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1334 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 0);
1335 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 1);
1336 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 99);
1337 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1338 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 0);
1339 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 1);
1340 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 99);
1341 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1343 TEST_PRINTERINFO_INT(2, starttime
, 2, starttime
, __LINE__
);
1344 TEST_PRINTERINFO_INT(2, untiltime
, 2, untiltime
, __LINE__
);
1347 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1348 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1351 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1352 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1354 /* FIXME: gd also test devmode and secdesc behavior */
1357 /* verify composition of level 1 description field */
1358 const char *description
;
1362 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1364 description
= talloc_strdup(tctx
, q0
.out
.info
->info1
.description
);
1367 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1369 tmp
= talloc_asprintf(tctx
, "%s,%s,%s",
1370 q0
.out
.info
->info2
.printername
,
1371 q0
.out
.info
->info2
.drivername
,
1372 q0
.out
.info
->info2
.location
);
1374 do { STRING_EQUAL(description
, tmp
, "description")} while (0);
1381 static bool test_ClosePrinter(struct torture_context
*tctx
,
1382 struct dcerpc_pipe
*p
,
1383 struct policy_handle
*handle
)
1386 struct spoolss_ClosePrinter r
;
1388 r
.in
.handle
= handle
;
1389 r
.out
.handle
= handle
;
1391 torture_comment(tctx
, "Testing ClosePrinter\n");
1393 status
= dcerpc_spoolss_ClosePrinter(p
, tctx
, &r
);
1394 torture_assert_ntstatus_ok(tctx
, status
, "ClosePrinter failed");
1399 static bool test_GetForm(struct torture_context
*tctx
,
1400 struct dcerpc_pipe
*p
,
1401 struct policy_handle
*handle
,
1402 const char *form_name
,
1406 struct spoolss_GetForm r
;
1409 r
.in
.handle
= handle
;
1410 r
.in
.form_name
= form_name
;
1414 r
.out
.needed
= &needed
;
1416 torture_comment(tctx
, "Testing GetForm level %d\n", r
.in
.level
);
1418 status
= dcerpc_spoolss_GetForm(p
, tctx
, &r
);
1419 torture_assert_ntstatus_ok(tctx
, status
, "GetForm failed");
1421 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1422 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1423 data_blob_clear(&blob
);
1424 r
.in
.buffer
= &blob
;
1425 r
.in
.offered
= needed
;
1426 status
= dcerpc_spoolss_GetForm(p
, tctx
, &r
);
1427 torture_assert_ntstatus_ok(tctx
, status
, "GetForm failed");
1429 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetForm failed");
1431 torture_assert(tctx
, r
.out
.info
, "No form info returned");
1434 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetForm failed");
1439 static bool test_EnumForms(struct torture_context
*tctx
,
1440 struct dcerpc_pipe
*p
,
1441 struct policy_handle
*handle
, bool print_server
)
1444 struct spoolss_EnumForms r
;
1448 uint32_t levels
[] = { 1, 2 };
1451 for (i
=0; i
<ARRAY_SIZE(levels
); i
++) {
1453 union spoolss_FormInfo
*info
;
1455 r
.in
.handle
= handle
;
1456 r
.in
.level
= levels
[i
];
1459 r
.out
.needed
= &needed
;
1460 r
.out
.count
= &count
;
1463 torture_comment(tctx
, "Testing EnumForms level %d\n", levels
[i
]);
1465 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &r
);
1466 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
1468 if ((r
.in
.level
== 2) && (W_ERROR_EQUAL(r
.out
.result
, WERR_UNKNOWN_LEVEL
))) {
1472 if (print_server
&& W_ERROR_EQUAL(r
.out
.result
, WERR_BADFID
))
1473 torture_fail(tctx
, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1475 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1477 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1478 data_blob_clear(&blob
);
1479 r
.in
.buffer
= &blob
;
1480 r
.in
.offered
= needed
;
1482 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &r
);
1484 torture_assert(tctx
, info
, "No forms returned");
1486 for (j
= 0; j
< count
; j
++) {
1488 ret
&= test_GetForm(tctx
, p
, handle
, info
[j
].info1
.form_name
, levels
[i
]);
1492 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
1494 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumForms failed");
1500 static bool test_DeleteForm(struct torture_context
*tctx
,
1501 struct dcerpc_pipe
*p
,
1502 struct policy_handle
*handle
,
1503 const char *form_name
)
1506 struct spoolss_DeleteForm r
;
1508 r
.in
.handle
= handle
;
1509 r
.in
.form_name
= form_name
;
1511 status
= dcerpc_spoolss_DeleteForm(p
, tctx
, &r
);
1513 torture_assert_ntstatus_ok(tctx
, status
, "DeleteForm failed");
1515 torture_assert_werr_ok(tctx
, r
.out
.result
, "DeleteForm failed");
1520 static bool test_AddForm(struct torture_context
*tctx
,
1521 struct dcerpc_pipe
*p
,
1522 struct policy_handle
*handle
, bool print_server
)
1524 struct spoolss_AddForm r
;
1525 struct spoolss_AddFormInfo1 addform
;
1526 const char *form_name
= "testform3";
1530 r
.in
.handle
= handle
;
1532 r
.in
.info
.info1
= &addform
;
1533 addform
.flags
= SPOOLSS_FORM_USER
;
1534 addform
.form_name
= form_name
;
1535 addform
.size
.width
= 50;
1536 addform
.size
.height
= 25;
1537 addform
.area
.left
= 5;
1538 addform
.area
.top
= 10;
1539 addform
.area
.right
= 45;
1540 addform
.area
.bottom
= 15;
1542 status
= dcerpc_spoolss_AddForm(p
, tctx
, &r
);
1544 torture_assert_ntstatus_ok(tctx
, status
, "AddForm failed");
1546 torture_assert_werr_ok(tctx
, r
.out
.result
, "AddForm failed");
1548 if (!print_server
) ret
&= test_GetForm(tctx
, p
, handle
, form_name
, 1);
1551 struct spoolss_SetForm sf
;
1552 struct spoolss_AddFormInfo1 setform
;
1554 sf
.in
.handle
= handle
;
1555 sf
.in
.form_name
= form_name
;
1557 sf
.in
.info
.info1
= &setform
;
1558 setform
.flags
= addform
.flags
;
1559 setform
.form_name
= addform
.form_name
;
1560 setform
.size
= addform
.size
;
1561 setform
.area
= addform
.area
;
1563 setform
.size
.width
= 1234;
1565 status
= dcerpc_spoolss_SetForm(p
, tctx
, &sf
);
1567 torture_assert_ntstatus_ok(tctx
, status
, "SetForm failed");
1569 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetForm failed");
1572 if (!print_server
) ret
&= test_GetForm(tctx
, p
, handle
, form_name
, 1);
1575 struct spoolss_EnumForms e
;
1576 union spoolss_FormInfo
*info
;
1581 e
.in
.handle
= handle
;
1585 e
.out
.needed
= &needed
;
1586 e
.out
.count
= &count
;
1589 torture_comment(tctx
, "Testing EnumForms level 1\n");
1591 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &e
);
1592 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
1594 if (print_server
&& W_ERROR_EQUAL(e
.out
.result
, WERR_BADFID
))
1595 torture_fail(tctx
, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1597 if (W_ERROR_EQUAL(e
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1599 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1600 data_blob_clear(&blob
);
1601 e
.in
.buffer
= &blob
;
1602 e
.in
.offered
= needed
;
1604 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &e
);
1606 torture_assert(tctx
, info
, "No forms returned");
1608 for (j
= 0; j
< count
; j
++) {
1609 if (strequal(form_name
, info
[j
].info1
.form_name
)) {
1615 torture_assert(tctx
, found
, "Newly added form not found in enum call");
1618 if (!test_DeleteForm(tctx
, p
, handle
, form_name
)) {
1625 static bool test_EnumPorts_old(struct torture_context
*tctx
,
1626 struct dcerpc_pipe
*p
)
1629 struct spoolss_EnumPorts r
;
1632 union spoolss_PortInfo
*info
;
1634 r
.in
.servername
= talloc_asprintf(tctx
, "\\\\%s",
1635 dcerpc_server_name(p
));
1639 r
.out
.needed
= &needed
;
1640 r
.out
.count
= &count
;
1643 torture_comment(tctx
, "Testing EnumPorts\n");
1645 status
= dcerpc_spoolss_EnumPorts(p
, tctx
, &r
);
1647 torture_assert_ntstatus_ok(tctx
, status
, "EnumPorts failed");
1649 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1650 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1651 data_blob_clear(&blob
);
1652 r
.in
.buffer
= &blob
;
1653 r
.in
.offered
= needed
;
1655 status
= dcerpc_spoolss_EnumPorts(p
, tctx
, &r
);
1656 torture_assert_ntstatus_ok(tctx
, status
, "EnumPorts failed");
1658 torture_assert(tctx
, info
, "No ports returned");
1664 static bool test_AddPort(struct torture_context
*tctx
,
1665 struct dcerpc_pipe
*p
)
1668 struct spoolss_AddPort r
;
1670 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s",
1671 dcerpc_server_name(p
));
1673 r
.in
.monitor_name
= "foo";
1675 torture_comment(tctx
, "Testing AddPort\n");
1677 status
= dcerpc_spoolss_AddPort(p
, tctx
, &r
);
1679 torture_assert_ntstatus_ok(tctx
, status
, "AddPort failed");
1681 /* win2k3 returns WERR_NOT_SUPPORTED */
1685 if (!W_ERROR_IS_OK(r
.out
.result
)) {
1686 printf("AddPort failed - %s\n", win_errstr(r
.out
.result
));
1695 static bool test_GetJob(struct torture_context
*tctx
,
1696 struct dcerpc_pipe
*p
,
1697 struct policy_handle
*handle
, uint32_t job_id
)
1700 struct spoolss_GetJob r
;
1701 union spoolss_JobInfo info
;
1703 uint32_t levels
[] = {1, 2 /* 3, 4 */};
1706 r
.in
.handle
= handle
;
1707 r
.in
.job_id
= job_id
;
1711 r
.out
.needed
= &needed
;
1714 torture_comment(tctx
, "Testing GetJob level %d\n", r
.in
.level
);
1716 status
= dcerpc_spoolss_GetJob(p
, tctx
, &r
);
1717 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
, "Unexpected return code");
1719 for (i
= 0; i
< ARRAY_SIZE(levels
); i
++) {
1721 torture_comment(tctx
, "Testing GetJob level %d\n", r
.in
.level
);
1725 r
.in
.level
= levels
[i
];
1729 status
= dcerpc_spoolss_GetJob(p
, tctx
, &r
);
1730 torture_assert_ntstatus_ok(tctx
, status
, "GetJob failed");
1732 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1733 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1734 data_blob_clear(&blob
);
1735 r
.in
.buffer
= &blob
;
1736 r
.in
.offered
= needed
;
1738 status
= dcerpc_spoolss_GetJob(p
, tctx
, &r
);
1739 torture_assert_ntstatus_ok(tctx
, status
, "GetJob failed");
1742 torture_assert(tctx
, r
.out
.info
, "No job info returned");
1743 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetJob failed");
1749 static bool test_SetJob(struct torture_context
*tctx
,
1750 struct dcerpc_pipe
*p
,
1751 struct policy_handle
*handle
, uint32_t job_id
,
1752 enum spoolss_JobControl command
)
1755 struct spoolss_SetJob r
;
1757 r
.in
.handle
= handle
;
1758 r
.in
.job_id
= job_id
;
1760 r
.in
.command
= command
;
1763 case SPOOLSS_JOB_CONTROL_PAUSE
:
1764 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1766 case SPOOLSS_JOB_CONTROL_RESUME
:
1767 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1769 case SPOOLSS_JOB_CONTROL_CANCEL
:
1770 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1772 case SPOOLSS_JOB_CONTROL_RESTART
:
1773 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1775 case SPOOLSS_JOB_CONTROL_DELETE
:
1776 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1778 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER
:
1779 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1781 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED
:
1782 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1784 case SPOOLSS_JOB_CONTROL_RETAIN
:
1785 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1787 case SPOOLSS_JOB_CONTROL_RELEASE
:
1788 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1791 torture_comment(tctx
, "Testing SetJob\n");
1795 status
= dcerpc_spoolss_SetJob(p
, tctx
, &r
);
1796 torture_assert_ntstatus_ok(tctx
, status
, "SetJob failed");
1797 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetJob failed");
1802 static bool test_AddJob(struct torture_context
*tctx
,
1803 struct dcerpc_pipe
*p
,
1804 struct policy_handle
*handle
)
1807 struct spoolss_AddJob r
;
1811 r
.in
.handle
= handle
;
1813 r
.out
.needed
= &needed
;
1814 r
.in
.buffer
= r
.out
.buffer
= NULL
;
1816 torture_comment(tctx
, "Testing AddJob\n");
1818 status
= dcerpc_spoolss_AddJob(p
, tctx
, &r
);
1819 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
, "AddJob failed");
1823 status
= dcerpc_spoolss_AddJob(p
, tctx
, &r
);
1824 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
, "AddJob failed");
1830 static bool test_EnumJobs(struct torture_context
*tctx
,
1831 struct dcerpc_pipe
*p
,
1832 struct policy_handle
*handle
)
1835 struct spoolss_EnumJobs r
;
1838 union spoolss_JobInfo
*info
;
1840 r
.in
.handle
= handle
;
1842 r
.in
.numjobs
= 0xffffffff;
1846 r
.out
.needed
= &needed
;
1847 r
.out
.count
= &count
;
1850 torture_comment(tctx
, "Testing EnumJobs\n");
1852 status
= dcerpc_spoolss_EnumJobs(p
, tctx
, &r
);
1854 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
1856 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1858 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1859 data_blob_clear(&blob
);
1860 r
.in
.buffer
= &blob
;
1861 r
.in
.offered
= needed
;
1863 status
= dcerpc_spoolss_EnumJobs(p
, tctx
, &r
);
1865 torture_assert(tctx
, info
, "No jobs returned");
1867 for (j
= 0; j
< count
; j
++) {
1869 test_GetJob(tctx
, p
, handle
, info
[j
].info1
.job_id
);
1872 if (!torture_setting_bool(tctx
, "samba3", false)) {
1873 test_SetJob(tctx
, p
, handle
, info
[j
].info1
.job_id
, SPOOLSS_JOB_CONTROL_PAUSE
);
1874 test_SetJob(tctx
, p
, handle
, info
[j
].info1
.job_id
, SPOOLSS_JOB_CONTROL_RESUME
);
1879 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumJobs failed");
1885 static bool test_DoPrintTest(struct torture_context
*tctx
,
1886 struct dcerpc_pipe
*p
,
1887 struct policy_handle
*handle
)
1891 struct spoolss_StartDocPrinter s
;
1892 struct spoolss_DocumentInfo1 info1
;
1893 struct spoolss_StartPagePrinter sp
;
1894 struct spoolss_WritePrinter w
;
1895 struct spoolss_EndPagePrinter ep
;
1896 struct spoolss_EndDocPrinter e
;
1899 uint32_t num_written
;
1901 torture_comment(tctx
, "Testing StartDocPrinter\n");
1903 s
.in
.handle
= handle
;
1905 s
.in
.info
.info1
= &info1
;
1906 s
.out
.job_id
= &job_id
;
1907 info1
.document_name
= "TorturePrintJob";
1908 info1
.output_file
= NULL
;
1909 info1
.datatype
= "RAW";
1911 status
= dcerpc_spoolss_StartDocPrinter(p
, tctx
, &s
);
1912 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_StartDocPrinter failed");
1913 torture_assert_werr_ok(tctx
, s
.out
.result
, "StartDocPrinter failed");
1915 for (i
=1; i
< 4; i
++) {
1916 torture_comment(tctx
, "Testing StartPagePrinter: Page[%d]\n", i
);
1918 sp
.in
.handle
= handle
;
1920 status
= dcerpc_spoolss_StartPagePrinter(p
, tctx
, &sp
);
1921 torture_assert_ntstatus_ok(tctx
, status
,
1922 "dcerpc_spoolss_StartPagePrinter failed");
1923 torture_assert_werr_ok(tctx
, sp
.out
.result
, "StartPagePrinter failed");
1925 torture_comment(tctx
, "Testing WritePrinter: Page[%d]\n", i
);
1927 w
.in
.handle
= handle
;
1928 w
.in
.data
= data_blob_string_const(talloc_asprintf(tctx
,"TortureTestPage: %d\nData\n",i
));
1929 w
.out
.num_written
= &num_written
;
1931 status
= dcerpc_spoolss_WritePrinter(p
, tctx
, &w
);
1932 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_WritePrinter failed");
1933 torture_assert_werr_ok(tctx
, w
.out
.result
, "WritePrinter failed");
1935 torture_comment(tctx
, "Testing EndPagePrinter: Page[%d]\n", i
);
1937 ep
.in
.handle
= handle
;
1939 status
= dcerpc_spoolss_EndPagePrinter(p
, tctx
, &ep
);
1940 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndPagePrinter failed");
1941 torture_assert_werr_ok(tctx
, ep
.out
.result
, "EndPagePrinter failed");
1944 torture_comment(tctx
, "Testing EndDocPrinter\n");
1946 e
.in
.handle
= handle
;
1948 status
= dcerpc_spoolss_EndDocPrinter(p
, tctx
, &e
);
1949 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndDocPrinter failed");
1950 torture_assert_werr_ok(tctx
, e
.out
.result
, "EndDocPrinter failed");
1952 ret
&= test_AddJob(tctx
, p
, handle
);
1953 ret
&= test_EnumJobs(tctx
, p
, handle
);
1955 ret
&= test_SetJob(tctx
, p
, handle
, job_id
, SPOOLSS_JOB_CONTROL_DELETE
);
1960 static bool test_PausePrinter(struct torture_context
*tctx
,
1961 struct dcerpc_pipe
*p
,
1962 struct policy_handle
*handle
)
1965 struct spoolss_SetPrinter r
;
1966 struct spoolss_SetPrinterInfoCtr info_ctr
;
1967 struct spoolss_DevmodeContainer devmode_ctr
;
1968 struct sec_desc_buf secdesc_ctr
;
1971 info_ctr
.info
.info0
= NULL
;
1973 ZERO_STRUCT(devmode_ctr
);
1974 ZERO_STRUCT(secdesc_ctr
);
1976 r
.in
.handle
= handle
;
1977 r
.in
.info_ctr
= &info_ctr
;
1978 r
.in
.devmode_ctr
= &devmode_ctr
;
1979 r
.in
.secdesc_ctr
= &secdesc_ctr
;
1980 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
1982 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1984 status
= dcerpc_spoolss_SetPrinter(p
, tctx
, &r
);
1986 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
1988 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
1993 static bool test_ResumePrinter(struct torture_context
*tctx
,
1994 struct dcerpc_pipe
*p
,
1995 struct policy_handle
*handle
)
1998 struct spoolss_SetPrinter r
;
1999 struct spoolss_SetPrinterInfoCtr info_ctr
;
2000 struct spoolss_DevmodeContainer devmode_ctr
;
2001 struct sec_desc_buf secdesc_ctr
;
2004 info_ctr
.info
.info0
= NULL
;
2006 ZERO_STRUCT(devmode_ctr
);
2007 ZERO_STRUCT(secdesc_ctr
);
2009 r
.in
.handle
= handle
;
2010 r
.in
.info_ctr
= &info_ctr
;
2011 r
.in
.devmode_ctr
= &devmode_ctr
;
2012 r
.in
.secdesc_ctr
= &secdesc_ctr
;
2013 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
2015 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2017 status
= dcerpc_spoolss_SetPrinter(p
, tctx
, &r
);
2019 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
2021 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
2026 static bool test_GetPrinterData(struct torture_context
*tctx
,
2027 struct dcerpc_pipe
*p
,
2028 struct policy_handle
*handle
,
2029 const char *value_name
)
2032 struct spoolss_GetPrinterData r
;
2034 enum winreg_Type type
;
2035 union spoolss_PrinterData data
;
2037 r
.in
.handle
= handle
;
2038 r
.in
.value_name
= value_name
;
2040 r
.out
.needed
= &needed
;
2044 torture_comment(tctx
, "Testing GetPrinterData\n");
2046 status
= dcerpc_spoolss_GetPrinterData(p
, tctx
, &r
);
2047 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
2049 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
2050 r
.in
.offered
= needed
;
2052 status
= dcerpc_spoolss_GetPrinterData(p
, tctx
, &r
);
2053 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
2055 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrinterData failed");
2061 static bool test_GetPrinterDataEx(struct torture_context
*tctx
,
2062 struct dcerpc_pipe
*p
,
2063 struct policy_handle
*handle
,
2064 const char *key_name
,
2065 const char *value_name
)
2068 struct spoolss_GetPrinterDataEx r
;
2069 enum winreg_Type type
;
2072 r
.in
.handle
= handle
;
2073 r
.in
.key_name
= key_name
;
2074 r
.in
.value_name
= value_name
;
2077 r
.out
.needed
= &needed
;
2078 r
.out
.buffer
= NULL
;
2080 torture_comment(tctx
, "Testing GetPrinterDataEx\n");
2082 status
= dcerpc_spoolss_GetPrinterDataEx(p
, tctx
, &r
);
2083 if (!NT_STATUS_IS_OK(status
)) {
2084 if (NT_STATUS_EQUAL(status
,NT_STATUS_NET_WRITE_FAULT
) &&
2085 p
->last_fault_code
== DCERPC_FAULT_OP_RNG_ERROR
) {
2086 torture_skip(tctx
, "GetPrinterDataEx not supported by server\n");
2088 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
2091 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
2092 r
.in
.offered
= needed
;
2093 r
.out
.buffer
= talloc_array(tctx
, uint8_t, needed
);
2095 status
= dcerpc_spoolss_GetPrinterDataEx(p
, tctx
, &r
);
2096 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
2098 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrinterDataEx failed");
2104 static bool test_EnumPrinterData(struct torture_context
*tctx
, struct dcerpc_pipe
*p
,
2105 struct policy_handle
*handle
)
2108 struct spoolss_EnumPrinterData r
;
2111 r
.in
.handle
= handle
;
2112 r
.in
.enum_index
= 0;
2115 uint32_t value_size
= 0;
2116 uint32_t data_size
= 0;
2117 enum winreg_Type type
= 0;
2119 r
.in
.value_offered
= value_size
;
2120 r
.out
.value_needed
= &value_size
;
2121 r
.in
.data_offered
= data_size
;
2122 r
.out
.data_needed
= &data_size
;
2125 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, 0);
2127 torture_comment(tctx
, "Testing EnumPrinterData\n");
2129 status
= dcerpc_spoolss_EnumPrinterData(p
, tctx
, &r
);
2131 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterData failed");
2133 r
.in
.value_offered
= value_size
;
2134 r
.out
.value_name
= talloc_zero_array(tctx
, const char, value_size
);
2135 r
.in
.data_offered
= data_size
;
2136 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, data_size
);
2138 status
= dcerpc_spoolss_EnumPrinterData(p
, tctx
, &r
);
2140 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterData failed");
2142 torture_assert(tctx
, test_GetPrinterData(tctx
, p
, handle
, r
.out
.value_name
),
2143 talloc_asprintf(tctx
, "failed to call GetPrinterData for %s\n", r
.out
.value_name
));
2145 torture_assert(tctx
, test_GetPrinterDataEx(tctx
, p
, handle
, "PrinterDriverData", r
.out
.value_name
),
2146 talloc_asprintf(tctx
, "failed to call GetPrinterDataEx on PrinterDriverData for %s\n", r
.out
.value_name
));
2150 } while (W_ERROR_IS_OK(r
.out
.result
));
2155 static bool test_EnumPrinterDataEx(struct torture_context
*tctx
,
2156 struct dcerpc_pipe
*p
,
2157 struct policy_handle
*handle
)
2160 struct spoolss_EnumPrinterDataEx r
;
2161 struct spoolss_PrinterEnumValues
*info
;
2165 r
.in
.handle
= handle
;
2166 r
.in
.key_name
= "PrinterDriverData";
2168 r
.out
.needed
= &needed
;
2169 r
.out
.count
= &count
;
2172 torture_comment(tctx
, "Testing EnumPrinterDataEx\n");
2174 status
= dcerpc_spoolss_EnumPrinterDataEx(p
, tctx
, &r
);
2175 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterDataEx failed");
2177 r
.in
.offered
= needed
;
2179 status
= dcerpc_spoolss_EnumPrinterDataEx(p
, tctx
, &r
);
2181 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterDataEx failed");
2187 static bool test_DeletePrinterData(struct torture_context
*tctx
,
2188 struct dcerpc_pipe
*p
,
2189 struct policy_handle
*handle
,
2190 const char *value_name
)
2193 struct spoolss_DeletePrinterData r
;
2195 r
.in
.handle
= handle
;
2196 r
.in
.value_name
= value_name
;
2198 torture_comment(tctx
, "Testing DeletePrinterData\n");
2200 status
= dcerpc_spoolss_DeletePrinterData(p
, tctx
, &r
);
2202 torture_assert_ntstatus_ok(tctx
, status
, "DeletePrinterData failed");
2207 static bool test_SetPrinterData(struct torture_context
*tctx
,
2208 struct dcerpc_pipe
*p
,
2209 struct policy_handle
*handle
)
2212 struct spoolss_SetPrinterData r
;
2213 const char *value_name
= "spottyfoot";
2215 r
.in
.handle
= handle
;
2216 r
.in
.value_name
= value_name
;
2218 r
.in
.data
.string
= "dog";
2220 torture_comment(tctx
, "Testing SetPrinterData\n");
2222 status
= dcerpc_spoolss_SetPrinterData(p
, tctx
, &r
);
2224 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinterData failed");
2226 if (!test_GetPrinterData(tctx
, p
, handle
, value_name
)) {
2230 if (!test_DeletePrinterData(tctx
, p
, handle
, value_name
)) {
2237 static bool test_SecondaryClosePrinter(struct torture_context
*tctx
,
2238 struct dcerpc_pipe
*p
,
2239 struct policy_handle
*handle
)
2242 struct dcerpc_binding
*b
;
2243 struct dcerpc_pipe
*p2
;
2244 struct spoolss_ClosePrinter cp
;
2246 /* only makes sense on SMB */
2247 if (p
->conn
->transport
.transport
!= NCACN_NP
) {
2251 torture_comment(tctx
, "testing close on secondary pipe\n");
2253 status
= dcerpc_parse_binding(tctx
, p
->conn
->binding_string
, &b
);
2254 torture_assert_ntstatus_ok(tctx
, status
, "Failed to parse dcerpc binding");
2256 status
= dcerpc_secondary_connection(p
, &p2
, b
);
2257 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create secondary connection");
2259 status
= dcerpc_bind_auth_none(p2
, &ndr_table_spoolss
);
2260 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create bind on secondary connection");
2262 cp
.in
.handle
= handle
;
2263 cp
.out
.handle
= handle
;
2265 status
= dcerpc_spoolss_ClosePrinter(p2
, tctx
, &cp
);
2266 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_NET_WRITE_FAULT
,
2267 "ERROR: Allowed close on secondary connection");
2269 torture_assert_int_equal(tctx
, p2
->last_fault_code
, DCERPC_FAULT_CONTEXT_MISMATCH
,
2270 "Unexpected fault code");
2277 static bool test_OpenPrinter_badname(struct torture_context
*tctx
,
2278 struct dcerpc_pipe
*p
, const char *name
)
2281 struct spoolss_OpenPrinter op
;
2282 struct spoolss_OpenPrinterEx opEx
;
2283 struct policy_handle handle
;
2286 op
.in
.printername
= name
;
2287 op
.in
.datatype
= NULL
;
2288 op
.in
.devmode_ctr
.devmode
= NULL
;
2289 op
.in
.access_mask
= 0;
2290 op
.out
.handle
= &handle
;
2292 torture_comment(tctx
, "\nTesting OpenPrinter(%s) with bad name\n", op
.in
.printername
);
2294 status
= dcerpc_spoolss_OpenPrinter(p
, tctx
, &op
);
2295 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
2296 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME
,op
.out
.result
)) {
2297 torture_comment(tctx
, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
2298 name
, win_errstr(op
.out
.result
));
2301 if (W_ERROR_IS_OK(op
.out
.result
)) {
2302 ret
&=test_ClosePrinter(tctx
, p
, &handle
);
2305 opEx
.in
.printername
= name
;
2306 opEx
.in
.datatype
= NULL
;
2307 opEx
.in
.devmode_ctr
.devmode
= NULL
;
2308 opEx
.in
.access_mask
= 0;
2310 opEx
.in
.userlevel
.level1
= NULL
;
2311 opEx
.out
.handle
= &handle
;
2313 torture_comment(tctx
, "Testing OpenPrinterEx(%s) with bad name\n", opEx
.in
.printername
);
2315 status
= dcerpc_spoolss_OpenPrinterEx(p
, tctx
, &opEx
);
2316 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinterEx failed");
2317 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM
,opEx
.out
.result
)) {
2318 torture_comment(tctx
, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
2319 name
, win_errstr(opEx
.out
.result
));
2322 if (W_ERROR_IS_OK(opEx
.out
.result
)) {
2323 ret
&=test_ClosePrinter(tctx
, p
, &handle
);
2329 static bool test_OpenPrinter(struct torture_context
*tctx
,
2330 struct dcerpc_pipe
*p
,
2334 struct spoolss_OpenPrinter r
;
2335 struct policy_handle handle
;
2338 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s\\%s", dcerpc_server_name(p
), name
);
2339 r
.in
.datatype
= NULL
;
2340 r
.in
.devmode_ctr
.devmode
= NULL
;
2341 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
2342 r
.out
.handle
= &handle
;
2344 torture_comment(tctx
, "Testing OpenPrinter(%s)\n", r
.in
.printername
);
2346 status
= dcerpc_spoolss_OpenPrinter(p
, tctx
, &r
);
2348 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
2350 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenPrinter failed");
2352 if (!test_GetPrinter(tctx
, p
, &handle
)) {
2356 if (!torture_setting_bool(tctx
, "samba3", false)) {
2357 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
2362 if (!test_ClosePrinter(tctx
, p
, &handle
)) {
2369 static bool call_OpenPrinterEx(struct torture_context
*tctx
,
2370 struct dcerpc_pipe
*p
,
2371 const char *name
, struct policy_handle
*handle
)
2373 struct spoolss_OpenPrinterEx r
;
2374 struct spoolss_UserLevel1 userlevel1
;
2377 if (name
&& name
[0]) {
2378 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s\\%s",
2379 dcerpc_server_name(p
), name
);
2381 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s",
2382 dcerpc_server_name(p
));
2385 r
.in
.datatype
= NULL
;
2386 r
.in
.devmode_ctr
.devmode
= NULL
;
2387 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
2389 r
.in
.userlevel
.level1
= &userlevel1
;
2390 r
.out
.handle
= handle
;
2392 userlevel1
.size
= 1234;
2393 userlevel1
.client
= "hello";
2394 userlevel1
.user
= "spottyfoot!";
2395 userlevel1
.build
= 1;
2396 userlevel1
.major
= 2;
2397 userlevel1
.minor
= 3;
2398 userlevel1
.processor
= 4;
2400 torture_comment(tctx
, "Testing OpenPrinterEx(%s)\n", r
.in
.printername
);
2402 status
= dcerpc_spoolss_OpenPrinterEx(p
, tctx
, &r
);
2404 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinterEx failed");
2406 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenPrinterEx failed");
2411 static bool test_OpenPrinterEx(struct torture_context
*tctx
,
2412 struct dcerpc_pipe
*p
,
2415 struct policy_handle handle
;
2418 if (!call_OpenPrinterEx(tctx
, p
, name
, &handle
)) {
2422 if (!test_GetPrinter(tctx
, p
, &handle
)) {
2426 if (!test_EnumForms(tctx
, p
, &handle
, false)) {
2430 if (!test_AddForm(tctx
, p
, &handle
, false)) {
2434 if (!test_EnumPrinterData(tctx
, p
, &handle
)) {
2438 if (!test_EnumPrinterDataEx(tctx
, p
, &handle
)) {
2442 if (!test_printer_keys(tctx
, p
, &handle
)) {
2446 if (!test_PausePrinter(tctx
, p
, &handle
)) {
2450 if (!test_DoPrintTest(tctx
, p
, &handle
)) {
2454 if (!test_ResumePrinter(tctx
, p
, &handle
)) {
2458 if (!test_SetPrinterData(tctx
, p
, &handle
)) {
2462 if (!torture_setting_bool(tctx
, "samba3", false)) {
2463 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
2468 if (!test_ClosePrinter(tctx
, p
, &handle
)) {
2475 static bool test_EnumPrinters_old(struct torture_context
*tctx
, struct dcerpc_pipe
*p
)
2477 struct spoolss_EnumPrinters r
;
2479 uint16_t levels
[] = {1, 2, 4, 5};
2483 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
2484 union spoolss_PrinterInfo
*info
;
2489 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
2491 r
.in
.level
= levels
[i
];
2494 r
.out
.needed
= &needed
;
2495 r
.out
.count
= &count
;
2498 torture_comment(tctx
, "Testing EnumPrinters level %u\n", r
.in
.level
);
2500 status
= dcerpc_spoolss_EnumPrinters(p
, tctx
, &r
);
2501 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
2503 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2504 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2505 data_blob_clear(&blob
);
2506 r
.in
.buffer
= &blob
;
2507 r
.in
.offered
= needed
;
2508 status
= dcerpc_spoolss_EnumPrinters(p
, tctx
, &r
);
2511 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
2513 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
2516 torture_comment(tctx
, "No printers returned\n");
2520 for (j
=0;j
<count
;j
++) {
2521 if (r
.in
.level
== 1) {
2522 char *unc
= talloc_strdup(tctx
, info
[j
].info1
.name
);
2525 if (unc
[0] == '\\' && unc
[1] == '\\') {
2528 slash
= strchr(unc
, '\\');
2533 if (!test_OpenPrinter(tctx
, p
, name
)) {
2536 if (!test_OpenPrinterEx(tctx
, p
, name
)) {
2546 static bool test_GetPrinterDriver(struct torture_context
*tctx
,
2547 struct dcerpc_pipe
*p
,
2548 struct policy_handle
*handle
,
2549 const char *driver_name
)
2551 struct spoolss_GetPrinterDriver r
;
2554 r
.in
.handle
= handle
;
2555 r
.in
.architecture
= "W32X86";
2559 r
.out
.needed
= &needed
;
2561 torture_comment(tctx
, "Testing GetPrinterDriver level %d\n", r
.in
.level
);
2563 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver(p
, tctx
, &r
),
2564 "failed to call GetPrinterDriver");
2565 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2566 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2567 data_blob_clear(&blob
);
2568 r
.in
.buffer
= &blob
;
2569 r
.in
.offered
= needed
;
2570 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver(p
, tctx
, &r
),
2571 "failed to call GetPrinterDriver");
2574 torture_assert_werr_ok(tctx
, r
.out
.result
,
2575 "failed to call GetPrinterDriver");
2580 static bool test_GetPrinterDriver2(struct torture_context
*tctx
,
2581 struct dcerpc_pipe
*p
,
2582 struct policy_handle
*handle
,
2583 const char *driver_name
)
2585 struct spoolss_GetPrinterDriver2 r
;
2587 uint32_t server_major_version
;
2588 uint32_t server_minor_version
;
2590 r
.in
.handle
= handle
;
2591 r
.in
.architecture
= "W32X86";
2595 r
.in
.client_major_version
= 0;
2596 r
.in
.client_minor_version
= 0;
2597 r
.out
.needed
= &needed
;
2598 r
.out
.server_major_version
= &server_major_version
;
2599 r
.out
.server_minor_version
= &server_minor_version
;
2601 torture_comment(tctx
, "Testing GetPrinterDriver2 level %d\n", r
.in
.level
);
2603 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver2(p
, tctx
, &r
),
2604 "failed to call GetPrinterDriver2");
2605 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2606 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2607 data_blob_clear(&blob
);
2608 r
.in
.buffer
= &blob
;
2609 r
.in
.offered
= needed
;
2610 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver2(p
, tctx
, &r
),
2611 "failed to call GetPrinterDriver2");
2614 torture_assert_werr_ok(tctx
, r
.out
.result
,
2615 "failed to call GetPrinterDriver2");
2620 static bool test_EnumPrinterDrivers_old(struct torture_context
*tctx
,
2621 struct dcerpc_pipe
*p
)
2623 struct spoolss_EnumPrinterDrivers r
;
2625 uint16_t levels
[] = {1, 2, 3, 4, 5, 6};
2628 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
2632 union spoolss_DriverInfo
*info
;
2634 r
.in
.server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
2635 r
.in
.environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
2636 r
.in
.level
= levels
[i
];
2639 r
.out
.needed
= &needed
;
2640 r
.out
.count
= &count
;
2643 torture_comment(tctx
, "Testing EnumPrinterDrivers level %u\n", r
.in
.level
);
2645 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, tctx
, &r
);
2647 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterDrivers failed");
2649 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2650 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2651 data_blob_clear(&blob
);
2652 r
.in
.buffer
= &blob
;
2653 r
.in
.offered
= needed
;
2654 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, tctx
, &r
);
2657 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterDrivers failed");
2659 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDrivers failed");
2662 torture_comment(tctx
, "No printer drivers returned\n");
2670 static bool test_DeletePrinter(struct torture_context
*tctx
,
2671 struct dcerpc_pipe
*p
,
2672 struct policy_handle
*handle
)
2674 struct spoolss_DeletePrinter r
;
2676 torture_comment(tctx
, "Testing DeletePrinter\n");
2678 r
.in
.handle
= handle
;
2680 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_DeletePrinter(p
, tctx
, &r
),
2681 "failed to delete printer");
2682 torture_assert_werr_ok(tctx
, r
.out
.result
,
2683 "failed to delete printer");
2688 static bool test_EnumPrinters_findname(struct torture_context
*tctx
,
2689 struct dcerpc_pipe
*p
,
2695 struct spoolss_EnumPrinters e
;
2697 union spoolss_PrinterInfo
*info
;
2708 e
.out
.count
= &count
;
2710 e
.out
.needed
= &needed
;
2712 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters(p
, tctx
, &e
),
2713 "failed to enum printers");
2715 if (W_ERROR_EQUAL(e
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2716 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2717 data_blob_clear(&blob
);
2718 e
.in
.buffer
= &blob
;
2719 e
.in
.offered
= needed
;
2721 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters(p
, tctx
, &e
),
2722 "failed to enum printers");
2725 torture_assert_werr_ok(tctx
, e
.out
.result
,
2726 "failed to enum printers");
2728 for (i
=0; i
< count
; i
++) {
2730 const char *current
= NULL
;
2734 current
= info
[i
].info1
.name
;
2738 if (strequal(current
, name
)) {
2747 static bool test_AddPrinter_wellknown(struct torture_context
*tctx
,
2748 struct dcerpc_pipe
*p
,
2749 const char *printername
,
2753 struct spoolss_AddPrinter r
;
2754 struct spoolss_AddPrinterEx rex
;
2755 struct spoolss_SetPrinterInfoCtr info_ctr
;
2756 struct spoolss_SetPrinterInfo1 info1
;
2757 struct spoolss_DevmodeContainer devmode_ctr
;
2758 struct sec_desc_buf secdesc_ctr
;
2759 struct spoolss_UserLevelCtr userlevel_ctr
;
2760 struct policy_handle handle
;
2763 ZERO_STRUCT(devmode_ctr
);
2764 ZERO_STRUCT(secdesc_ctr
);
2765 ZERO_STRUCT(userlevel_ctr
);
2768 torture_comment(tctx
, "Testing AddPrinter%s level 1\n", ex
? "Ex":"");
2770 /* try to add printer to wellknown printer list (level 1) */
2772 userlevel_ctr
.level
= 1;
2774 info_ctr
.info
.info1
= &info1
;
2777 rex
.in
.server
= NULL
;
2778 rex
.in
.info_ctr
= &info_ctr
;
2779 rex
.in
.devmode_ctr
= &devmode_ctr
;
2780 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
2781 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
2782 rex
.out
.handle
= &handle
;
2785 r
.in
.info_ctr
= &info_ctr
;
2786 r
.in
.devmode_ctr
= &devmode_ctr
;
2787 r
.in
.secdesc_ctr
= &secdesc_ctr
;
2788 r
.out
.handle
= &handle
;
2790 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
2791 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
2792 "failed to add printer");
2793 result
= ex
? rex
.out
.result
: r
.out
.result
;
2794 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
2795 "unexpected result code");
2797 info1
.name
= printername
;
2798 info1
.flags
= PRINTER_ATTRIBUTE_SHARED
;
2800 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
2801 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
2802 "failed to add printer");
2803 result
= ex
? rex
.out
.result
: r
.out
.result
;
2804 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
2805 "unexpected result code");
2807 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
2808 better do a real check to see the printer is really there */
2810 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, p
,
2811 PRINTER_ENUM_NETWORK
, 1,
2814 "failed to enum printers");
2816 torture_assert(tctx
, found
, "failed to find newly added printer");
2820 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
2821 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
2822 "failed to add printer");
2823 result
= ex
? rex
.out
.result
: r
.out
.result
;
2824 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
2825 "unexpected result code");
2827 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
2828 better do a real check to see the printer has really been removed
2829 from the well known printer list */
2833 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, p
,
2834 PRINTER_ENUM_NETWORK
, 1,
2837 "failed to enum printers");
2839 torture_assert(tctx
, !found
, "printer still in well known printer list");
2844 static bool test_AddPrinter_normal(struct torture_context
*tctx
,
2845 struct dcerpc_pipe
*p
,
2846 struct policy_handle
*handle_p
,
2847 const char *printername
,
2848 const char *drivername
,
2849 const char *portname
,
2853 struct spoolss_AddPrinter r
;
2854 struct spoolss_AddPrinterEx rex
;
2855 struct spoolss_SetPrinterInfoCtr info_ctr
;
2856 struct spoolss_SetPrinterInfo2 info2
;
2857 struct spoolss_DevmodeContainer devmode_ctr
;
2858 struct sec_desc_buf secdesc_ctr
;
2859 struct spoolss_UserLevelCtr userlevel_ctr
;
2860 struct policy_handle handle
;
2863 ZERO_STRUCT(devmode_ctr
);
2864 ZERO_STRUCT(secdesc_ctr
);
2865 ZERO_STRUCT(userlevel_ctr
);
2867 torture_comment(tctx
, "Testing AddPrinter%s level 2\n", ex
? "Ex":"");
2869 userlevel_ctr
.level
= 1;
2871 rex
.in
.server
= NULL
;
2872 rex
.in
.info_ctr
= &info_ctr
;
2873 rex
.in
.devmode_ctr
= &devmode_ctr
;
2874 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
2875 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
2876 rex
.out
.handle
= &handle
;
2879 r
.in
.info_ctr
= &info_ctr
;
2880 r
.in
.devmode_ctr
= &devmode_ctr
;
2881 r
.in
.secdesc_ctr
= &secdesc_ctr
;
2882 r
.out
.handle
= &handle
;
2886 /* try to add printer to printer list (level 2) */
2890 info_ctr
.info
.info2
= &info2
;
2893 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
2894 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
2895 "failed to add printer");
2896 result
= ex
? rex
.out
.result
: r
.out
.result
;
2897 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
2898 "unexpected result code");
2900 info2
.printername
= printername
;
2902 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
2903 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
2904 "failed to add printer");
2905 result
= ex
? rex
.out
.result
: r
.out
.result
;
2907 if (W_ERROR_EQUAL(result
, WERR_PRINTER_ALREADY_EXISTS
)) {
2908 struct policy_handle printer_handle
;
2910 torture_assert(tctx
, call_OpenPrinterEx(tctx
, p
, printername
, &printer_handle
),
2911 "failed to open printer handle");
2913 torture_assert(tctx
, test_DeletePrinter(tctx
, p
, &printer_handle
),
2914 "failed to delete printer");
2916 torture_assert(tctx
, test_ClosePrinter(tctx
, p
, &printer_handle
),
2917 "failed to close server handle");
2922 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PORT
,
2923 "unexpected result code");
2925 info2
.portname
= portname
;
2927 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
2928 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
2929 "failed to add printer");
2930 result
= ex
? rex
.out
.result
: r
.out
.result
;
2931 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTER_DRIVER
,
2932 "unexpected result code");
2934 info2
.drivername
= drivername
;
2936 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
2937 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
2938 "failed to add printer");
2939 result
= ex
? rex
.out
.result
: r
.out
.result
;
2940 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTPROCESSOR
,
2941 "unexpected result code");
2943 info2
.printprocessor
= "winprint";
2945 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
2946 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
2947 "failed to add printer");
2948 result
= ex
? rex
.out
.result
: r
.out
.result
;
2949 torture_assert_werr_ok(tctx
, result
,
2950 "failed to add printer");
2954 /* we are paranoid, really check if the printer is there now */
2956 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, p
,
2957 PRINTER_ENUM_LOCAL
, 1,
2960 "failed to enum printers");
2961 torture_assert(tctx
, found
, "failed to find newly added printer");
2963 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
2964 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
2965 "failed to add printer");
2966 result
= ex
? rex
.out
.result
: r
.out
.result
;
2967 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
2968 "unexpected result code");
2973 static bool test_AddPrinterEx(struct torture_context
*tctx
,
2974 struct dcerpc_pipe
*p
,
2975 struct policy_handle
*handle_p
,
2976 const char *printername
,
2977 const char *drivername
,
2978 const char *portname
)
2982 if (!torture_setting_bool(tctx
, "samba3", false)) {
2983 if (!test_AddPrinter_wellknown(tctx
, p
, TORTURE_WELLKNOWN_PRINTER_EX
, true)) {
2984 torture_comment(tctx
, "failed to add printer to well known list\n");
2989 if (!test_AddPrinter_normal(tctx
, p
, handle_p
,
2990 printername
, drivername
, portname
,
2992 torture_comment(tctx
, "failed to add printer to printer list\n");
2999 static bool test_AddPrinter(struct torture_context
*tctx
,
3000 struct dcerpc_pipe
*p
,
3001 struct policy_handle
*handle_p
,
3002 const char *printername
,
3003 const char *drivername
,
3004 const char *portname
)
3008 if (!torture_setting_bool(tctx
, "samba3", false)) {
3009 if (!test_AddPrinter_wellknown(tctx
, p
, TORTURE_WELLKNOWN_PRINTER
, false)) {
3010 torture_comment(tctx
, "failed to add printer to well known list\n");
3015 if (!test_AddPrinter_normal(tctx
, p
, handle_p
,
3016 printername
, drivername
, portname
,
3018 torture_comment(tctx
, "failed to add printer to printer list\n");
3025 static bool test_printer_info(struct torture_context
*tctx
,
3026 struct dcerpc_pipe
*p
,
3027 struct policy_handle
*handle
)
3031 if (!test_PrinterInfo(tctx
, p
, handle
)) {
3035 if (!test_SetPrinter_errors(tctx
, p
, handle
)) {
3042 bool test_printer_keys(struct torture_context
*tctx
,
3043 struct dcerpc_pipe
*p
,
3044 struct policy_handle
*handle
)
3046 const char **key_array
= NULL
;
3050 struct spoolss_EnumPrinterKey r
;
3052 struct spoolss_StringArray2 key_buffer
;
3054 r
.in
.handle
= handle
;
3057 r
.out
.key_buffer
= &key_buffer
;
3058 r
.out
.needed
= &needed
;
3060 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterKey(p
, tctx
, &r
),
3061 "failed to call EnumPrinterKey");
3062 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
3063 r
.in
.offered
= needed
;
3064 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterKey(p
, tctx
, &r
),
3065 "failed to call EnumPrinterKey");
3067 torture_assert_werr_ok(tctx
, r
.out
.result
,
3068 "failed to call EnumPrinterKey");
3070 key_array
= key_buffer
.string
;
3073 for (i
=0; key_array
[i
]; i
++) {
3074 struct spoolss_EnumPrinterDataEx r
;
3076 struct spoolss_PrinterEnumValues
*info
;
3079 r
.in
.handle
= handle
;
3080 r
.in
.key_name
= key_array
[i
];
3082 r
.out
.count
= &count
;
3084 r
.out
.needed
= &needed
;
3086 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterDataEx(p
, tctx
, &r
),
3087 "failed to call EnumPrinterDataEx");
3088 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
3089 r
.in
.offered
= needed
;
3090 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterDataEx(p
, tctx
, &r
),
3091 "failed to call EnumPrinterDataEx");
3093 torture_assert_werr_ok(tctx
, r
.out
.result
,
3094 "failed to call EnumPrinterDataEx");
3100 static bool test_printer(struct torture_context
*tctx
,
3101 struct dcerpc_pipe
*p
)
3104 struct policy_handle handle
[2];
3106 const char *drivername
= "Microsoft XPS Document Writer";
3107 const char *portname
= "LPT1:";
3109 /* test printer created via AddPrinter */
3111 if (!test_AddPrinter(tctx
, p
, &handle
[0], TORTURE_PRINTER
, drivername
, portname
)) {
3115 if (!test_printer_info(tctx
, p
, &handle
[0])) {
3119 if (!test_printer_keys(tctx
, p
, &handle
[0])) {
3123 if (!test_DeletePrinter(tctx
, p
, &handle
[0])) {
3127 if (!test_EnumPrinters_findname(tctx
, p
, PRINTER_ENUM_LOCAL
, 1,
3128 TORTURE_PRINTER
, &found
)) {
3132 torture_assert(tctx
, !found
, "deleted printer still there");
3134 /* test printer created via AddPrinterEx */
3136 if (!test_AddPrinterEx(tctx
, p
, &handle
[1], TORTURE_PRINTER_EX
, drivername
, portname
)) {
3140 if (!test_printer_info(tctx
, p
, &handle
[1])) {
3144 if (!test_printer_keys(tctx
, p
, &handle
[1])) {
3148 if (!test_DeletePrinter(tctx
, p
, &handle
[1])) {
3152 if (!test_EnumPrinters_findname(tctx
, p
, PRINTER_ENUM_LOCAL
, 1,
3153 TORTURE_PRINTER_EX
, &found
)) {
3157 torture_assert(tctx
, !found
, "deleted printer still there");
3162 bool torture_rpc_spoolss(struct torture_context
*torture
)
3165 struct dcerpc_pipe
*p
;
3167 struct test_spoolss_context
*ctx
;
3169 status
= torture_rpc_connection(torture
, &p
, &ndr_table_spoolss
);
3170 if (!NT_STATUS_IS_OK(status
)) {
3174 ctx
= talloc_zero(torture
, struct test_spoolss_context
);
3176 ret
&= test_OpenPrinter_server(torture
, p
, &ctx
->server_handle
);
3178 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "W3SvcInstalled");
3179 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "BeepEnabled");
3180 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "EventLog");
3181 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "NetPopup");
3182 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "NetPopupToComputer");
3183 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "MajorVersion");
3184 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "MinorVersion");
3185 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "DefaultSpoolDirectory");
3186 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "Architecture");
3187 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "DsPresent");
3188 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "OSVersion");
3189 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "OSVersionEx");
3190 ret
&= test_GetPrinterData(torture
, p
, &ctx
->server_handle
, "DNSMachineName");
3191 ret
&= test_EnumForms(torture
, p
, &ctx
->server_handle
, true);
3192 ret
&= test_AddForm(torture
, p
, &ctx
->server_handle
, true);
3193 ret
&= test_EnumPorts(torture
, p
, ctx
);
3194 ret
&= test_GetPrinterDriverDirectory(torture
, p
, ctx
);
3195 ret
&= test_GetPrintProcessorDirectory(torture
, p
, ctx
);
3196 ret
&= test_EnumPrinterDrivers(torture
, p
, ctx
);
3197 ret
&= test_EnumMonitors(torture
, p
, ctx
);
3198 ret
&= test_EnumPrintProcessors(torture
, p
, ctx
);
3199 ret
&= test_EnumPrintProcDataTypes(torture
, p
, ctx
);
3200 ret
&= test_EnumPrinters(torture
, p
, ctx
);
3201 ret
&= test_OpenPrinter_badname(torture
, p
, "__INVALID_PRINTER__");
3202 ret
&= test_OpenPrinter_badname(torture
, p
, "\\\\__INVALID_HOST__");
3203 ret
&= test_OpenPrinter_badname(torture
, p
, "");
3204 ret
&= test_OpenPrinter_badname(torture
, p
, "\\\\\\");
3205 ret
&= test_OpenPrinter_badname(torture
, p
, "\\\\\\__INVALID_PRINTER__");
3206 ret
&= test_OpenPrinter_badname(torture
, p
, talloc_asprintf(torture
, "\\\\%s\\", dcerpc_server_name(p
)));
3207 ret
&= test_OpenPrinter_badname(torture
, p
,
3208 talloc_asprintf(torture
, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p
)));
3211 ret
&= test_AddPort(torture
, p
);
3212 ret
&= test_EnumPorts_old(torture
, p
);
3213 ret
&= test_EnumPrinters_old(torture
, p
);
3214 ret
&= test_EnumPrinterDrivers_old(torture
, p
);
3219 struct torture_suite
*torture_rpc_spoolss_printer(TALLOC_CTX
*mem_ctx
)
3221 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "SPOOLSS-PRINTER");
3223 struct torture_rpc_tcase
*tcase
= torture_suite_add_rpc_iface_tcase(suite
,
3224 "printer", &ndr_table_spoolss
);
3226 torture_rpc_tcase_add_test(tcase
, "printer", test_printer
);