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
,
313 const char *architecture
)
316 struct spoolss_EnumPrinterDrivers r
;
317 uint16_t levels
[] = { 1, 2, 3, 4, 5, 6 };
320 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
321 int level
= levels
[i
];
325 union spoolss_DriverInfo
*info
;
327 /* FIXME: gd, come back and fix "" as server, and handle
328 * priority of returned error codes in torture test and samba 3
331 r
.in
.server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
332 r
.in
.environment
= architecture
;
336 r
.out
.needed
= &needed
;
337 r
.out
.count
= &count
;
340 torture_comment(tctx
, "Testing EnumPrinterDrivers level %u (%s)\n", r
.in
.level
, r
.in
.environment
);
342 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, ctx
, &r
);
343 torture_assert_ntstatus_ok(tctx
, status
,
344 "dcerpc_spoolss_EnumPrinterDrivers failed");
345 if (W_ERROR_IS_OK(r
.out
.result
)) {
346 /* TODO: do some more checks here */
349 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
350 blob
= data_blob_talloc(ctx
, NULL
, needed
);
351 data_blob_clear(&blob
);
353 r
.in
.offered
= needed
;
355 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, ctx
, &r
);
356 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinterDrivers failed");
359 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDrivers failed");
361 ctx
->driver_count
[level
] = count
;
362 ctx
->drivers
[level
] = info
;
365 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
366 int level
= levels
[i
];
367 int old_level
= levels
[i
-1];
369 torture_assert_int_equal(tctx
, ctx
->driver_count
[level
], ctx
->driver_count
[old_level
],
370 "EnumPrinterDrivers invalid value");
373 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
374 int level
= levels
[i
];
376 for (j
=0;j
<ctx
->driver_count
[level
];j
++) {
377 union spoolss_DriverInfo
*cur
= &ctx
->drivers
[level
][j
];
378 union spoolss_DriverInfo
*ref
= &ctx
->drivers
[6][j
];
381 COMPARE_STRING(tctx
, cur
->info1
, ref
->info6
, driver_name
);
384 COMPARE_UINT32(tctx
, cur
->info2
, ref
->info6
, version
);
385 COMPARE_STRING(tctx
, cur
->info2
, ref
->info6
, driver_name
);
386 COMPARE_STRING(tctx
, cur
->info2
, ref
->info6
, architecture
);
387 COMPARE_STRING(tctx
, cur
->info2
, ref
->info6
, driver_path
);
388 COMPARE_STRING(tctx
, cur
->info2
, ref
->info6
, data_file
);
389 COMPARE_STRING(tctx
, cur
->info2
, ref
->info6
, config_file
);
392 COMPARE_UINT32(tctx
, cur
->info3
, ref
->info6
, version
);
393 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, driver_name
);
394 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, architecture
);
395 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, driver_path
);
396 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, data_file
);
397 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, config_file
);
398 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, help_file
);
399 COMPARE_STRING_ARRAY(tctx
, cur
->info3
, ref
->info6
, dependent_files
);
400 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, monitor_name
);
401 COMPARE_STRING(tctx
, cur
->info3
, ref
->info6
, default_datatype
);
404 COMPARE_UINT32(tctx
, cur
->info4
, ref
->info6
, version
);
405 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, driver_name
);
406 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, architecture
);
407 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, driver_path
);
408 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, data_file
);
409 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, config_file
);
410 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, help_file
);
411 COMPARE_STRING_ARRAY(tctx
, cur
->info4
, ref
->info6
, dependent_files
);
412 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, monitor_name
);
413 COMPARE_STRING(tctx
, cur
->info4
, ref
->info6
, default_datatype
);
414 COMPARE_STRING_ARRAY(tctx
, cur
->info4
, ref
->info6
, previous_names
);
417 COMPARE_UINT32(tctx
, cur
->info5
, ref
->info6
, version
);
418 COMPARE_STRING(tctx
, cur
->info5
, ref
->info6
, driver_name
);
419 COMPARE_STRING(tctx
, cur
->info5
, ref
->info6
, architecture
);
420 COMPARE_STRING(tctx
, cur
->info5
, ref
->info6
, driver_path
);
421 COMPARE_STRING(tctx
, cur
->info5
, ref
->info6
, data_file
);
422 COMPARE_STRING(tctx
, cur
->info5
, ref
->info6
, config_file
);
423 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_attributes);*/
424 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, config_version);*/
425 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_version); */
428 /* level 6 is our reference, and it makes no sense to compare it to itself */
437 static bool test_EnumMonitors(struct torture_context
*tctx
,
438 struct dcerpc_pipe
*p
,
439 struct test_spoolss_context
*ctx
)
442 struct spoolss_EnumMonitors r
;
443 uint16_t levels
[] = { 1, 2 };
446 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
447 int level
= levels
[i
];
451 union spoolss_MonitorInfo
*info
;
453 r
.in
.servername
= "";
457 r
.out
.needed
= &needed
;
458 r
.out
.count
= &count
;
461 torture_comment(tctx
, "Testing EnumMonitors level %u\n", r
.in
.level
);
463 status
= dcerpc_spoolss_EnumMonitors(p
, ctx
, &r
);
464 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumMonitors failed");
465 if (W_ERROR_IS_OK(r
.out
.result
)) {
466 /* TODO: do some more checks here */
469 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
470 "EnumMonitors failed");
472 blob
= data_blob_talloc(ctx
, NULL
, needed
);
473 data_blob_clear(&blob
);
475 r
.in
.offered
= needed
;
477 status
= dcerpc_spoolss_EnumMonitors(p
, ctx
, &r
);
478 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumMonitors failed");
480 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumMonitors failed");
482 ctx
->monitor_count
[level
] = count
;
483 ctx
->monitors
[level
] = info
;
486 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
487 int level
= levels
[i
];
488 int old_level
= levels
[i
-1];
489 torture_assert_int_equal(tctx
, ctx
->monitor_count
[level
], ctx
->monitor_count
[old_level
],
490 "EnumMonitors invalid value");
493 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
494 int level
= levels
[i
];
495 for (j
=0;j
<ctx
->monitor_count
[level
];j
++) {
496 union spoolss_MonitorInfo
*cur
= &ctx
->monitors
[level
][j
];
497 union spoolss_MonitorInfo
*ref
= &ctx
->monitors
[2][j
];
500 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, monitor_name
);
503 /* level 2 is our reference, and it makes no sense to compare it to itself */
512 static bool test_EnumPrintProcessors(struct torture_context
*tctx
,
513 struct dcerpc_pipe
*p
,
514 struct test_spoolss_context
*ctx
)
517 struct spoolss_EnumPrintProcessors r
;
518 uint16_t levels
[] = { 1 };
521 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
522 int level
= levels
[i
];
526 union spoolss_PrintProcessorInfo
*info
;
528 r
.in
.servername
= "";
529 r
.in
.environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
533 r
.out
.needed
= &needed
;
534 r
.out
.count
= &count
;
537 torture_comment(tctx
, "Testing EnumPrintProcessors level %u\n", r
.in
.level
);
539 status
= dcerpc_spoolss_EnumPrintProcessors(p
, ctx
, &r
);
540 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcessors failed");
541 if (W_ERROR_IS_OK(r
.out
.result
)) {
542 /* TODO: do some more checks here */
545 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
546 "EnumPrintProcessors unexpected return code");
548 blob
= data_blob_talloc(ctx
, NULL
, needed
);
549 data_blob_clear(&blob
);
551 r
.in
.offered
= needed
;
553 status
= dcerpc_spoolss_EnumPrintProcessors(p
, ctx
, &r
);
554 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcessors failed");
556 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrintProcessors failed");
558 ctx
->print_processor_count
[level
] = count
;
559 ctx
->print_processors
[level
] = info
;
562 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
563 int level
= levels
[i
];
564 int old_level
= levels
[i
-1];
565 torture_assert_int_equal(tctx
, ctx
->print_processor_count
[level
], ctx
->print_processor_count
[old_level
],
566 "EnumPrintProcessors failed");
569 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
570 int level
= levels
[i
];
571 for (j
=0;j
<ctx
->print_processor_count
[level
];j
++) {
573 union spoolss_PrintProcessorInfo
*cur
= &ctx
->print_processors
[level
][j
];
574 union spoolss_PrintProcessorInfo
*ref
= &ctx
->print_processors
[1][j
];
578 /* level 1 is our reference, and it makes no sense to compare it to itself */
587 static bool test_EnumPrintProcDataTypes(struct torture_context
*tctx
,
588 struct dcerpc_pipe
*p
,
589 struct test_spoolss_context
*ctx
)
592 struct spoolss_EnumPrintProcDataTypes r
;
593 uint16_t levels
[] = { 1 };
596 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
597 int level
= levels
[i
];
601 union spoolss_PrintProcDataTypesInfo
*info
;
603 r
.in
.servername
= "";
604 r
.in
.print_processor_name
= "winprint";
608 r
.out
.needed
= &needed
;
609 r
.out
.count
= &count
;
612 torture_comment(tctx
, "Testing EnumPrintProcDataTypes level %u\n", r
.in
.level
);
614 status
= dcerpc_spoolss_EnumPrintProcDataTypes(p
, ctx
, &r
);
615 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcDataType failed");
616 if (W_ERROR_IS_OK(r
.out
.result
)) {
617 /* TODO: do some more checks here */
620 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
621 "EnumPrintProcDataTypes unexpected return code");
623 blob
= data_blob_talloc(ctx
, NULL
, needed
);
624 data_blob_clear(&blob
);
626 r
.in
.offered
= needed
;
628 status
= dcerpc_spoolss_EnumPrintProcDataTypes(p
, ctx
, &r
);
629 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
631 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrintProcDataTypes failed");
638 static bool test_EnumPrinters(struct torture_context
*tctx
,
639 struct dcerpc_pipe
*p
,
640 struct test_spoolss_context
*ctx
)
642 struct spoolss_EnumPrinters r
;
644 uint16_t levels
[] = { 0, 1, 2, 4, 5 };
647 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
648 int level
= levels
[i
];
652 union spoolss_PrinterInfo
*info
;
654 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
659 r
.out
.needed
= &needed
;
660 r
.out
.count
= &count
;
663 torture_comment(tctx
, "Testing EnumPrinters level %u\n", r
.in
.level
);
665 status
= dcerpc_spoolss_EnumPrinters(p
, ctx
, &r
);
666 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinters failed");
667 if (W_ERROR_IS_OK(r
.out
.result
)) {
668 /* TODO: do some more checks here */
671 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
672 "EnumPrinters unexpected return code");
674 blob
= data_blob_talloc(ctx
, NULL
, needed
);
675 data_blob_clear(&blob
);
677 r
.in
.offered
= needed
;
679 status
= dcerpc_spoolss_EnumPrinters(p
, ctx
, &r
);
680 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinters failed");
682 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
684 ctx
->printer_count
[level
] = count
;
685 ctx
->printers
[level
] = info
;
688 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
689 int level
= levels
[i
];
690 int old_level
= levels
[i
-1];
691 torture_assert_int_equal(tctx
, ctx
->printer_count
[level
], ctx
->printer_count
[old_level
],
692 "EnumPrinters invalid value");
695 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
696 int level
= levels
[i
];
697 for (j
=0;j
<ctx
->printer_count
[level
];j
++) {
698 union spoolss_PrinterInfo
*cur
= &ctx
->printers
[level
][j
];
699 union spoolss_PrinterInfo
*ref
= &ctx
->printers
[2][j
];
702 COMPARE_STRING(tctx
, cur
->info0
, ref
->info2
, printername
);
703 COMPARE_STRING(tctx
, cur
->info0
, ref
->info2
, servername
);
704 COMPARE_UINT32(tctx
, cur
->info0
, ref
->info2
, cjobs
);
705 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
706 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
707 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
708 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
709 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
710 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
711 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
712 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
713 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
714 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
715 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
716 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
717 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
718 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
719 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
720 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
721 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
722 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
723 COMPARE_UINT32(tctx
, cur
->info0
, ref
->info2
, status
);
724 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
725 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
726 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
727 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
728 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
729 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
730 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
733 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
734 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
735 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
736 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, comment
);
739 /* level 2 is our reference, and it makes no sense to compare it to itself */
742 COMPARE_STRING(tctx
, cur
->info4
, ref
->info2
, printername
);
743 COMPARE_STRING(tctx
, cur
->info4
, ref
->info2
, servername
);
744 COMPARE_UINT32(tctx
, cur
->info4
, ref
->info2
, attributes
);
747 COMPARE_STRING(tctx
, cur
->info5
, ref
->info2
, printername
);
748 COMPARE_STRING(tctx
, cur
->info5
, ref
->info2
, portname
);
749 COMPARE_UINT32(tctx
, cur
->info5
, ref
->info2
, attributes
);
750 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
751 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
758 * - verify that the port of a printer was in the list returned by EnumPorts
764 static bool test_GetPrinter(struct torture_context
*tctx
,
765 struct dcerpc_pipe
*p
,
766 struct policy_handle
*handle
)
769 struct spoolss_GetPrinter r
;
770 uint16_t levels
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
774 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
775 r
.in
.handle
= handle
;
776 r
.in
.level
= levels
[i
];
779 r
.out
.needed
= &needed
;
781 torture_comment(tctx
, "Testing GetPrinter level %u\n", r
.in
.level
);
783 status
= dcerpc_spoolss_GetPrinter(p
, tctx
, &r
);
784 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinter failed");
786 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
787 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
788 data_blob_clear(&blob
);
790 r
.in
.offered
= needed
;
791 status
= dcerpc_spoolss_GetPrinter(p
, tctx
, &r
);
794 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinter failed");
796 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrinter failed");
802 static bool test_SetPrinter_errors(struct torture_context
*tctx
,
803 struct dcerpc_pipe
*p
,
804 struct policy_handle
*handle
)
806 struct spoolss_SetPrinter r
;
807 uint16_t levels
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
810 struct spoolss_SetPrinterInfoCtr info_ctr
;
811 struct spoolss_DevmodeContainer devmode_ctr
;
812 struct sec_desc_buf secdesc_ctr
;
815 info_ctr
.info
.info0
= NULL
;
817 ZERO_STRUCT(devmode_ctr
);
818 ZERO_STRUCT(secdesc_ctr
);
820 r
.in
.handle
= handle
;
821 r
.in
.info_ctr
= &info_ctr
;
822 r
.in
.devmode_ctr
= &devmode_ctr
;
823 r
.in
.secdesc_ctr
= &secdesc_ctr
;
826 torture_comment(tctx
, "Testing SetPrinter all zero\n");
828 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter(p
, tctx
, &r
),
829 "failed to call SetPrinter");
830 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
831 "failed to call SetPrinter");
834 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
836 struct spoolss_SetPrinterInfo0 info0
;
837 struct spoolss_SetPrinterInfo1 info1
;
838 struct spoolss_SetPrinterInfo2 info2
;
839 struct spoolss_SetPrinterInfo3 info3
;
840 struct spoolss_SetPrinterInfo4 info4
;
841 struct spoolss_SetPrinterInfo5 info5
;
842 struct spoolss_SetPrinterInfo6 info6
;
843 struct spoolss_SetPrinterInfo7 info7
;
844 struct spoolss_DeviceModeInfo info8
;
845 struct spoolss_DeviceModeInfo info9
;
848 info_ctr
.level
= levels
[i
];
852 info_ctr
.info
.info0
= &info0
;
856 info_ctr
.info
.info1
= &info1
;
860 info_ctr
.info
.info2
= &info2
;
864 info_ctr
.info
.info3
= &info3
;
868 info_ctr
.info
.info4
= &info4
;
872 info_ctr
.info
.info5
= &info5
;
876 info_ctr
.info
.info6
= &info6
;
880 info_ctr
.info
.info7
= &info7
;
884 info_ctr
.info
.info8
= &info8
;
888 info_ctr
.info
.info9
= &info9
;
892 torture_comment(tctx
, "Testing SetPrinter level %d, command %d\n",
893 info_ctr
.level
, r
.in
.command
);
895 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter(p
, tctx
, &r
),
896 "failed to call SetPrinter");
898 switch (r
.in
.command
) {
899 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
: /* 0 */
900 /* is ignored for all levels other then 0 */
901 if (info_ctr
.level
> 0) {
905 case SPOOLSS_PRINTER_CONTROL_PAUSE
: /* 1 */
906 case SPOOLSS_PRINTER_CONTROL_RESUME
: /* 2 */
907 case SPOOLSS_PRINTER_CONTROL_PURGE
: /* 3 */
908 if (info_ctr
.level
> 0) {
909 /* is invalid for all levels other then 0 */
910 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PRINTER_COMMAND
,
911 "unexpected error code returned");
914 torture_assert_werr_ok(tctx
, r
.out
.result
,
915 "failed to call SetPrinter with non 0 command");
920 case SPOOLSS_PRINTER_CONTROL_SET_STATUS
: /* 4 */
921 /* FIXME: gd needs further investigation */
923 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PRINTER_COMMAND
,
924 "unexpected error code returned");
928 switch (info_ctr
.level
) {
930 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
,
931 "unexpected error code returned");
934 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_PRINTER_DRIVER
,
935 "unexpected error code returned");
941 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
942 "unexpected error code returned");
945 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_NOT_SUPPORTED
,
946 "unexpected error code returned");
949 torture_assert_werr_ok(tctx
, r
.out
.result
,
950 "failed to call SetPrinter");
955 if (r
.in
.command
< 5) {
963 static void clear_info2(struct spoolss_SetPrinterInfoCtr
*r
)
965 if ((r
->level
== 2) && (r
->info
.info2
)) {
966 r
->info
.info2
->secdesc
= NULL
;
967 r
->info
.info2
->devmode
= NULL
;
971 static bool test_PrinterInfo(struct torture_context
*tctx
,
972 struct dcerpc_pipe
*p
,
973 struct policy_handle
*handle
)
976 struct spoolss_SetPrinter s
;
977 struct spoolss_GetPrinter q
;
978 struct spoolss_GetPrinter q0
;
979 struct spoolss_SetPrinterInfoCtr info_ctr
;
980 union spoolss_PrinterInfo info
;
981 struct spoolss_DevmodeContainer devmode_ctr
;
982 struct sec_desc_buf secdesc_ctr
;
987 uint32_t status_list
[] = {
988 /* these do not stick
989 PRINTER_STATUS_PAUSED,
990 PRINTER_STATUS_ERROR,
991 PRINTER_STATUS_PENDING_DELETION, */
992 PRINTER_STATUS_PAPER_JAM
,
993 PRINTER_STATUS_PAPER_OUT
,
994 PRINTER_STATUS_MANUAL_FEED
,
995 PRINTER_STATUS_PAPER_PROBLEM
,
996 PRINTER_STATUS_OFFLINE
,
997 PRINTER_STATUS_IO_ACTIVE
,
999 PRINTER_STATUS_PRINTING
,
1000 PRINTER_STATUS_OUTPUT_BIN_FULL
,
1001 PRINTER_STATUS_NOT_AVAILABLE
,
1002 PRINTER_STATUS_WAITING
,
1003 PRINTER_STATUS_PROCESSING
,
1004 PRINTER_STATUS_INITIALIZING
,
1005 PRINTER_STATUS_WARMING_UP
,
1006 PRINTER_STATUS_TONER_LOW
,
1007 PRINTER_STATUS_NO_TONER
,
1008 PRINTER_STATUS_PAGE_PUNT
,
1009 PRINTER_STATUS_USER_INTERVENTION
,
1010 PRINTER_STATUS_OUT_OF_MEMORY
,
1011 PRINTER_STATUS_DOOR_OPEN
,
1012 PRINTER_STATUS_SERVER_UNKNOWN
,
1013 PRINTER_STATUS_POWER_SAVE
,
1014 /* these do not stick
1023 uint32_t default_attribute
= PRINTER_ATTRIBUTE_LOCAL
;
1024 uint32_t attribute_list
[] = {
1025 PRINTER_ATTRIBUTE_QUEUED
,
1026 /* fails with WERR_INVALID_DATATYPE:
1027 PRINTER_ATTRIBUTE_DIRECT, */
1029 PRINTER_ATTRIBUTE_DEFAULT, */
1030 PRINTER_ATTRIBUTE_SHARED
,
1032 PRINTER_ATTRIBUTE_NETWORK, */
1033 PRINTER_ATTRIBUTE_HIDDEN
,
1034 PRINTER_ATTRIBUTE_LOCAL
,
1035 PRINTER_ATTRIBUTE_ENABLE_DEVQ
,
1036 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
,
1037 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST
,
1038 PRINTER_ATTRIBUTE_WORK_OFFLINE
,
1040 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1041 /* fails with WERR_INVALID_DATATYPE:
1042 PRINTER_ATTRIBUTE_RAW_ONLY, */
1043 /* these do not stick
1044 PRINTER_ATTRIBUTE_PUBLISHED,
1045 PRINTER_ATTRIBUTE_FAX,
1046 PRINTER_ATTRIBUTE_TS,
1065 ZERO_STRUCT(devmode_ctr
);
1066 ZERO_STRUCT(secdesc_ctr
);
1068 s
.in
.handle
= handle
;
1070 s
.in
.info_ctr
= &info_ctr
;
1071 s
.in
.devmode_ctr
= &devmode_ctr
;
1072 s
.in
.secdesc_ctr
= &secdesc_ctr
;
1074 q
.in
.handle
= handle
;
1078 #define TESTGETCALL(call, r) \
1079 r.in.buffer = NULL; \
1081 r.out.needed = &needed; \
1082 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1083 if (!NT_STATUS_IS_OK(status)) { \
1084 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1085 r.in.level, nt_errstr(status), __location__); \
1089 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1090 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1091 data_blob_clear(&blob); \
1092 r.in.buffer = &blob; \
1093 r.in.offered = needed; \
1095 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1096 if (!NT_STATUS_IS_OK(status)) { \
1097 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1098 r.in.level, nt_errstr(status), __location__); \
1102 if (!W_ERROR_IS_OK(r.out.result)) { \
1103 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1104 r.in.level, win_errstr(r.out.result), __location__); \
1110 #define TESTSETCALL_EXP(call, r, err) \
1111 clear_info2(&info_ctr);\
1112 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1113 if (!NT_STATUS_IS_OK(status)) { \
1114 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1115 r.in.info_ctr->level, nt_errstr(status), __location__); \
1119 if (!W_ERROR_IS_OK(err)) { \
1120 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1121 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1122 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1127 if (!W_ERROR_IS_OK(r.out.result)) { \
1128 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1129 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1134 #define TESTSETCALL(call, r) \
1135 TESTSETCALL_EXP(call, r, WERR_OK)
1137 #define STRING_EQUAL(s1, s2, field) \
1138 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1139 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1140 #field, s2, __location__); \
1145 #define MEM_EQUAL(s1, s2, length, field) \
1146 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1147 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1148 #field, (const char *)s2, __location__); \
1153 #define INT_EQUAL(i1, i2, field) \
1155 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1156 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1161 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1162 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1163 q.in.level = lvl1; \
1164 TESTGETCALL(GetPrinter, q) \
1165 info_ctr.level = lvl1; \
1166 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1167 info_ctr.info.info ## lvl1->field1 = value;\
1168 TESTSETCALL_EXP(SetPrinter, s, err) \
1169 info_ctr.info.info ## lvl1->field1 = ""; \
1170 TESTGETCALL(GetPrinter, q) \
1171 info_ctr.info.info ## lvl1->field1 = value; \
1172 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1173 q.in.level = lvl2; \
1174 TESTGETCALL(GetPrinter, q) \
1175 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1176 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1179 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1180 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1183 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1184 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1185 q.in.level = lvl1; \
1186 TESTGETCALL(GetPrinter, q) \
1187 info_ctr.level = lvl1; \
1188 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1189 info_ctr.info.info ## lvl1->field1 = value; \
1190 TESTSETCALL(SetPrinter, s) \
1191 info_ctr.info.info ## lvl1->field1 = 0; \
1192 TESTGETCALL(GetPrinter, q) \
1193 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1194 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1195 q.in.level = lvl2; \
1196 TESTGETCALL(GetPrinter, q) \
1197 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1198 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1201 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1202 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1206 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1208 TEST_PRINTERINFO_STRING(2, comment
, 1, comment
, "xx2-1 comment");
1209 TEST_PRINTERINFO_STRING(2, comment
, 2, comment
, "xx2-2 comment");
1211 /* level 0 printername does not stick */
1212 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1213 TEST_PRINTERINFO_STRING(2, printername
, 1, name
, "xx2-1 printer");
1214 TEST_PRINTERINFO_STRING(2, printername
, 2, printername
, "xx2-2 printer");
1215 TEST_PRINTERINFO_STRING(2, printername
, 4, printername
, "xx2-4 printer");
1216 TEST_PRINTERINFO_STRING(2, printername
, 5, printername
, "xx2-5 printer");
1217 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1218 TEST_PRINTERINFO_STRING(4, printername
, 1, name
, "xx4-1 printer");
1219 TEST_PRINTERINFO_STRING(4, printername
, 2, printername
, "xx4-2 printer");
1220 TEST_PRINTERINFO_STRING(4, printername
, 4, printername
, "xx4-4 printer");
1221 TEST_PRINTERINFO_STRING(4, printername
, 5, printername
, "xx4-5 printer");
1222 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1223 TEST_PRINTERINFO_STRING(5, printername
, 1, name
, "xx5-1 printer");
1224 TEST_PRINTERINFO_STRING(5, printername
, 2, printername
, "xx5-2 printer");
1225 TEST_PRINTERINFO_STRING(5, printername
, 4, printername
, "xx5-4 printer");
1226 TEST_PRINTERINFO_STRING(5, printername
, 5, printername
, "xx5-5 printer");
1228 /* servername can be set but does not stick
1229 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1230 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1231 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1234 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1235 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname
, 2, portname
, "xx2-2 portname", WERR_UNKNOWN_PORT
);
1236 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname
, 5, portname
, "xx2-5 portname", WERR_UNKNOWN_PORT
);
1237 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname
, 2, portname
, "xx5-2 portname", WERR_UNKNOWN_PORT
);
1238 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname
, 5, portname
, "xx5-5 portname", WERR_UNKNOWN_PORT
);
1240 TEST_PRINTERINFO_STRING(2, sharename
, 2, sharename
, "xx2-2 sharename");
1241 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1242 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername
, 2, drivername
, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER
);
1243 TEST_PRINTERINFO_STRING(2, location
, 2, location
, "xx2-2 location");
1244 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1245 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile
, 2, sepfile
, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE
);
1246 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1247 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor
, 2, printprocessor
, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR
);
1248 TEST_PRINTERINFO_STRING(2, datatype
, 2, datatype
, "xx2-2 datatype");
1249 TEST_PRINTERINFO_STRING(2, parameters
, 2, parameters
, "xx2-2 parameters");
1251 for (i
=0; i
< ARRAY_SIZE(attribute_list
); i
++) {
1252 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1254 (attribute_list[i] | default_attribute)
1256 TEST_PRINTERINFO_INT_EXP(2, attributes
, 2, attributes
,
1258 (attribute_list
[i
] | default_attribute
)
1260 TEST_PRINTERINFO_INT_EXP(2, attributes
, 4, attributes
,
1262 (attribute_list
[i
] | default_attribute
)
1264 TEST_PRINTERINFO_INT_EXP(2, attributes
, 5, attributes
,
1266 (attribute_list
[i
] | default_attribute
)
1268 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1270 (attribute_list[i] | default_attribute)
1272 TEST_PRINTERINFO_INT_EXP(4, attributes
, 2, attributes
,
1274 (attribute_list
[i
] | default_attribute
)
1276 TEST_PRINTERINFO_INT_EXP(4, attributes
, 4, attributes
,
1278 (attribute_list
[i
] | default_attribute
)
1280 TEST_PRINTERINFO_INT_EXP(4, attributes
, 5, attributes
,
1282 (attribute_list
[i
] | default_attribute
)
1284 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1286 (attribute_list[i] | default_attribute)
1288 TEST_PRINTERINFO_INT_EXP(5, attributes
, 2, attributes
,
1290 (attribute_list
[i
] | default_attribute
)
1292 TEST_PRINTERINFO_INT_EXP(5, attributes
, 4, attributes
,
1294 (attribute_list
[i
] | default_attribute
)
1296 TEST_PRINTERINFO_INT_EXP(5, attributes
, 5, attributes
,
1298 (attribute_list
[i
] | default_attribute
)
1302 for (i
=0; i
< ARRAY_SIZE(status_list
); i
++) {
1303 /* level 2 sets do not stick
1304 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1305 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1306 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1307 TEST_PRINTERINFO_INT(6, status
, 0, status
, status_list
[i
]);
1308 TEST_PRINTERINFO_INT(6, status
, 2, status
, status_list
[i
]);
1309 TEST_PRINTERINFO_INT(6, status
, 6, status
, status_list
[i
]);
1312 /* priorities need to be between 0 and 99
1313 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1314 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 0);
1315 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 1);
1316 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 99);
1317 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1318 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 0);
1319 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 1);
1320 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 99);
1321 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1323 TEST_PRINTERINFO_INT(2, starttime
, 2, starttime
, __LINE__
);
1324 TEST_PRINTERINFO_INT(2, untiltime
, 2, untiltime
, __LINE__
);
1327 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1328 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1331 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1332 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1334 /* FIXME: gd also test devmode and secdesc behavior */
1337 /* verify composition of level 1 description field */
1338 const char *description
;
1342 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1344 description
= talloc_strdup(tctx
, q0
.out
.info
->info1
.description
);
1347 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1349 tmp
= talloc_asprintf(tctx
, "%s,%s,%s",
1350 q0
.out
.info
->info2
.printername
,
1351 q0
.out
.info
->info2
.drivername
,
1352 q0
.out
.info
->info2
.location
);
1354 do { STRING_EQUAL(description
, tmp
, "description")} while (0);
1361 static bool test_ClosePrinter(struct torture_context
*tctx
,
1362 struct dcerpc_pipe
*p
,
1363 struct policy_handle
*handle
)
1366 struct spoolss_ClosePrinter r
;
1368 r
.in
.handle
= handle
;
1369 r
.out
.handle
= handle
;
1371 torture_comment(tctx
, "Testing ClosePrinter\n");
1373 status
= dcerpc_spoolss_ClosePrinter(p
, tctx
, &r
);
1374 torture_assert_ntstatus_ok(tctx
, status
, "ClosePrinter failed");
1375 torture_assert_werr_ok(tctx
, r
.out
.result
, "ClosePrinter failed");
1380 static bool test_GetForm(struct torture_context
*tctx
,
1381 struct dcerpc_pipe
*p
,
1382 struct policy_handle
*handle
,
1383 const char *form_name
,
1387 struct spoolss_GetForm r
;
1390 r
.in
.handle
= handle
;
1391 r
.in
.form_name
= form_name
;
1395 r
.out
.needed
= &needed
;
1397 torture_comment(tctx
, "Testing GetForm level %d\n", r
.in
.level
);
1399 status
= dcerpc_spoolss_GetForm(p
, tctx
, &r
);
1400 torture_assert_ntstatus_ok(tctx
, status
, "GetForm failed");
1402 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1403 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1404 data_blob_clear(&blob
);
1405 r
.in
.buffer
= &blob
;
1406 r
.in
.offered
= needed
;
1407 status
= dcerpc_spoolss_GetForm(p
, tctx
, &r
);
1408 torture_assert_ntstatus_ok(tctx
, status
, "GetForm failed");
1410 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetForm failed");
1412 torture_assert(tctx
, r
.out
.info
, "No form info returned");
1415 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetForm failed");
1420 static bool test_EnumForms(struct torture_context
*tctx
,
1421 struct dcerpc_pipe
*p
,
1422 struct policy_handle
*handle
, bool print_server
)
1425 struct spoolss_EnumForms r
;
1429 uint32_t levels
[] = { 1, 2 };
1432 for (i
=0; i
<ARRAY_SIZE(levels
); i
++) {
1434 union spoolss_FormInfo
*info
;
1436 r
.in
.handle
= handle
;
1437 r
.in
.level
= levels
[i
];
1440 r
.out
.needed
= &needed
;
1441 r
.out
.count
= &count
;
1444 torture_comment(tctx
, "Testing EnumForms level %d\n", levels
[i
]);
1446 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &r
);
1447 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
1449 if ((r
.in
.level
== 2) && (W_ERROR_EQUAL(r
.out
.result
, WERR_UNKNOWN_LEVEL
))) {
1453 if (print_server
&& W_ERROR_EQUAL(r
.out
.result
, WERR_BADFID
))
1454 torture_fail(tctx
, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1456 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1458 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1459 data_blob_clear(&blob
);
1460 r
.in
.buffer
= &blob
;
1461 r
.in
.offered
= needed
;
1463 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &r
);
1465 torture_assert(tctx
, info
, "No forms returned");
1467 for (j
= 0; j
< count
; j
++) {
1469 ret
&= test_GetForm(tctx
, p
, handle
, info
[j
].info1
.form_name
, levels
[i
]);
1473 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
1475 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumForms failed");
1481 static bool test_DeleteForm(struct torture_context
*tctx
,
1482 struct dcerpc_pipe
*p
,
1483 struct policy_handle
*handle
,
1484 const char *form_name
)
1487 struct spoolss_DeleteForm r
;
1489 r
.in
.handle
= handle
;
1490 r
.in
.form_name
= form_name
;
1492 status
= dcerpc_spoolss_DeleteForm(p
, tctx
, &r
);
1494 torture_assert_ntstatus_ok(tctx
, status
, "DeleteForm failed");
1496 torture_assert_werr_ok(tctx
, r
.out
.result
, "DeleteForm failed");
1501 static bool test_AddForm(struct torture_context
*tctx
,
1502 struct dcerpc_pipe
*p
,
1503 struct policy_handle
*handle
, bool print_server
)
1505 struct spoolss_AddForm r
;
1506 struct spoolss_AddFormInfo1 addform
;
1507 const char *form_name
= "testform3";
1511 r
.in
.handle
= handle
;
1513 r
.in
.info
.info1
= &addform
;
1514 addform
.flags
= SPOOLSS_FORM_USER
;
1515 addform
.form_name
= form_name
;
1516 addform
.size
.width
= 50;
1517 addform
.size
.height
= 25;
1518 addform
.area
.left
= 5;
1519 addform
.area
.top
= 10;
1520 addform
.area
.right
= 45;
1521 addform
.area
.bottom
= 15;
1523 status
= dcerpc_spoolss_AddForm(p
, tctx
, &r
);
1525 torture_assert_ntstatus_ok(tctx
, status
, "AddForm failed");
1527 torture_assert_werr_ok(tctx
, r
.out
.result
, "AddForm failed");
1529 if (!print_server
) ret
&= test_GetForm(tctx
, p
, handle
, form_name
, 1);
1532 struct spoolss_SetForm sf
;
1533 struct spoolss_AddFormInfo1 setform
;
1535 sf
.in
.handle
= handle
;
1536 sf
.in
.form_name
= form_name
;
1538 sf
.in
.info
.info1
= &setform
;
1539 setform
.flags
= addform
.flags
;
1540 setform
.form_name
= addform
.form_name
;
1541 setform
.size
= addform
.size
;
1542 setform
.area
= addform
.area
;
1544 setform
.size
.width
= 1234;
1546 status
= dcerpc_spoolss_SetForm(p
, tctx
, &sf
);
1548 torture_assert_ntstatus_ok(tctx
, status
, "SetForm failed");
1550 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetForm failed");
1553 if (!print_server
) ret
&= test_GetForm(tctx
, p
, handle
, form_name
, 1);
1556 struct spoolss_EnumForms e
;
1557 union spoolss_FormInfo
*info
;
1562 e
.in
.handle
= handle
;
1566 e
.out
.needed
= &needed
;
1567 e
.out
.count
= &count
;
1570 torture_comment(tctx
, "Testing EnumForms level 1\n");
1572 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &e
);
1573 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
1575 if (print_server
&& W_ERROR_EQUAL(e
.out
.result
, WERR_BADFID
))
1576 torture_fail(tctx
, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1578 if (W_ERROR_EQUAL(e
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1580 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1581 data_blob_clear(&blob
);
1582 e
.in
.buffer
= &blob
;
1583 e
.in
.offered
= needed
;
1585 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &e
);
1587 torture_assert(tctx
, info
, "No forms returned");
1589 for (j
= 0; j
< count
; j
++) {
1590 if (strequal(form_name
, info
[j
].info1
.form_name
)) {
1596 torture_assert(tctx
, found
, "Newly added form not found in enum call");
1599 if (!test_DeleteForm(tctx
, p
, handle
, form_name
)) {
1606 static bool test_EnumPorts_old(struct torture_context
*tctx
,
1607 struct dcerpc_pipe
*p
)
1610 struct spoolss_EnumPorts r
;
1613 union spoolss_PortInfo
*info
;
1615 r
.in
.servername
= talloc_asprintf(tctx
, "\\\\%s",
1616 dcerpc_server_name(p
));
1620 r
.out
.needed
= &needed
;
1621 r
.out
.count
= &count
;
1624 torture_comment(tctx
, "Testing EnumPorts\n");
1626 status
= dcerpc_spoolss_EnumPorts(p
, tctx
, &r
);
1628 torture_assert_ntstatus_ok(tctx
, status
, "EnumPorts failed");
1630 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1631 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1632 data_blob_clear(&blob
);
1633 r
.in
.buffer
= &blob
;
1634 r
.in
.offered
= needed
;
1636 status
= dcerpc_spoolss_EnumPorts(p
, tctx
, &r
);
1637 torture_assert_ntstatus_ok(tctx
, status
, "EnumPorts failed");
1638 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
1640 torture_assert(tctx
, info
, "No ports returned");
1643 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
1648 static bool test_AddPort(struct torture_context
*tctx
,
1649 struct dcerpc_pipe
*p
)
1652 struct spoolss_AddPort r
;
1654 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s",
1655 dcerpc_server_name(p
));
1657 r
.in
.monitor_name
= "foo";
1659 torture_comment(tctx
, "Testing AddPort\n");
1661 status
= dcerpc_spoolss_AddPort(p
, tctx
, &r
);
1663 torture_assert_ntstatus_ok(tctx
, status
, "AddPort failed");
1665 /* win2k3 returns WERR_NOT_SUPPORTED */
1669 if (!W_ERROR_IS_OK(r
.out
.result
)) {
1670 printf("AddPort failed - %s\n", win_errstr(r
.out
.result
));
1679 static bool test_GetJob(struct torture_context
*tctx
,
1680 struct dcerpc_pipe
*p
,
1681 struct policy_handle
*handle
, uint32_t job_id
)
1684 struct spoolss_GetJob r
;
1685 union spoolss_JobInfo info
;
1687 uint32_t levels
[] = {1, 2 /* 3, 4 */};
1690 r
.in
.handle
= handle
;
1691 r
.in
.job_id
= job_id
;
1695 r
.out
.needed
= &needed
;
1698 torture_comment(tctx
, "Testing GetJob level %d\n", r
.in
.level
);
1700 status
= dcerpc_spoolss_GetJob(p
, tctx
, &r
);
1701 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
, "Unexpected return code");
1703 for (i
= 0; i
< ARRAY_SIZE(levels
); i
++) {
1705 torture_comment(tctx
, "Testing GetJob level %d\n", r
.in
.level
);
1709 r
.in
.level
= levels
[i
];
1713 status
= dcerpc_spoolss_GetJob(p
, tctx
, &r
);
1714 torture_assert_ntstatus_ok(tctx
, status
, "GetJob failed");
1716 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1717 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1718 data_blob_clear(&blob
);
1719 r
.in
.buffer
= &blob
;
1720 r
.in
.offered
= needed
;
1722 status
= dcerpc_spoolss_GetJob(p
, tctx
, &r
);
1723 torture_assert_ntstatus_ok(tctx
, status
, "GetJob failed");
1726 torture_assert(tctx
, r
.out
.info
, "No job info returned");
1727 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetJob failed");
1733 static bool test_SetJob(struct torture_context
*tctx
,
1734 struct dcerpc_pipe
*p
,
1735 struct policy_handle
*handle
, uint32_t job_id
,
1736 enum spoolss_JobControl command
)
1739 struct spoolss_SetJob r
;
1741 r
.in
.handle
= handle
;
1742 r
.in
.job_id
= job_id
;
1744 r
.in
.command
= command
;
1747 case SPOOLSS_JOB_CONTROL_PAUSE
:
1748 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1750 case SPOOLSS_JOB_CONTROL_RESUME
:
1751 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1753 case SPOOLSS_JOB_CONTROL_CANCEL
:
1754 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1756 case SPOOLSS_JOB_CONTROL_RESTART
:
1757 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1759 case SPOOLSS_JOB_CONTROL_DELETE
:
1760 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1762 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER
:
1763 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1765 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED
:
1766 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1768 case SPOOLSS_JOB_CONTROL_RETAIN
:
1769 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1771 case SPOOLSS_JOB_CONTROL_RELEASE
:
1772 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1775 torture_comment(tctx
, "Testing SetJob\n");
1779 status
= dcerpc_spoolss_SetJob(p
, tctx
, &r
);
1780 torture_assert_ntstatus_ok(tctx
, status
, "SetJob failed");
1781 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetJob failed");
1786 static bool test_AddJob(struct torture_context
*tctx
,
1787 struct dcerpc_pipe
*p
,
1788 struct policy_handle
*handle
)
1791 struct spoolss_AddJob r
;
1795 r
.in
.handle
= handle
;
1797 r
.out
.needed
= &needed
;
1798 r
.in
.buffer
= r
.out
.buffer
= NULL
;
1800 torture_comment(tctx
, "Testing AddJob\n");
1802 status
= dcerpc_spoolss_AddJob(p
, tctx
, &r
);
1803 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
, "AddJob failed");
1807 status
= dcerpc_spoolss_AddJob(p
, tctx
, &r
);
1808 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
, "AddJob failed");
1814 static bool test_EnumJobs(struct torture_context
*tctx
,
1815 struct dcerpc_pipe
*p
,
1816 struct policy_handle
*handle
)
1819 struct spoolss_EnumJobs r
;
1822 union spoolss_JobInfo
*info
;
1824 r
.in
.handle
= handle
;
1826 r
.in
.numjobs
= 0xffffffff;
1830 r
.out
.needed
= &needed
;
1831 r
.out
.count
= &count
;
1834 torture_comment(tctx
, "Testing EnumJobs\n");
1836 status
= dcerpc_spoolss_EnumJobs(p
, tctx
, &r
);
1838 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
1840 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1842 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1843 data_blob_clear(&blob
);
1844 r
.in
.buffer
= &blob
;
1845 r
.in
.offered
= needed
;
1847 status
= dcerpc_spoolss_EnumJobs(p
, tctx
, &r
);
1849 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
1850 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumJobs failed");
1851 torture_assert(tctx
, info
, "No jobs returned");
1853 for (j
= 0; j
< count
; j
++) {
1855 torture_assert(tctx
, test_GetJob(tctx
, p
, handle
, info
[j
].info1
.job_id
),
1856 "failed to call test_GetJob");
1859 if (!torture_setting_bool(tctx
, "samba3", false)) {
1860 test_SetJob(tctx
, p
, handle
, info
[j
].info1
.job_id
, SPOOLSS_JOB_CONTROL_PAUSE
);
1861 test_SetJob(tctx
, p
, handle
, info
[j
].info1
.job_id
, SPOOLSS_JOB_CONTROL_RESUME
);
1866 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumJobs failed");
1872 static bool test_DoPrintTest(struct torture_context
*tctx
,
1873 struct dcerpc_pipe
*p
,
1874 struct policy_handle
*handle
)
1878 struct spoolss_StartDocPrinter s
;
1879 struct spoolss_DocumentInfo1 info1
;
1880 struct spoolss_StartPagePrinter sp
;
1881 struct spoolss_WritePrinter w
;
1882 struct spoolss_EndPagePrinter ep
;
1883 struct spoolss_EndDocPrinter e
;
1886 uint32_t num_written
;
1888 torture_comment(tctx
, "Testing StartDocPrinter\n");
1890 s
.in
.handle
= handle
;
1892 s
.in
.info
.info1
= &info1
;
1893 s
.out
.job_id
= &job_id
;
1894 info1
.document_name
= "TorturePrintJob";
1895 info1
.output_file
= NULL
;
1896 info1
.datatype
= "RAW";
1898 status
= dcerpc_spoolss_StartDocPrinter(p
, tctx
, &s
);
1899 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_StartDocPrinter failed");
1900 torture_assert_werr_ok(tctx
, s
.out
.result
, "StartDocPrinter failed");
1902 for (i
=1; i
< 4; i
++) {
1903 torture_comment(tctx
, "Testing StartPagePrinter: Page[%d]\n", i
);
1905 sp
.in
.handle
= handle
;
1907 status
= dcerpc_spoolss_StartPagePrinter(p
, tctx
, &sp
);
1908 torture_assert_ntstatus_ok(tctx
, status
,
1909 "dcerpc_spoolss_StartPagePrinter failed");
1910 torture_assert_werr_ok(tctx
, sp
.out
.result
, "StartPagePrinter failed");
1912 torture_comment(tctx
, "Testing WritePrinter: Page[%d]\n", i
);
1914 w
.in
.handle
= handle
;
1915 w
.in
.data
= data_blob_string_const(talloc_asprintf(tctx
,"TortureTestPage: %d\nData\n",i
));
1916 w
.out
.num_written
= &num_written
;
1918 status
= dcerpc_spoolss_WritePrinter(p
, tctx
, &w
);
1919 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_WritePrinter failed");
1920 torture_assert_werr_ok(tctx
, w
.out
.result
, "WritePrinter failed");
1922 torture_comment(tctx
, "Testing EndPagePrinter: Page[%d]\n", i
);
1924 ep
.in
.handle
= handle
;
1926 status
= dcerpc_spoolss_EndPagePrinter(p
, tctx
, &ep
);
1927 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndPagePrinter failed");
1928 torture_assert_werr_ok(tctx
, ep
.out
.result
, "EndPagePrinter failed");
1931 torture_comment(tctx
, "Testing EndDocPrinter\n");
1933 e
.in
.handle
= handle
;
1935 status
= dcerpc_spoolss_EndDocPrinter(p
, tctx
, &e
);
1936 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndDocPrinter failed");
1937 torture_assert_werr_ok(tctx
, e
.out
.result
, "EndDocPrinter failed");
1939 ret
&= test_AddJob(tctx
, p
, handle
);
1940 ret
&= test_EnumJobs(tctx
, p
, handle
);
1942 ret
&= test_SetJob(tctx
, p
, handle
, job_id
, SPOOLSS_JOB_CONTROL_DELETE
);
1947 static bool test_PausePrinter(struct torture_context
*tctx
,
1948 struct dcerpc_pipe
*p
,
1949 struct policy_handle
*handle
)
1952 struct spoolss_SetPrinter r
;
1953 struct spoolss_SetPrinterInfoCtr info_ctr
;
1954 struct spoolss_DevmodeContainer devmode_ctr
;
1955 struct sec_desc_buf secdesc_ctr
;
1958 info_ctr
.info
.info0
= NULL
;
1960 ZERO_STRUCT(devmode_ctr
);
1961 ZERO_STRUCT(secdesc_ctr
);
1963 r
.in
.handle
= handle
;
1964 r
.in
.info_ctr
= &info_ctr
;
1965 r
.in
.devmode_ctr
= &devmode_ctr
;
1966 r
.in
.secdesc_ctr
= &secdesc_ctr
;
1967 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
1969 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1971 status
= dcerpc_spoolss_SetPrinter(p
, tctx
, &r
);
1973 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
1975 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
1980 static bool test_ResumePrinter(struct torture_context
*tctx
,
1981 struct dcerpc_pipe
*p
,
1982 struct policy_handle
*handle
)
1985 struct spoolss_SetPrinter r
;
1986 struct spoolss_SetPrinterInfoCtr info_ctr
;
1987 struct spoolss_DevmodeContainer devmode_ctr
;
1988 struct sec_desc_buf secdesc_ctr
;
1991 info_ctr
.info
.info0
= NULL
;
1993 ZERO_STRUCT(devmode_ctr
);
1994 ZERO_STRUCT(secdesc_ctr
);
1996 r
.in
.handle
= handle
;
1997 r
.in
.info_ctr
= &info_ctr
;
1998 r
.in
.devmode_ctr
= &devmode_ctr
;
1999 r
.in
.secdesc_ctr
= &secdesc_ctr
;
2000 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
2002 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2004 status
= dcerpc_spoolss_SetPrinter(p
, tctx
, &r
);
2006 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
2008 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
2013 static bool test_GetPrinterData(struct torture_context
*tctx
,
2014 struct dcerpc_pipe
*p
,
2015 struct policy_handle
*handle
,
2016 const char *value_name
,
2017 enum winreg_Type
*type_p
,
2018 union spoolss_PrinterData
*data_p
)
2021 struct spoolss_GetPrinterData r
;
2023 enum winreg_Type type
;
2024 union spoolss_PrinterData data
;
2026 r
.in
.handle
= handle
;
2027 r
.in
.value_name
= value_name
;
2029 r
.out
.needed
= &needed
;
2033 torture_comment(tctx
, "Testing GetPrinterData(%s)\n", r
.in
.value_name
);
2035 status
= dcerpc_spoolss_GetPrinterData(p
, tctx
, &r
);
2036 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
2038 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
2039 r
.in
.offered
= needed
;
2041 status
= dcerpc_spoolss_GetPrinterData(p
, tctx
, &r
);
2042 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
2045 torture_assert_werr_ok(tctx
, r
.out
.result
,
2046 talloc_asprintf(tctx
, "GetPrinterData(%s) failed", r
.in
.value_name
));
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
,
2064 enum winreg_Type
*type_p
,
2065 union spoolss_PrinterData
*data_p
)
2068 struct spoolss_GetPrinterDataEx r
;
2069 enum winreg_Type type
;
2071 union spoolss_PrinterData data
;
2073 r
.in
.handle
= handle
;
2074 r
.in
.key_name
= key_name
;
2075 r
.in
.value_name
= value_name
;
2078 r
.out
.needed
= &needed
;
2081 torture_comment(tctx
, "Testing GetPrinterDataEx(%s - %s)\n",
2082 r
.in
.key_name
, r
.in
.value_name
);
2084 status
= dcerpc_spoolss_GetPrinterDataEx(p
, tctx
, &r
);
2085 if (!NT_STATUS_IS_OK(status
)) {
2086 if (NT_STATUS_EQUAL(status
,NT_STATUS_NET_WRITE_FAULT
) &&
2087 p
->last_fault_code
== DCERPC_FAULT_OP_RNG_ERROR
) {
2088 torture_skip(tctx
, "GetPrinterDataEx not supported by server\n");
2090 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
2093 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
2094 r
.in
.offered
= needed
;
2095 status
= dcerpc_spoolss_GetPrinterDataEx(p
, tctx
, &r
);
2096 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
2099 torture_assert_werr_ok(tctx
, r
.out
.result
,
2100 talloc_asprintf(tctx
, "GetPrinterDataEx(%s - %s) failed", r
.in
.key_name
, r
.in
.value_name
));
2113 static bool test_GetPrinterData_list(struct torture_context
*tctx
,
2114 struct dcerpc_pipe
*p
,
2115 struct policy_handle
*handle
)
2117 const char *list
[] = {
2121 /* "NetPopup", not on w2k8 */
2122 /* "NetPopupToComputer", not on w2k8 */
2125 "DefaultSpoolDirectory",
2129 /* "OSVersionEx", not on s3 */
2134 for (i
=0; i
< ARRAY_SIZE(list
); i
++) {
2135 enum winreg_Type type
, type_ex
;
2136 union spoolss_PrinterData data
, data_ex
;
2138 torture_assert(tctx
, test_GetPrinterData(tctx
, p
, handle
, list
[i
], &type
, &data
),
2139 talloc_asprintf(tctx
, "GetPrinterData failed on %s\n", list
[i
]));
2140 torture_assert(tctx
, test_GetPrinterDataEx(tctx
, p
, handle
, "random_string", list
[i
], &type_ex
, &data_ex
),
2141 talloc_asprintf(tctx
, "GetPrinterDataEx failed on %s\n", list
[i
]));
2142 torture_assert_int_equal(tctx
, type
, type_ex
, "type mismatch");
2145 torture_assert_str_equal(tctx
, data
.string
, data_ex
.string
, "REG_SZ mismatch");
2148 torture_assert_int_equal(tctx
, data
.value
, data_ex
.value
, "REG_DWORD mismatch");
2151 torture_assert_data_blob_equal(tctx
, data
.binary
, data_ex
.binary
, "REG_BINARY mismatch");
2161 static bool test_EnumPrinterData(struct torture_context
*tctx
, struct dcerpc_pipe
*p
,
2162 struct policy_handle
*handle
)
2165 struct spoolss_EnumPrinterData r
;
2168 r
.in
.handle
= handle
;
2169 r
.in
.enum_index
= 0;
2172 uint32_t value_size
= 0;
2173 uint32_t data_size
= 0;
2174 enum winreg_Type type
= 0;
2176 r
.in
.value_offered
= value_size
;
2177 r
.out
.value_needed
= &value_size
;
2178 r
.in
.data_offered
= data_size
;
2179 r
.out
.data_needed
= &data_size
;
2182 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, 0);
2184 torture_comment(tctx
, "Testing EnumPrinterData\n");
2186 status
= dcerpc_spoolss_EnumPrinterData(p
, tctx
, &r
);
2188 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterData failed");
2189 if (W_ERROR_EQUAL(r
.out
.result
, WERR_NO_MORE_ITEMS
)) {
2192 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterData");
2194 r
.in
.value_offered
= value_size
;
2195 r
.out
.value_name
= talloc_zero_array(tctx
, const char, value_size
);
2196 r
.in
.data_offered
= data_size
;
2197 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, data_size
);
2199 status
= dcerpc_spoolss_EnumPrinterData(p
, tctx
, &r
);
2201 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterData failed");
2202 if (W_ERROR_EQUAL(r
.out
.result
, WERR_NO_MORE_ITEMS
)) {
2206 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterData failed");
2208 torture_assert(tctx
, test_GetPrinterData(tctx
, p
, handle
, r
.out
.value_name
, NULL
, NULL
),
2209 talloc_asprintf(tctx
, "failed to call GetPrinterData for %s\n", r
.out
.value_name
));
2211 torture_assert(tctx
, test_GetPrinterDataEx(tctx
, p
, handle
, "PrinterDriverData", r
.out
.value_name
, NULL
, NULL
),
2212 talloc_asprintf(tctx
, "failed to call GetPrinterDataEx on PrinterDriverData for %s\n", r
.out
.value_name
));
2216 } while (W_ERROR_IS_OK(r
.out
.result
));
2221 static bool test_EnumPrinterDataEx(struct torture_context
*tctx
,
2222 struct dcerpc_pipe
*p
,
2223 struct policy_handle
*handle
,
2224 const char *key_name
)
2226 struct spoolss_EnumPrinterDataEx r
;
2227 struct spoolss_PrinterEnumValues
*info
;
2231 r
.in
.handle
= handle
;
2232 r
.in
.key_name
= key_name
;
2234 r
.out
.needed
= &needed
;
2235 r
.out
.count
= &count
;
2238 torture_comment(tctx
, "Testing EnumPrinterDataEx(%s)\n", key_name
);
2240 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterDataEx(p
, tctx
, &r
),
2241 "EnumPrinterDataEx failed");
2242 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
2243 r
.in
.offered
= needed
;
2244 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterDataEx(p
, tctx
, &r
),
2245 "EnumPrinterDataEx failed");
2248 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDataEx failed");
2254 static bool test_DeletePrinterData(struct torture_context
*tctx
,
2255 struct dcerpc_pipe
*p
,
2256 struct policy_handle
*handle
,
2257 const char *value_name
)
2260 struct spoolss_DeletePrinterData r
;
2262 r
.in
.handle
= handle
;
2263 r
.in
.value_name
= value_name
;
2265 torture_comment(tctx
, "Testing DeletePrinterData(%s)\n",
2268 status
= dcerpc_spoolss_DeletePrinterData(p
, tctx
, &r
);
2270 torture_assert_ntstatus_ok(tctx
, status
, "DeletePrinterData failed");
2271 torture_assert_werr_ok(tctx
, r
.out
.result
, "DeletePrinterData failed");
2276 static bool test_DeletePrinterDataEx(struct torture_context
*tctx
,
2277 struct dcerpc_pipe
*p
,
2278 struct policy_handle
*handle
,
2279 const char *key_name
,
2280 const char *value_name
)
2282 struct spoolss_DeletePrinterDataEx r
;
2284 r
.in
.handle
= handle
;
2285 r
.in
.key_name
= key_name
;
2286 r
.in
.value_name
= value_name
;
2288 torture_comment(tctx
, "Testing DeletePrinterDataEx(%s - %s)\n",
2289 r
.in
.key_name
, r
.in
.value_name
);
2291 torture_assert_ntstatus_ok(tctx
,
2292 dcerpc_spoolss_DeletePrinterDataEx(p
, tctx
, &r
),
2293 "DeletePrinterDataEx failed");
2294 torture_assert_werr_ok(tctx
, r
.out
.result
,
2295 "DeletePrinterDataEx failed");
2300 static bool test_DeletePrinterKey(struct torture_context
*tctx
,
2301 struct dcerpc_pipe
*p
,
2302 struct policy_handle
*handle
,
2303 const char *key_name
)
2305 struct spoolss_DeletePrinterKey r
;
2307 r
.in
.handle
= handle
;
2308 r
.in
.key_name
= key_name
;
2310 torture_comment(tctx
, "Testing DeletePrinterKey(%s)\n", r
.in
.key_name
);
2312 if (strequal(key_name
, "") && !torture_setting_bool(tctx
, "dangerous", false)) {
2313 torture_skip(tctx
, "not wiping out printer registry - enable dangerous tests to use\n");
2317 torture_assert_ntstatus_ok(tctx
,
2318 dcerpc_spoolss_DeletePrinterKey(p
, tctx
, &r
),
2319 "DeletePrinterKey failed");
2320 torture_assert_werr_ok(tctx
, r
.out
.result
,
2321 "DeletePrinterKey failed");
2326 static bool test_SetPrinterData(struct torture_context
*tctx
,
2327 struct dcerpc_pipe
*p
,
2328 struct policy_handle
*handle
)
2331 struct spoolss_SetPrinterData r
;
2332 const char *values
[] = {
2343 for (i
=0; i
< ARRAY_SIZE(values
); i
++) {
2345 enum winreg_Type type
;
2346 union spoolss_PrinterData data
;
2348 r
.in
.handle
= handle
;
2349 r
.in
.value_name
= values
[i
];
2351 r
.in
.data
.string
= "dog";
2353 torture_comment(tctx
, "Testing SetPrinterData(%s)\n",
2356 status
= dcerpc_spoolss_SetPrinterData(p
, tctx
, &r
);
2358 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinterData failed");
2359 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinterData failed");
2361 if (!test_GetPrinterData(tctx
, p
, handle
, r
.in
.value_name
, &type
, &data
)) {
2365 torture_assert_int_equal(tctx
, r
.in
.type
, type
, "type mismatch");
2366 torture_assert_str_equal(tctx
, r
.in
.data
.string
, data
.string
, "data mismatch");
2368 if (!test_DeletePrinterData(tctx
, p
, handle
, r
.in
.value_name
)) {
2376 static bool test_EnumPrinterKey(struct torture_context
*tctx
,
2377 struct dcerpc_pipe
*p
,
2378 struct policy_handle
*handle
,
2379 const char *key_name
,
2380 const char ***array
);
2382 static bool test_SetPrinterDataEx(struct torture_context
*tctx
,
2383 struct dcerpc_pipe
*p
,
2384 struct policy_handle
*handle
)
2387 struct spoolss_SetPrinterDataEx r
;
2388 const char *value_name
= "dog";
2389 const char *keys
[] = {
2392 "torturedataex_with_subkey\\subkey",
2393 "torturedataex_with_subkey\\subkey:0",
2394 "torturedataex_with_subkey\\subkey:1",
2395 "torturedataex_with_subkey\\subkey\\subsubkey",
2396 "torturedataex_with_subkey\\subkey\\subsubkey:0",
2397 "torturedataex_with_subkey\\subkey\\subsubkey:1",
2404 DATA_BLOB blob
= data_blob_string_const("catfoobar");
2407 for (i
=0; i
< ARRAY_SIZE(keys
); i
++) {
2411 enum winreg_Type type
;
2412 const char **subkeys
;
2413 union spoolss_PrinterData data
;
2415 r
.in
.handle
= handle
;
2416 r
.in
.key_name
= keys
[i
];
2417 r
.in
.value_name
= value_name
;
2418 r
.in
.type
= REG_BINARY
;
2419 r
.in
.data
.binary
= blob
;
2421 torture_comment(tctx
, "Testing SetPrinterDataEx(%s - %s)\n", r
.in
.key_name
, value_name
);
2423 status
= dcerpc_spoolss_SetPrinterDataEx(p
, tctx
, &r
);
2425 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinterDataEx failed");
2426 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinterDataEx failed");
2428 key
= talloc_strdup(tctx
, r
.in
.key_name
);
2430 if (!test_GetPrinterDataEx(tctx
, p
, handle
, r
.in
.key_name
, value_name
, &type
, &data
)) {
2434 torture_assert_int_equal(tctx
, r
.in
.type
, type
, "type mismatch");
2435 torture_assert_data_blob_equal(tctx
, blob
, data
.binary
, "data mismatch");
2437 if (!test_EnumPrinterDataEx(tctx
, p
, handle
, r
.in
.key_name
)) {
2441 if (!test_DeletePrinterDataEx(tctx
, p
, handle
, r
.in
.key_name
, value_name
)) {
2445 c
= strchr(key
, '\\');
2449 /* we have subkeys */
2453 if (!test_EnumPrinterKey(tctx
, p
, handle
, key
, &subkeys
)) {
2457 for (i
=0; subkeys
&& subkeys
[i
]; i
++) {
2459 const char *current_key
= talloc_asprintf(tctx
, "%s\\%s", key
, subkeys
[i
]);
2461 if (!test_DeletePrinterKey(tctx
, p
, handle
, current_key
)) {
2466 if (!test_DeletePrinterKey(tctx
, p
, handle
, key
)) {
2471 if (!test_DeletePrinterKey(tctx
, p
, handle
, key
)) {
2481 static bool test_SecondaryClosePrinter(struct torture_context
*tctx
,
2482 struct dcerpc_pipe
*p
,
2483 struct policy_handle
*handle
)
2486 struct dcerpc_binding
*b
;
2487 struct dcerpc_pipe
*p2
;
2488 struct spoolss_ClosePrinter cp
;
2490 /* only makes sense on SMB */
2491 if (p
->conn
->transport
.transport
!= NCACN_NP
) {
2495 torture_comment(tctx
, "testing close on secondary pipe\n");
2497 status
= dcerpc_parse_binding(tctx
, p
->conn
->binding_string
, &b
);
2498 torture_assert_ntstatus_ok(tctx
, status
, "Failed to parse dcerpc binding");
2500 status
= dcerpc_secondary_connection(p
, &p2
, b
);
2501 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create secondary connection");
2503 status
= dcerpc_bind_auth_none(p2
, &ndr_table_spoolss
);
2504 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create bind on secondary connection");
2506 cp
.in
.handle
= handle
;
2507 cp
.out
.handle
= handle
;
2509 status
= dcerpc_spoolss_ClosePrinter(p2
, tctx
, &cp
);
2510 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_NET_WRITE_FAULT
,
2511 "ERROR: Allowed close on secondary connection");
2513 torture_assert_int_equal(tctx
, p2
->last_fault_code
, DCERPC_FAULT_CONTEXT_MISMATCH
,
2514 "Unexpected fault code");
2521 static bool test_OpenPrinter_badname(struct torture_context
*tctx
,
2522 struct dcerpc_pipe
*p
, const char *name
)
2525 struct spoolss_OpenPrinter op
;
2526 struct spoolss_OpenPrinterEx opEx
;
2527 struct policy_handle handle
;
2530 op
.in
.printername
= name
;
2531 op
.in
.datatype
= NULL
;
2532 op
.in
.devmode_ctr
.devmode
= NULL
;
2533 op
.in
.access_mask
= 0;
2534 op
.out
.handle
= &handle
;
2536 torture_comment(tctx
, "\nTesting OpenPrinter(%s) with bad name\n", op
.in
.printername
);
2538 status
= dcerpc_spoolss_OpenPrinter(p
, tctx
, &op
);
2539 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
2540 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME
,op
.out
.result
)) {
2541 torture_comment(tctx
, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
2542 name
, win_errstr(op
.out
.result
));
2545 if (W_ERROR_IS_OK(op
.out
.result
)) {
2546 ret
&=test_ClosePrinter(tctx
, p
, &handle
);
2549 opEx
.in
.printername
= name
;
2550 opEx
.in
.datatype
= NULL
;
2551 opEx
.in
.devmode_ctr
.devmode
= NULL
;
2552 opEx
.in
.access_mask
= 0;
2554 opEx
.in
.userlevel
.level1
= NULL
;
2555 opEx
.out
.handle
= &handle
;
2557 torture_comment(tctx
, "Testing OpenPrinterEx(%s) with bad name\n", opEx
.in
.printername
);
2559 status
= dcerpc_spoolss_OpenPrinterEx(p
, tctx
, &opEx
);
2560 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinterEx failed");
2561 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM
,opEx
.out
.result
)) {
2562 torture_comment(tctx
, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
2563 name
, win_errstr(opEx
.out
.result
));
2566 if (W_ERROR_IS_OK(opEx
.out
.result
)) {
2567 ret
&=test_ClosePrinter(tctx
, p
, &handle
);
2573 static bool test_OpenPrinter(struct torture_context
*tctx
,
2574 struct dcerpc_pipe
*p
,
2578 struct spoolss_OpenPrinter r
;
2579 struct policy_handle handle
;
2582 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s\\%s", dcerpc_server_name(p
), name
);
2583 r
.in
.datatype
= NULL
;
2584 r
.in
.devmode_ctr
.devmode
= NULL
;
2585 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
2586 r
.out
.handle
= &handle
;
2588 torture_comment(tctx
, "Testing OpenPrinter(%s)\n", r
.in
.printername
);
2590 status
= dcerpc_spoolss_OpenPrinter(p
, tctx
, &r
);
2592 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
2594 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenPrinter failed");
2596 if (!test_GetPrinter(tctx
, p
, &handle
)) {
2600 if (!torture_setting_bool(tctx
, "samba3", false)) {
2601 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
2606 if (!test_ClosePrinter(tctx
, p
, &handle
)) {
2613 static bool call_OpenPrinterEx(struct torture_context
*tctx
,
2614 struct dcerpc_pipe
*p
,
2615 const char *name
, struct policy_handle
*handle
)
2617 struct spoolss_OpenPrinterEx r
;
2618 struct spoolss_UserLevel1 userlevel1
;
2621 if (name
&& name
[0]) {
2622 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s\\%s",
2623 dcerpc_server_name(p
), name
);
2625 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s",
2626 dcerpc_server_name(p
));
2629 r
.in
.datatype
= NULL
;
2630 r
.in
.devmode_ctr
.devmode
= NULL
;
2631 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
2633 r
.in
.userlevel
.level1
= &userlevel1
;
2634 r
.out
.handle
= handle
;
2636 userlevel1
.size
= 1234;
2637 userlevel1
.client
= "hello";
2638 userlevel1
.user
= "spottyfoot!";
2639 userlevel1
.build
= 1;
2640 userlevel1
.major
= 2;
2641 userlevel1
.minor
= 3;
2642 userlevel1
.processor
= 4;
2644 torture_comment(tctx
, "Testing OpenPrinterEx(%s)\n", r
.in
.printername
);
2646 status
= dcerpc_spoolss_OpenPrinterEx(p
, tctx
, &r
);
2648 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinterEx failed");
2650 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenPrinterEx failed");
2655 static bool test_OpenPrinterEx(struct torture_context
*tctx
,
2656 struct dcerpc_pipe
*p
,
2659 struct policy_handle handle
;
2662 if (!call_OpenPrinterEx(tctx
, p
, name
, &handle
)) {
2666 if (!test_GetPrinter(tctx
, p
, &handle
)) {
2670 if (!test_EnumForms(tctx
, p
, &handle
, false)) {
2674 if (!test_AddForm(tctx
, p
, &handle
, false)) {
2678 if (!test_EnumPrinterData(tctx
, p
, &handle
)) {
2682 if (!test_EnumPrinterDataEx(tctx
, p
, &handle
, "PrinterDriverData")) {
2686 if (!test_printer_keys(tctx
, p
, &handle
)) {
2690 if (!test_PausePrinter(tctx
, p
, &handle
)) {
2694 if (!test_DoPrintTest(tctx
, p
, &handle
)) {
2698 if (!test_ResumePrinter(tctx
, p
, &handle
)) {
2702 if (!test_SetPrinterData(tctx
, p
, &handle
)) {
2706 if (!test_SetPrinterDataEx(tctx
, p
, &handle
)) {
2710 if (!torture_setting_bool(tctx
, "samba3", false)) {
2711 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
2716 if (!test_ClosePrinter(tctx
, p
, &handle
)) {
2723 static bool test_EnumPrinters_old(struct torture_context
*tctx
, struct dcerpc_pipe
*p
)
2725 struct spoolss_EnumPrinters r
;
2727 uint16_t levels
[] = {1, 2, 4, 5};
2731 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
2732 union spoolss_PrinterInfo
*info
;
2737 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
2739 r
.in
.level
= levels
[i
];
2742 r
.out
.needed
= &needed
;
2743 r
.out
.count
= &count
;
2746 torture_comment(tctx
, "Testing EnumPrinters level %u\n", r
.in
.level
);
2748 status
= dcerpc_spoolss_EnumPrinters(p
, tctx
, &r
);
2749 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
2751 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2752 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2753 data_blob_clear(&blob
);
2754 r
.in
.buffer
= &blob
;
2755 r
.in
.offered
= needed
;
2756 status
= dcerpc_spoolss_EnumPrinters(p
, tctx
, &r
);
2759 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
2761 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
2764 torture_comment(tctx
, "No printers returned\n");
2768 for (j
=0;j
<count
;j
++) {
2769 if (r
.in
.level
== 1) {
2770 char *unc
= talloc_strdup(tctx
, info
[j
].info1
.name
);
2773 if (unc
[0] == '\\' && unc
[1] == '\\') {
2776 slash
= strchr(unc
, '\\');
2781 if (!test_OpenPrinter(tctx
, p
, name
)) {
2784 if (!test_OpenPrinterEx(tctx
, p
, name
)) {
2794 static bool test_GetPrinterDriver(struct torture_context
*tctx
,
2795 struct dcerpc_pipe
*p
,
2796 struct policy_handle
*handle
,
2797 const char *driver_name
)
2799 struct spoolss_GetPrinterDriver r
;
2802 r
.in
.handle
= handle
;
2803 r
.in
.architecture
= "W32X86";
2807 r
.out
.needed
= &needed
;
2809 torture_comment(tctx
, "Testing GetPrinterDriver level %d\n", r
.in
.level
);
2811 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver(p
, tctx
, &r
),
2812 "failed to call GetPrinterDriver");
2813 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2814 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2815 data_blob_clear(&blob
);
2816 r
.in
.buffer
= &blob
;
2817 r
.in
.offered
= needed
;
2818 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver(p
, tctx
, &r
),
2819 "failed to call GetPrinterDriver");
2822 torture_assert_werr_ok(tctx
, r
.out
.result
,
2823 "failed to call GetPrinterDriver");
2828 static bool test_GetPrinterDriver2(struct torture_context
*tctx
,
2829 struct dcerpc_pipe
*p
,
2830 struct policy_handle
*handle
,
2831 const char *driver_name
)
2833 struct spoolss_GetPrinterDriver2 r
;
2835 uint32_t server_major_version
;
2836 uint32_t server_minor_version
;
2838 r
.in
.handle
= handle
;
2839 r
.in
.architecture
= "W32X86";
2843 r
.in
.client_major_version
= 0;
2844 r
.in
.client_minor_version
= 0;
2845 r
.out
.needed
= &needed
;
2846 r
.out
.server_major_version
= &server_major_version
;
2847 r
.out
.server_minor_version
= &server_minor_version
;
2849 torture_comment(tctx
, "Testing GetPrinterDriver2 level %d\n", r
.in
.level
);
2851 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver2(p
, tctx
, &r
),
2852 "failed to call GetPrinterDriver2");
2853 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2854 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2855 data_blob_clear(&blob
);
2856 r
.in
.buffer
= &blob
;
2857 r
.in
.offered
= needed
;
2858 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver2(p
, tctx
, &r
),
2859 "failed to call GetPrinterDriver2");
2862 torture_assert_werr_ok(tctx
, r
.out
.result
,
2863 "failed to call GetPrinterDriver2");
2868 static bool test_EnumPrinterDrivers_old(struct torture_context
*tctx
,
2869 struct dcerpc_pipe
*p
)
2871 struct spoolss_EnumPrinterDrivers r
;
2873 uint16_t levels
[] = {1, 2, 3, 4, 5, 6};
2876 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
2880 union spoolss_DriverInfo
*info
;
2882 r
.in
.server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
2883 r
.in
.environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
2884 r
.in
.level
= levels
[i
];
2887 r
.out
.needed
= &needed
;
2888 r
.out
.count
= &count
;
2891 torture_comment(tctx
, "Testing EnumPrinterDrivers level %u\n", r
.in
.level
);
2893 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, tctx
, &r
);
2895 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterDrivers failed");
2897 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2898 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2899 data_blob_clear(&blob
);
2900 r
.in
.buffer
= &blob
;
2901 r
.in
.offered
= needed
;
2902 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, tctx
, &r
);
2905 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterDrivers failed");
2907 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDrivers failed");
2910 torture_comment(tctx
, "No printer drivers returned\n");
2918 static bool test_DeletePrinter(struct torture_context
*tctx
,
2919 struct dcerpc_pipe
*p
,
2920 struct policy_handle
*handle
)
2922 struct spoolss_DeletePrinter r
;
2924 torture_comment(tctx
, "Testing DeletePrinter\n");
2926 r
.in
.handle
= handle
;
2928 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_DeletePrinter(p
, tctx
, &r
),
2929 "failed to delete printer");
2930 torture_assert_werr_ok(tctx
, r
.out
.result
,
2931 "failed to delete printer");
2936 static bool test_EnumPrinters_findname(struct torture_context
*tctx
,
2937 struct dcerpc_pipe
*p
,
2943 struct spoolss_EnumPrinters e
;
2945 union spoolss_PrinterInfo
*info
;
2956 e
.out
.count
= &count
;
2958 e
.out
.needed
= &needed
;
2960 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters(p
, tctx
, &e
),
2961 "failed to enum printers");
2963 if (W_ERROR_EQUAL(e
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2964 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2965 data_blob_clear(&blob
);
2966 e
.in
.buffer
= &blob
;
2967 e
.in
.offered
= needed
;
2969 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters(p
, tctx
, &e
),
2970 "failed to enum printers");
2973 torture_assert_werr_ok(tctx
, e
.out
.result
,
2974 "failed to enum printers");
2976 for (i
=0; i
< count
; i
++) {
2978 const char *current
= NULL
;
2982 current
= info
[i
].info1
.name
;
2986 if (strequal(current
, name
)) {
2995 static bool test_AddPrinter_wellknown(struct torture_context
*tctx
,
2996 struct dcerpc_pipe
*p
,
2997 const char *printername
,
3001 struct spoolss_AddPrinter r
;
3002 struct spoolss_AddPrinterEx rex
;
3003 struct spoolss_SetPrinterInfoCtr info_ctr
;
3004 struct spoolss_SetPrinterInfo1 info1
;
3005 struct spoolss_DevmodeContainer devmode_ctr
;
3006 struct sec_desc_buf secdesc_ctr
;
3007 struct spoolss_UserLevelCtr userlevel_ctr
;
3008 struct policy_handle handle
;
3011 ZERO_STRUCT(devmode_ctr
);
3012 ZERO_STRUCT(secdesc_ctr
);
3013 ZERO_STRUCT(userlevel_ctr
);
3016 torture_comment(tctx
, "Testing AddPrinter%s level 1\n", ex
? "Ex":"");
3018 /* try to add printer to wellknown printer list (level 1) */
3020 userlevel_ctr
.level
= 1;
3022 info_ctr
.info
.info1
= &info1
;
3025 rex
.in
.server
= NULL
;
3026 rex
.in
.info_ctr
= &info_ctr
;
3027 rex
.in
.devmode_ctr
= &devmode_ctr
;
3028 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
3029 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
3030 rex
.out
.handle
= &handle
;
3033 r
.in
.info_ctr
= &info_ctr
;
3034 r
.in
.devmode_ctr
= &devmode_ctr
;
3035 r
.in
.secdesc_ctr
= &secdesc_ctr
;
3036 r
.out
.handle
= &handle
;
3038 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3039 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3040 "failed to add printer");
3041 result
= ex
? rex
.out
.result
: r
.out
.result
;
3042 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
3043 "unexpected result code");
3045 info1
.name
= printername
;
3046 info1
.flags
= PRINTER_ATTRIBUTE_SHARED
;
3048 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3049 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3050 "failed to add printer");
3051 result
= ex
? rex
.out
.result
: r
.out
.result
;
3052 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
3053 "unexpected result code");
3055 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
3056 better do a real check to see the printer is really there */
3058 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, p
,
3059 PRINTER_ENUM_NETWORK
, 1,
3062 "failed to enum printers");
3064 torture_assert(tctx
, found
, "failed to find newly added printer");
3068 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3069 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3070 "failed to add printer");
3071 result
= ex
? rex
.out
.result
: r
.out
.result
;
3072 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
3073 "unexpected result code");
3075 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
3076 better do a real check to see the printer has really been removed
3077 from the well known printer list */
3081 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, p
,
3082 PRINTER_ENUM_NETWORK
, 1,
3085 "failed to enum printers");
3087 torture_assert(tctx
, !found
, "printer still in well known printer list");
3092 static bool test_AddPrinter_normal(struct torture_context
*tctx
,
3093 struct dcerpc_pipe
*p
,
3094 struct policy_handle
*handle_p
,
3095 const char *printername
,
3096 const char *drivername
,
3097 const char *portname
,
3101 struct spoolss_AddPrinter r
;
3102 struct spoolss_AddPrinterEx rex
;
3103 struct spoolss_SetPrinterInfoCtr info_ctr
;
3104 struct spoolss_SetPrinterInfo2 info2
;
3105 struct spoolss_DevmodeContainer devmode_ctr
;
3106 struct sec_desc_buf secdesc_ctr
;
3107 struct spoolss_UserLevelCtr userlevel_ctr
;
3108 struct policy_handle handle
;
3111 ZERO_STRUCT(devmode_ctr
);
3112 ZERO_STRUCT(secdesc_ctr
);
3113 ZERO_STRUCT(userlevel_ctr
);
3115 torture_comment(tctx
, "Testing AddPrinter%s level 2\n", ex
? "Ex":"");
3117 userlevel_ctr
.level
= 1;
3119 rex
.in
.server
= NULL
;
3120 rex
.in
.info_ctr
= &info_ctr
;
3121 rex
.in
.devmode_ctr
= &devmode_ctr
;
3122 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
3123 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
3124 rex
.out
.handle
= &handle
;
3127 r
.in
.info_ctr
= &info_ctr
;
3128 r
.in
.devmode_ctr
= &devmode_ctr
;
3129 r
.in
.secdesc_ctr
= &secdesc_ctr
;
3130 r
.out
.handle
= &handle
;
3134 /* try to add printer to printer list (level 2) */
3138 info_ctr
.info
.info2
= &info2
;
3141 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3142 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3143 "failed to add printer");
3144 result
= ex
? rex
.out
.result
: r
.out
.result
;
3145 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
3146 "unexpected result code");
3148 info2
.printername
= printername
;
3150 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3151 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3152 "failed to add printer");
3153 result
= ex
? rex
.out
.result
: r
.out
.result
;
3155 if (W_ERROR_EQUAL(result
, WERR_PRINTER_ALREADY_EXISTS
)) {
3156 struct policy_handle printer_handle
;
3158 torture_assert(tctx
, call_OpenPrinterEx(tctx
, p
, printername
, &printer_handle
),
3159 "failed to open printer handle");
3161 torture_assert(tctx
, test_DeletePrinter(tctx
, p
, &printer_handle
),
3162 "failed to delete printer");
3164 torture_assert(tctx
, test_ClosePrinter(tctx
, p
, &printer_handle
),
3165 "failed to close server handle");
3170 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PORT
,
3171 "unexpected result code");
3173 info2
.portname
= portname
;
3175 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3176 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3177 "failed to add printer");
3178 result
= ex
? rex
.out
.result
: r
.out
.result
;
3179 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTER_DRIVER
,
3180 "unexpected result code");
3182 info2
.drivername
= drivername
;
3184 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3185 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3186 "failed to add printer");
3187 result
= ex
? rex
.out
.result
: r
.out
.result
;
3188 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTPROCESSOR
,
3189 "unexpected result code");
3191 info2
.printprocessor
= "winprint";
3193 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3194 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3195 "failed to add printer");
3196 result
= ex
? rex
.out
.result
: r
.out
.result
;
3197 torture_assert_werr_ok(tctx
, result
,
3198 "failed to add printer");
3202 /* we are paranoid, really check if the printer is there now */
3204 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, p
,
3205 PRINTER_ENUM_LOCAL
, 1,
3208 "failed to enum printers");
3209 torture_assert(tctx
, found
, "failed to find newly added printer");
3211 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3212 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3213 "failed to add printer");
3214 result
= ex
? rex
.out
.result
: r
.out
.result
;
3215 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
3216 "unexpected result code");
3221 static bool test_AddPrinterEx(struct torture_context
*tctx
,
3222 struct dcerpc_pipe
*p
,
3223 struct policy_handle
*handle_p
,
3224 const char *printername
,
3225 const char *drivername
,
3226 const char *portname
)
3230 if (!torture_setting_bool(tctx
, "samba3", false)) {
3231 if (!test_AddPrinter_wellknown(tctx
, p
, TORTURE_WELLKNOWN_PRINTER_EX
, true)) {
3232 torture_comment(tctx
, "failed to add printer to well known list\n");
3237 if (!test_AddPrinter_normal(tctx
, p
, handle_p
,
3238 printername
, drivername
, portname
,
3240 torture_comment(tctx
, "failed to add printer to printer list\n");
3247 static bool test_AddPrinter(struct torture_context
*tctx
,
3248 struct dcerpc_pipe
*p
,
3249 struct policy_handle
*handle_p
,
3250 const char *printername
,
3251 const char *drivername
,
3252 const char *portname
)
3256 if (!torture_setting_bool(tctx
, "samba3", false)) {
3257 if (!test_AddPrinter_wellknown(tctx
, p
, TORTURE_WELLKNOWN_PRINTER
, false)) {
3258 torture_comment(tctx
, "failed to add printer to well known list\n");
3263 if (!test_AddPrinter_normal(tctx
, p
, handle_p
,
3264 printername
, drivername
, portname
,
3266 torture_comment(tctx
, "failed to add printer to printer list\n");
3273 static bool test_printer_info(struct torture_context
*tctx
,
3274 struct dcerpc_pipe
*p
,
3275 struct policy_handle
*handle
)
3279 if (!test_PrinterInfo(tctx
, p
, handle
)) {
3283 if (!test_SetPrinter_errors(tctx
, p
, handle
)) {
3290 static bool test_EnumPrinterKey(struct torture_context
*tctx
,
3291 struct dcerpc_pipe
*p
,
3292 struct policy_handle
*handle
,
3293 const char *key_name
,
3294 const char ***array
)
3296 struct spoolss_EnumPrinterKey r
;
3298 struct spoolss_StringArray2 key_buffer
;
3300 r
.in
.handle
= handle
;
3301 r
.in
.key_name
= key_name
;
3303 r
.out
.key_buffer
= &key_buffer
;
3304 r
.out
.needed
= &needed
;
3306 torture_comment(tctx
, "Testing EnumPrinterKey(%s)\n", r
.in
.key_name
);
3308 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterKey(p
, tctx
, &r
),
3309 "failed to call EnumPrinterKey");
3310 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
3311 torture_assert(tctx
, (key_buffer
._ndr_size
== 0),
3312 talloc_asprintf(tctx
, "EnumPrinterKey did not return 0 _ndr_size (but %d), windows clients would abort here!", key_buffer
._ndr_size
));
3313 r
.in
.offered
= needed
;
3314 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterKey(p
, tctx
, &r
),
3315 "failed to call EnumPrinterKey");
3317 torture_assert_werr_ok(tctx
, r
.out
.result
,
3318 "failed to call EnumPrinterKey");
3320 torture_assert(tctx
, (key_buffer
._ndr_size
* 2 == needed
),
3321 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
3322 key_buffer
._ndr_size
, needed
/2));
3325 *array
= key_buffer
.string
;
3331 bool test_printer_keys(struct torture_context
*tctx
,
3332 struct dcerpc_pipe
*p
,
3333 struct policy_handle
*handle
)
3335 const char **key_array
= NULL
;
3338 torture_assert(tctx
, test_EnumPrinterKey(tctx
, p
, handle
, "", &key_array
),
3339 "failed to call test_EnumPrinterKey");
3341 for (i
=0; key_array
&& key_array
[i
]; i
++) {
3342 torture_assert(tctx
, test_EnumPrinterKey(tctx
, p
, handle
, key_array
[i
], NULL
),
3343 "failed to call test_EnumPrinterKey");
3345 for (i
=0; key_array
&& key_array
[i
]; i
++) {
3346 torture_assert(tctx
, test_EnumPrinterDataEx(tctx
, p
, handle
, key_array
[i
]),
3347 "failed to call test_EnumPrinterDataEx");
3353 static bool test_printer(struct torture_context
*tctx
,
3354 struct dcerpc_pipe
*p
)
3357 struct policy_handle handle
[2];
3359 const char *drivername
= "Microsoft XPS Document Writer";
3360 const char *portname
= "LPT1:";
3362 /* test printer created via AddPrinter */
3364 if (!test_AddPrinter(tctx
, p
, &handle
[0], TORTURE_PRINTER
, drivername
, portname
)) {
3368 if (!test_printer_info(tctx
, p
, &handle
[0])) {
3372 if (!test_printer_keys(tctx
, p
, &handle
[0])) {
3376 if (!test_DeletePrinter(tctx
, p
, &handle
[0])) {
3380 if (!test_EnumPrinters_findname(tctx
, p
, PRINTER_ENUM_LOCAL
, 1,
3381 TORTURE_PRINTER
, &found
)) {
3385 torture_assert(tctx
, !found
, "deleted printer still there");
3387 /* test printer created via AddPrinterEx */
3389 if (!test_AddPrinterEx(tctx
, p
, &handle
[1], TORTURE_PRINTER_EX
, drivername
, portname
)) {
3393 if (!test_printer_info(tctx
, p
, &handle
[1])) {
3397 if (!test_printer_keys(tctx
, p
, &handle
[1])) {
3401 if (!test_DeletePrinter(tctx
, p
, &handle
[1])) {
3405 if (!test_EnumPrinters_findname(tctx
, p
, PRINTER_ENUM_LOCAL
, 1,
3406 TORTURE_PRINTER_EX
, &found
)) {
3410 torture_assert(tctx
, !found
, "deleted printer still there");
3415 bool torture_rpc_spoolss(struct torture_context
*torture
)
3418 struct dcerpc_pipe
*p
;
3420 struct test_spoolss_context
*ctx
;
3422 status
= torture_rpc_connection(torture
, &p
, &ndr_table_spoolss
);
3423 if (!NT_STATUS_IS_OK(status
)) {
3427 ctx
= talloc_zero(torture
, struct test_spoolss_context
);
3429 ret
&= test_OpenPrinter_server(torture
, p
, &ctx
->server_handle
);
3430 ret
&= test_GetPrinterData_list(torture
, p
, &ctx
->server_handle
);
3431 ret
&= test_EnumForms(torture
, p
, &ctx
->server_handle
, true);
3432 ret
&= test_AddForm(torture
, p
, &ctx
->server_handle
, true);
3433 ret
&= test_EnumPorts(torture
, p
, ctx
);
3434 ret
&= test_GetPrinterDriverDirectory(torture
, p
, ctx
);
3435 ret
&= test_GetPrintProcessorDirectory(torture
, p
, ctx
);
3436 ret
&= test_EnumPrinterDrivers(torture
, p
, ctx
, SPOOLSS_ARCHITECTURE_NT_X86
);
3437 ret
&= test_EnumPrinterDrivers(torture
, p
, ctx
, SPOOLSS_ARCHITECTURE_ALL
);
3438 ret
&= test_EnumMonitors(torture
, p
, ctx
);
3439 ret
&= test_EnumPrintProcessors(torture
, p
, ctx
);
3440 ret
&= test_EnumPrintProcDataTypes(torture
, p
, ctx
);
3441 ret
&= test_EnumPrinters(torture
, p
, ctx
);
3442 ret
&= test_OpenPrinter_badname(torture
, p
, "__INVALID_PRINTER__");
3443 ret
&= test_OpenPrinter_badname(torture
, p
, "\\\\__INVALID_HOST__");
3444 ret
&= test_OpenPrinter_badname(torture
, p
, "");
3445 ret
&= test_OpenPrinter_badname(torture
, p
, "\\\\\\");
3446 ret
&= test_OpenPrinter_badname(torture
, p
, "\\\\\\__INVALID_PRINTER__");
3447 ret
&= test_OpenPrinter_badname(torture
, p
, talloc_asprintf(torture
, "\\\\%s\\", dcerpc_server_name(p
)));
3448 ret
&= test_OpenPrinter_badname(torture
, p
,
3449 talloc_asprintf(torture
, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p
)));
3452 ret
&= test_AddPort(torture
, p
);
3453 ret
&= test_EnumPorts_old(torture
, p
);
3454 ret
&= test_EnumPrinters_old(torture
, p
);
3455 ret
&= test_EnumPrinterDrivers_old(torture
, p
);
3460 struct torture_suite
*torture_rpc_spoolss_printer(TALLOC_CTX
*mem_ctx
)
3462 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "SPOOLSS-PRINTER");
3464 struct torture_rpc_tcase
*tcase
= torture_suite_add_rpc_iface_tcase(suite
,
3465 "printer", &ndr_table_spoolss
);
3467 torture_rpc_tcase_add_test(tcase
, "printer", test_printer
);