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
[8];
46 union spoolss_DriverInfo
*drivers
[8];
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_UINT64(tctx, c, r, e) do {\
84 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
85 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
89 #define COMPARE_NTTIME(tctx, c, r, e) do {\
90 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
91 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
94 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
100 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
103 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
105 for (__i=0;c.e[__i] != NULL; __i++) { \
106 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
110 static bool test_OpenPrinter_server(struct torture_context
*tctx
,
111 struct dcerpc_pipe
*p
,
112 struct policy_handle
*server_handle
)
115 struct spoolss_OpenPrinter op
;
117 op
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
118 op
.in
.datatype
= NULL
;
119 op
.in
.devmode_ctr
.devmode
= NULL
;
120 op
.in
.access_mask
= 0;
121 op
.out
.handle
= server_handle
;
123 torture_comment(tctx
, "Testing OpenPrinter(%s)\n", op
.in
.printername
);
125 status
= dcerpc_spoolss_OpenPrinter(p
, tctx
, &op
);
126 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_OpenPrinter failed");
127 torture_assert_werr_ok(tctx
, op
.out
.result
, "dcerpc_spoolss_OpenPrinter failed");
132 static bool test_EnumPorts(struct torture_context
*tctx
,
133 struct dcerpc_pipe
*p
,
134 struct test_spoolss_context
*ctx
)
137 struct spoolss_EnumPorts r
;
138 uint16_t levels
[] = { 1, 2 };
141 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
142 int level
= levels
[i
];
146 union spoolss_PortInfo
*info
;
148 r
.in
.servername
= "";
152 r
.out
.needed
= &needed
;
153 r
.out
.count
= &count
;
156 torture_comment(tctx
, "Testing EnumPorts level %u\n", r
.in
.level
);
158 status
= dcerpc_spoolss_EnumPorts(p
, ctx
, &r
);
159 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPorts failed");
160 if (W_ERROR_IS_OK(r
.out
.result
)) {
161 /* TODO: do some more checks here */
164 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
165 "EnumPorts unexpected return code");
167 blob
= data_blob_talloc(ctx
, NULL
, needed
);
168 data_blob_clear(&blob
);
170 r
.in
.offered
= needed
;
172 status
= dcerpc_spoolss_EnumPorts(p
, ctx
, &r
);
173 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPorts failed");
175 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
177 torture_assert(tctx
, info
, "EnumPorts returned no info");
179 ctx
->port_count
[level
] = count
;
180 ctx
->ports
[level
] = info
;
183 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
184 int level
= levels
[i
];
185 int old_level
= levels
[i
-1];
186 torture_assert_int_equal(tctx
, ctx
->port_count
[level
], ctx
->port_count
[old_level
],
187 "EnumPorts invalid value");
189 /* if the array sizes are not the same we would maybe segfault in the following code */
191 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
192 int level
= levels
[i
];
193 for (j
=0;j
<ctx
->port_count
[level
];j
++) {
194 union spoolss_PortInfo
*cur
= &ctx
->ports
[level
][j
];
195 union spoolss_PortInfo
*ref
= &ctx
->ports
[2][j
];
198 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, port_name
);
201 /* level 2 is our reference, and it makes no sense to compare it to itself */
210 static bool test_GetPrintProcessorDirectory(struct torture_context
*tctx
,
211 struct dcerpc_pipe
*p
,
212 struct test_spoolss_context
*ctx
)
215 struct spoolss_GetPrintProcessorDirectory r
;
230 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
233 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
239 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
240 int level
= levels
[i
].level
;
243 r
.in
.server
= levels
[i
].server
;
244 r
.in
.environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
248 r
.out
.needed
= &needed
;
250 torture_comment(tctx
, "Testing GetPrintProcessorDirectory level %u\n", r
.in
.level
);
252 status
= dcerpc_spoolss_GetPrintProcessorDirectory(p
, ctx
, &r
);
253 torture_assert_ntstatus_ok(tctx
, status
,
254 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
255 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
256 "GetPrintProcessorDirectory unexpected return code");
258 blob
= data_blob_talloc(ctx
, NULL
, needed
);
259 data_blob_clear(&blob
);
261 r
.in
.offered
= needed
;
263 status
= dcerpc_spoolss_GetPrintProcessorDirectory(p
, ctx
, &r
);
264 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
266 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrintProcessorDirectory failed");
273 static bool test_GetPrinterDriverDirectory(struct torture_context
*tctx
,
274 struct dcerpc_pipe
*p
,
275 struct test_spoolss_context
*ctx
)
278 struct spoolss_GetPrinterDriverDirectory r
;
293 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
296 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
302 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
303 int level
= levels
[i
].level
;
306 r
.in
.server
= levels
[i
].server
;
307 r
.in
.environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
311 r
.out
.needed
= &needed
;
313 torture_comment(tctx
, "Testing GetPrinterDriverDirectory level %u\n", r
.in
.level
);
315 status
= dcerpc_spoolss_GetPrinterDriverDirectory(p
, ctx
, &r
);
316 torture_assert_ntstatus_ok(tctx
, status
,
317 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
318 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
319 "GetPrinterDriverDirectory unexpected return code");
321 blob
= data_blob_talloc(ctx
, NULL
, needed
);
322 data_blob_clear(&blob
);
324 r
.in
.offered
= needed
;
326 status
= dcerpc_spoolss_GetPrinterDriverDirectory(p
, ctx
, &r
);
327 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
329 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrinterDriverDirectory failed");
335 static bool test_EnumPrinterDrivers(struct torture_context
*tctx
,
336 struct dcerpc_pipe
*p
,
337 struct test_spoolss_context
*ctx
,
338 const char *architecture
)
341 struct spoolss_EnumPrinterDrivers r
;
342 uint16_t levels
[] = { 1, 2, 3, 4, 5, 6, 8 };
345 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
346 int level
= levels
[i
];
350 union spoolss_DriverInfo
*info
;
352 /* FIXME: gd, come back and fix "" as server, and handle
353 * priority of returned error codes in torture test and samba 3
356 r
.in
.server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
357 r
.in
.environment
= architecture
;
361 r
.out
.needed
= &needed
;
362 r
.out
.count
= &count
;
365 torture_comment(tctx
, "Testing EnumPrinterDrivers level %u (%s)\n", r
.in
.level
, r
.in
.environment
);
367 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, ctx
, &r
);
368 torture_assert_ntstatus_ok(tctx
, status
,
369 "dcerpc_spoolss_EnumPrinterDrivers failed");
370 if (W_ERROR_IS_OK(r
.out
.result
)) {
371 /* TODO: do some more checks here */
374 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
375 blob
= data_blob_talloc(ctx
, NULL
, needed
);
376 data_blob_clear(&blob
);
378 r
.in
.offered
= needed
;
380 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, ctx
, &r
);
381 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinterDrivers failed");
384 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDrivers failed");
386 ctx
->driver_count
[level
] = count
;
387 ctx
->drivers
[level
] = info
;
390 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
391 int level
= levels
[i
];
392 int old_level
= levels
[i
-1];
394 torture_assert_int_equal(tctx
, ctx
->driver_count
[level
], ctx
->driver_count
[old_level
],
395 "EnumPrinterDrivers invalid value");
398 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
399 int level
= levels
[i
];
401 for (j
=0;j
<ctx
->driver_count
[level
];j
++) {
402 union spoolss_DriverInfo
*cur
= &ctx
->drivers
[level
][j
];
403 union spoolss_DriverInfo
*ref
= &ctx
->drivers
[8][j
];
407 COMPARE_STRING(tctx
, cur
->info1
, ref
->info8
, driver_name
);
410 COMPARE_UINT32(tctx
, cur
->info2
, ref
->info8
, version
);
411 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, driver_name
);
412 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, architecture
);
413 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, driver_path
);
414 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, data_file
);
415 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, config_file
);
418 COMPARE_UINT32(tctx
, cur
->info3
, ref
->info8
, version
);
419 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, driver_name
);
420 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, architecture
);
421 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, driver_path
);
422 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, data_file
);
423 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, config_file
);
424 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, help_file
);
425 COMPARE_STRING_ARRAY(tctx
, cur
->info3
, ref
->info8
, dependent_files
);
426 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, monitor_name
);
427 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, default_datatype
);
430 COMPARE_UINT32(tctx
, cur
->info4
, ref
->info8
, version
);
431 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, driver_name
);
432 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, architecture
);
433 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, driver_path
);
434 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, data_file
);
435 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, config_file
);
436 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, help_file
);
437 COMPARE_STRING_ARRAY(tctx
, cur
->info4
, ref
->info8
, dependent_files
);
438 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, monitor_name
);
439 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, default_datatype
);
440 COMPARE_STRING_ARRAY(tctx
, cur
->info4
, ref
->info8
, previous_names
);
443 COMPARE_UINT32(tctx
, cur
->info5
, ref
->info8
, version
);
444 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, driver_name
);
445 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, architecture
);
446 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, driver_path
);
447 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, data_file
);
448 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, config_file
);
449 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
450 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
451 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
454 COMPARE_UINT32(tctx
, cur
->info6
, ref
->info8
, version
);
455 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, driver_name
);
456 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, architecture
);
457 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, driver_path
);
458 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, data_file
);
459 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, config_file
);
460 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, help_file
);
461 COMPARE_STRING_ARRAY(tctx
, cur
->info6
, ref
->info8
, dependent_files
);
462 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, monitor_name
);
463 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, default_datatype
);
464 COMPARE_STRING_ARRAY(tctx
, cur
->info6
, ref
->info8
, previous_names
);
465 COMPARE_NTTIME(tctx
, cur
->info6
, ref
->info8
, driver_date
);
466 COMPARE_UINT64(tctx
, cur
->info6
, ref
->info8
, driver_version
);
467 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, manufacturer_name
);
468 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, manufacturer_url
);
469 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, hardware_id
);
470 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, provider
);
473 /* level 8 is our reference, and it makes no sense to compare it to itself */
482 static bool test_EnumMonitors(struct torture_context
*tctx
,
483 struct dcerpc_pipe
*p
,
484 struct test_spoolss_context
*ctx
)
487 struct spoolss_EnumMonitors r
;
488 uint16_t levels
[] = { 1, 2 };
491 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
492 int level
= levels
[i
];
496 union spoolss_MonitorInfo
*info
;
498 r
.in
.servername
= "";
502 r
.out
.needed
= &needed
;
503 r
.out
.count
= &count
;
506 torture_comment(tctx
, "Testing EnumMonitors level %u\n", r
.in
.level
);
508 status
= dcerpc_spoolss_EnumMonitors(p
, ctx
, &r
);
509 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumMonitors failed");
510 if (W_ERROR_IS_OK(r
.out
.result
)) {
511 /* TODO: do some more checks here */
514 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
515 "EnumMonitors failed");
517 blob
= data_blob_talloc(ctx
, NULL
, needed
);
518 data_blob_clear(&blob
);
520 r
.in
.offered
= needed
;
522 status
= dcerpc_spoolss_EnumMonitors(p
, ctx
, &r
);
523 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumMonitors failed");
525 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumMonitors failed");
527 ctx
->monitor_count
[level
] = count
;
528 ctx
->monitors
[level
] = info
;
531 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
532 int level
= levels
[i
];
533 int old_level
= levels
[i
-1];
534 torture_assert_int_equal(tctx
, ctx
->monitor_count
[level
], ctx
->monitor_count
[old_level
],
535 "EnumMonitors invalid value");
538 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
539 int level
= levels
[i
];
540 for (j
=0;j
<ctx
->monitor_count
[level
];j
++) {
541 union spoolss_MonitorInfo
*cur
= &ctx
->monitors
[level
][j
];
542 union spoolss_MonitorInfo
*ref
= &ctx
->monitors
[2][j
];
545 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, monitor_name
);
548 /* level 2 is our reference, and it makes no sense to compare it to itself */
557 static bool test_EnumPrintProcessors(struct torture_context
*tctx
,
558 struct dcerpc_pipe
*p
,
559 struct test_spoolss_context
*ctx
)
562 struct spoolss_EnumPrintProcessors r
;
563 uint16_t levels
[] = { 1 };
566 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
567 int level
= levels
[i
];
571 union spoolss_PrintProcessorInfo
*info
;
573 r
.in
.servername
= "";
574 r
.in
.environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
578 r
.out
.needed
= &needed
;
579 r
.out
.count
= &count
;
582 torture_comment(tctx
, "Testing EnumPrintProcessors level %u\n", r
.in
.level
);
584 status
= dcerpc_spoolss_EnumPrintProcessors(p
, ctx
, &r
);
585 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcessors failed");
586 if (W_ERROR_IS_OK(r
.out
.result
)) {
587 /* TODO: do some more checks here */
590 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
591 "EnumPrintProcessors unexpected return code");
593 blob
= data_blob_talloc(ctx
, NULL
, needed
);
594 data_blob_clear(&blob
);
596 r
.in
.offered
= needed
;
598 status
= dcerpc_spoolss_EnumPrintProcessors(p
, ctx
, &r
);
599 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcessors failed");
601 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrintProcessors failed");
603 ctx
->print_processor_count
[level
] = count
;
604 ctx
->print_processors
[level
] = info
;
607 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
608 int level
= levels
[i
];
609 int old_level
= levels
[i
-1];
610 torture_assert_int_equal(tctx
, ctx
->print_processor_count
[level
], ctx
->print_processor_count
[old_level
],
611 "EnumPrintProcessors failed");
614 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
615 int level
= levels
[i
];
616 for (j
=0;j
<ctx
->print_processor_count
[level
];j
++) {
618 union spoolss_PrintProcessorInfo
*cur
= &ctx
->print_processors
[level
][j
];
619 union spoolss_PrintProcessorInfo
*ref
= &ctx
->print_processors
[1][j
];
623 /* level 1 is our reference, and it makes no sense to compare it to itself */
632 static bool test_EnumPrintProcDataTypes(struct torture_context
*tctx
,
633 struct dcerpc_pipe
*p
,
634 struct test_spoolss_context
*ctx
)
637 struct spoolss_EnumPrintProcDataTypes r
;
638 uint16_t levels
[] = { 1 };
641 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
642 int level
= levels
[i
];
646 union spoolss_PrintProcDataTypesInfo
*info
;
648 r
.in
.servername
= "";
649 r
.in
.print_processor_name
= "winprint";
653 r
.out
.needed
= &needed
;
654 r
.out
.count
= &count
;
657 torture_comment(tctx
, "Testing EnumPrintProcDataTypes level %u\n", r
.in
.level
);
659 status
= dcerpc_spoolss_EnumPrintProcDataTypes(p
, ctx
, &r
);
660 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcDataType failed");
661 if (W_ERROR_IS_OK(r
.out
.result
)) {
662 /* TODO: do some more checks here */
665 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
666 "EnumPrintProcDataTypes unexpected return code");
668 blob
= data_blob_talloc(ctx
, NULL
, needed
);
669 data_blob_clear(&blob
);
671 r
.in
.offered
= needed
;
673 status
= dcerpc_spoolss_EnumPrintProcDataTypes(p
, ctx
, &r
);
674 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
676 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrintProcDataTypes failed");
683 static bool test_EnumPrinters(struct torture_context
*tctx
,
684 struct dcerpc_pipe
*p
,
685 struct test_spoolss_context
*ctx
)
687 struct spoolss_EnumPrinters r
;
689 uint16_t levels
[] = { 0, 1, 2, 4, 5 };
692 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
693 int level
= levels
[i
];
697 union spoolss_PrinterInfo
*info
;
699 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
704 r
.out
.needed
= &needed
;
705 r
.out
.count
= &count
;
708 torture_comment(tctx
, "Testing EnumPrinters level %u\n", r
.in
.level
);
710 status
= dcerpc_spoolss_EnumPrinters(p
, ctx
, &r
);
711 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinters failed");
712 if (W_ERROR_IS_OK(r
.out
.result
)) {
713 /* TODO: do some more checks here */
716 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
717 "EnumPrinters unexpected return code");
719 blob
= data_blob_talloc(ctx
, NULL
, needed
);
720 data_blob_clear(&blob
);
722 r
.in
.offered
= needed
;
724 status
= dcerpc_spoolss_EnumPrinters(p
, ctx
, &r
);
725 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinters failed");
727 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
729 ctx
->printer_count
[level
] = count
;
730 ctx
->printers
[level
] = info
;
733 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
734 int level
= levels
[i
];
735 int old_level
= levels
[i
-1];
736 torture_assert_int_equal(tctx
, ctx
->printer_count
[level
], ctx
->printer_count
[old_level
],
737 "EnumPrinters invalid value");
740 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
741 int level
= levels
[i
];
742 for (j
=0;j
<ctx
->printer_count
[level
];j
++) {
743 union spoolss_PrinterInfo
*cur
= &ctx
->printers
[level
][j
];
744 union spoolss_PrinterInfo
*ref
= &ctx
->printers
[2][j
];
747 COMPARE_STRING(tctx
, cur
->info0
, ref
->info2
, printername
);
748 COMPARE_STRING(tctx
, cur
->info0
, ref
->info2
, servername
);
749 COMPARE_UINT32(tctx
, cur
->info0
, ref
->info2
, cjobs
);
750 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
751 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
752 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
753 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
754 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
755 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
756 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
757 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
758 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
759 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
760 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
761 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
762 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
763 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
764 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
765 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
766 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
767 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
768 COMPARE_UINT32(tctx
, cur
->info0
, ref
->info2
, status
);
769 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
770 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
771 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
772 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
773 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
774 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
775 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
778 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
779 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
780 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
781 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, comment
);
784 /* level 2 is our reference, and it makes no sense to compare it to itself */
787 COMPARE_STRING(tctx
, cur
->info4
, ref
->info2
, printername
);
788 COMPARE_STRING(tctx
, cur
->info4
, ref
->info2
, servername
);
789 COMPARE_UINT32(tctx
, cur
->info4
, ref
->info2
, attributes
);
792 COMPARE_STRING(tctx
, cur
->info5
, ref
->info2
, printername
);
793 COMPARE_STRING(tctx
, cur
->info5
, ref
->info2
, portname
);
794 COMPARE_UINT32(tctx
, cur
->info5
, ref
->info2
, attributes
);
795 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
796 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
803 * - verify that the port of a printer was in the list returned by EnumPorts
809 static bool test_GetPrinter(struct torture_context
*tctx
,
810 struct dcerpc_pipe
*p
,
811 struct policy_handle
*handle
)
814 struct spoolss_GetPrinter r
;
815 uint16_t levels
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
819 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
820 r
.in
.handle
= handle
;
821 r
.in
.level
= levels
[i
];
824 r
.out
.needed
= &needed
;
826 torture_comment(tctx
, "Testing GetPrinter level %u\n", r
.in
.level
);
828 status
= dcerpc_spoolss_GetPrinter(p
, tctx
, &r
);
829 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinter failed");
831 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
832 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
833 data_blob_clear(&blob
);
835 r
.in
.offered
= needed
;
836 status
= dcerpc_spoolss_GetPrinter(p
, tctx
, &r
);
839 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinter failed");
841 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrinter failed");
847 static bool test_SetPrinter_errors(struct torture_context
*tctx
,
848 struct dcerpc_pipe
*p
,
849 struct policy_handle
*handle
)
851 struct spoolss_SetPrinter r
;
852 uint16_t levels
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
855 struct spoolss_SetPrinterInfoCtr info_ctr
;
856 struct spoolss_DevmodeContainer devmode_ctr
;
857 struct sec_desc_buf secdesc_ctr
;
860 info_ctr
.info
.info0
= NULL
;
862 ZERO_STRUCT(devmode_ctr
);
863 ZERO_STRUCT(secdesc_ctr
);
865 r
.in
.handle
= handle
;
866 r
.in
.info_ctr
= &info_ctr
;
867 r
.in
.devmode_ctr
= &devmode_ctr
;
868 r
.in
.secdesc_ctr
= &secdesc_ctr
;
871 torture_comment(tctx
, "Testing SetPrinter all zero\n");
873 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter(p
, tctx
, &r
),
874 "failed to call SetPrinter");
875 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
876 "failed to call SetPrinter");
879 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
881 struct spoolss_SetPrinterInfo0 info0
;
882 struct spoolss_SetPrinterInfo1 info1
;
883 struct spoolss_SetPrinterInfo2 info2
;
884 struct spoolss_SetPrinterInfo3 info3
;
885 struct spoolss_SetPrinterInfo4 info4
;
886 struct spoolss_SetPrinterInfo5 info5
;
887 struct spoolss_SetPrinterInfo6 info6
;
888 struct spoolss_SetPrinterInfo7 info7
;
889 struct spoolss_DeviceModeInfo info8
;
890 struct spoolss_DeviceModeInfo info9
;
893 info_ctr
.level
= levels
[i
];
897 info_ctr
.info
.info0
= &info0
;
901 info_ctr
.info
.info1
= &info1
;
905 info_ctr
.info
.info2
= &info2
;
909 info_ctr
.info
.info3
= &info3
;
913 info_ctr
.info
.info4
= &info4
;
917 info_ctr
.info
.info5
= &info5
;
921 info_ctr
.info
.info6
= &info6
;
925 info_ctr
.info
.info7
= &info7
;
929 info_ctr
.info
.info8
= &info8
;
933 info_ctr
.info
.info9
= &info9
;
937 torture_comment(tctx
, "Testing SetPrinter level %d, command %d\n",
938 info_ctr
.level
, r
.in
.command
);
940 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter(p
, tctx
, &r
),
941 "failed to call SetPrinter");
943 switch (r
.in
.command
) {
944 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
: /* 0 */
945 /* is ignored for all levels other then 0 */
946 if (info_ctr
.level
> 0) {
950 case SPOOLSS_PRINTER_CONTROL_PAUSE
: /* 1 */
951 case SPOOLSS_PRINTER_CONTROL_RESUME
: /* 2 */
952 case SPOOLSS_PRINTER_CONTROL_PURGE
: /* 3 */
953 if (info_ctr
.level
> 0) {
954 /* is invalid for all levels other then 0 */
955 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PRINTER_COMMAND
,
956 "unexpected error code returned");
959 torture_assert_werr_ok(tctx
, r
.out
.result
,
960 "failed to call SetPrinter with non 0 command");
965 case SPOOLSS_PRINTER_CONTROL_SET_STATUS
: /* 4 */
966 /* FIXME: gd needs further investigation */
968 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PRINTER_COMMAND
,
969 "unexpected error code returned");
973 switch (info_ctr
.level
) {
975 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
,
976 "unexpected error code returned");
979 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_PRINTER_DRIVER
,
980 "unexpected error code returned");
986 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
987 "unexpected error code returned");
990 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_NOT_SUPPORTED
,
991 "unexpected error code returned");
994 torture_assert_werr_ok(tctx
, r
.out
.result
,
995 "failed to call SetPrinter");
1000 if (r
.in
.command
< 5) {
1008 static void clear_info2(struct spoolss_SetPrinterInfoCtr
*r
)
1010 if ((r
->level
== 2) && (r
->info
.info2
)) {
1011 r
->info
.info2
->secdesc
= NULL
;
1012 r
->info
.info2
->devmode
= NULL
;
1016 static bool test_PrinterInfo(struct torture_context
*tctx
,
1017 struct dcerpc_pipe
*p
,
1018 struct policy_handle
*handle
)
1021 struct spoolss_SetPrinter s
;
1022 struct spoolss_GetPrinter q
;
1023 struct spoolss_GetPrinter q0
;
1024 struct spoolss_SetPrinterInfoCtr info_ctr
;
1025 union spoolss_PrinterInfo info
;
1026 struct spoolss_DevmodeContainer devmode_ctr
;
1027 struct sec_desc_buf secdesc_ctr
;
1032 uint32_t status_list
[] = {
1033 /* these do not stick
1034 PRINTER_STATUS_PAUSED,
1035 PRINTER_STATUS_ERROR,
1036 PRINTER_STATUS_PENDING_DELETION, */
1037 PRINTER_STATUS_PAPER_JAM
,
1038 PRINTER_STATUS_PAPER_OUT
,
1039 PRINTER_STATUS_MANUAL_FEED
,
1040 PRINTER_STATUS_PAPER_PROBLEM
,
1041 PRINTER_STATUS_OFFLINE
,
1042 PRINTER_STATUS_IO_ACTIVE
,
1043 PRINTER_STATUS_BUSY
,
1044 PRINTER_STATUS_PRINTING
,
1045 PRINTER_STATUS_OUTPUT_BIN_FULL
,
1046 PRINTER_STATUS_NOT_AVAILABLE
,
1047 PRINTER_STATUS_WAITING
,
1048 PRINTER_STATUS_PROCESSING
,
1049 PRINTER_STATUS_INITIALIZING
,
1050 PRINTER_STATUS_WARMING_UP
,
1051 PRINTER_STATUS_TONER_LOW
,
1052 PRINTER_STATUS_NO_TONER
,
1053 PRINTER_STATUS_PAGE_PUNT
,
1054 PRINTER_STATUS_USER_INTERVENTION
,
1055 PRINTER_STATUS_OUT_OF_MEMORY
,
1056 PRINTER_STATUS_DOOR_OPEN
,
1057 PRINTER_STATUS_SERVER_UNKNOWN
,
1058 PRINTER_STATUS_POWER_SAVE
,
1059 /* these do not stick
1068 uint32_t default_attribute
= PRINTER_ATTRIBUTE_LOCAL
;
1069 uint32_t attribute_list
[] = {
1070 PRINTER_ATTRIBUTE_QUEUED
,
1071 /* fails with WERR_INVALID_DATATYPE:
1072 PRINTER_ATTRIBUTE_DIRECT, */
1074 PRINTER_ATTRIBUTE_DEFAULT, */
1075 PRINTER_ATTRIBUTE_SHARED
,
1077 PRINTER_ATTRIBUTE_NETWORK, */
1078 PRINTER_ATTRIBUTE_HIDDEN
,
1079 PRINTER_ATTRIBUTE_LOCAL
,
1080 PRINTER_ATTRIBUTE_ENABLE_DEVQ
,
1081 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
,
1082 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST
,
1083 PRINTER_ATTRIBUTE_WORK_OFFLINE
,
1085 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1086 /* fails with WERR_INVALID_DATATYPE:
1087 PRINTER_ATTRIBUTE_RAW_ONLY, */
1088 /* these do not stick
1089 PRINTER_ATTRIBUTE_PUBLISHED,
1090 PRINTER_ATTRIBUTE_FAX,
1091 PRINTER_ATTRIBUTE_TS,
1110 ZERO_STRUCT(devmode_ctr
);
1111 ZERO_STRUCT(secdesc_ctr
);
1113 s
.in
.handle
= handle
;
1115 s
.in
.info_ctr
= &info_ctr
;
1116 s
.in
.devmode_ctr
= &devmode_ctr
;
1117 s
.in
.secdesc_ctr
= &secdesc_ctr
;
1119 q
.in
.handle
= handle
;
1123 #define TESTGETCALL(call, r) \
1124 r.in.buffer = NULL; \
1126 r.out.needed = &needed; \
1127 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1128 if (!NT_STATUS_IS_OK(status)) { \
1129 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1130 r.in.level, nt_errstr(status), __location__); \
1134 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1135 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1136 data_blob_clear(&blob); \
1137 r.in.buffer = &blob; \
1138 r.in.offered = needed; \
1140 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1141 if (!NT_STATUS_IS_OK(status)) { \
1142 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1143 r.in.level, nt_errstr(status), __location__); \
1147 if (!W_ERROR_IS_OK(r.out.result)) { \
1148 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1149 r.in.level, win_errstr(r.out.result), __location__); \
1155 #define TESTSETCALL_EXP(call, r, err) \
1156 clear_info2(&info_ctr);\
1157 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1158 if (!NT_STATUS_IS_OK(status)) { \
1159 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1160 r.in.info_ctr->level, nt_errstr(status), __location__); \
1164 if (!W_ERROR_IS_OK(err)) { \
1165 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1166 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1167 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1172 if (!W_ERROR_IS_OK(r.out.result)) { \
1173 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1174 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1179 #define TESTSETCALL(call, r) \
1180 TESTSETCALL_EXP(call, r, WERR_OK)
1182 #define STRING_EQUAL(s1, s2, field) \
1183 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1184 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1185 #field, s2, __location__); \
1190 #define MEM_EQUAL(s1, s2, length, field) \
1191 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1192 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1193 #field, (const char *)s2, __location__); \
1198 #define INT_EQUAL(i1, i2, field) \
1200 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1201 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1206 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1207 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1208 q.in.level = lvl1; \
1209 TESTGETCALL(GetPrinter, q) \
1210 info_ctr.level = lvl1; \
1211 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1212 info_ctr.info.info ## lvl1->field1 = value;\
1213 TESTSETCALL_EXP(SetPrinter, s, err) \
1214 info_ctr.info.info ## lvl1->field1 = ""; \
1215 TESTGETCALL(GetPrinter, q) \
1216 info_ctr.info.info ## lvl1->field1 = value; \
1217 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1218 q.in.level = lvl2; \
1219 TESTGETCALL(GetPrinter, q) \
1220 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1221 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1224 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1225 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1228 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1229 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1230 q.in.level = lvl1; \
1231 TESTGETCALL(GetPrinter, q) \
1232 info_ctr.level = lvl1; \
1233 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1234 info_ctr.info.info ## lvl1->field1 = value; \
1235 TESTSETCALL(SetPrinter, s) \
1236 info_ctr.info.info ## lvl1->field1 = 0; \
1237 TESTGETCALL(GetPrinter, q) \
1238 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1239 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1240 q.in.level = lvl2; \
1241 TESTGETCALL(GetPrinter, q) \
1242 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1243 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1246 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1247 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1251 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1253 TEST_PRINTERINFO_STRING(2, comment
, 1, comment
, "xx2-1 comment");
1254 TEST_PRINTERINFO_STRING(2, comment
, 2, comment
, "xx2-2 comment");
1256 /* level 0 printername does not stick */
1257 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1258 TEST_PRINTERINFO_STRING(2, printername
, 1, name
, "xx2-1 printer");
1259 TEST_PRINTERINFO_STRING(2, printername
, 2, printername
, "xx2-2 printer");
1260 TEST_PRINTERINFO_STRING(2, printername
, 4, printername
, "xx2-4 printer");
1261 TEST_PRINTERINFO_STRING(2, printername
, 5, printername
, "xx2-5 printer");
1262 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1263 TEST_PRINTERINFO_STRING(4, printername
, 1, name
, "xx4-1 printer");
1264 TEST_PRINTERINFO_STRING(4, printername
, 2, printername
, "xx4-2 printer");
1265 TEST_PRINTERINFO_STRING(4, printername
, 4, printername
, "xx4-4 printer");
1266 TEST_PRINTERINFO_STRING(4, printername
, 5, printername
, "xx4-5 printer");
1267 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1268 TEST_PRINTERINFO_STRING(5, printername
, 1, name
, "xx5-1 printer");
1269 TEST_PRINTERINFO_STRING(5, printername
, 2, printername
, "xx5-2 printer");
1270 TEST_PRINTERINFO_STRING(5, printername
, 4, printername
, "xx5-4 printer");
1271 TEST_PRINTERINFO_STRING(5, printername
, 5, printername
, "xx5-5 printer");
1273 /* servername can be set but does not stick
1274 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1275 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1276 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1279 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1280 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname
, 2, portname
, "xx2-2 portname", WERR_UNKNOWN_PORT
);
1281 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname
, 5, portname
, "xx2-5 portname", WERR_UNKNOWN_PORT
);
1282 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname
, 2, portname
, "xx5-2 portname", WERR_UNKNOWN_PORT
);
1283 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname
, 5, portname
, "xx5-5 portname", WERR_UNKNOWN_PORT
);
1285 TEST_PRINTERINFO_STRING(2, sharename
, 2, sharename
, "xx2-2 sharename");
1286 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1287 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername
, 2, drivername
, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER
);
1288 TEST_PRINTERINFO_STRING(2, location
, 2, location
, "xx2-2 location");
1289 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1290 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile
, 2, sepfile
, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE
);
1291 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1292 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor
, 2, printprocessor
, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR
);
1293 TEST_PRINTERINFO_STRING(2, datatype
, 2, datatype
, "xx2-2 datatype");
1294 TEST_PRINTERINFO_STRING(2, parameters
, 2, parameters
, "xx2-2 parameters");
1296 for (i
=0; i
< ARRAY_SIZE(attribute_list
); i
++) {
1297 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1299 (attribute_list[i] | default_attribute)
1301 TEST_PRINTERINFO_INT_EXP(2, attributes
, 2, attributes
,
1303 (attribute_list
[i
] | default_attribute
)
1305 TEST_PRINTERINFO_INT_EXP(2, attributes
, 4, attributes
,
1307 (attribute_list
[i
] | default_attribute
)
1309 TEST_PRINTERINFO_INT_EXP(2, attributes
, 5, attributes
,
1311 (attribute_list
[i
] | default_attribute
)
1313 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1315 (attribute_list[i] | default_attribute)
1317 TEST_PRINTERINFO_INT_EXP(4, attributes
, 2, attributes
,
1319 (attribute_list
[i
] | default_attribute
)
1321 TEST_PRINTERINFO_INT_EXP(4, attributes
, 4, attributes
,
1323 (attribute_list
[i
] | default_attribute
)
1325 TEST_PRINTERINFO_INT_EXP(4, attributes
, 5, attributes
,
1327 (attribute_list
[i
] | default_attribute
)
1329 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1331 (attribute_list[i] | default_attribute)
1333 TEST_PRINTERINFO_INT_EXP(5, attributes
, 2, attributes
,
1335 (attribute_list
[i
] | default_attribute
)
1337 TEST_PRINTERINFO_INT_EXP(5, attributes
, 4, attributes
,
1339 (attribute_list
[i
] | default_attribute
)
1341 TEST_PRINTERINFO_INT_EXP(5, attributes
, 5, attributes
,
1343 (attribute_list
[i
] | default_attribute
)
1347 for (i
=0; i
< ARRAY_SIZE(status_list
); i
++) {
1348 /* level 2 sets do not stick
1349 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1350 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1351 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1352 TEST_PRINTERINFO_INT(6, status
, 0, status
, status_list
[i
]);
1353 TEST_PRINTERINFO_INT(6, status
, 2, status
, status_list
[i
]);
1354 TEST_PRINTERINFO_INT(6, status
, 6, status
, status_list
[i
]);
1357 /* priorities need to be between 0 and 99
1358 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1359 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 0);
1360 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 1);
1361 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 99);
1362 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1363 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 0);
1364 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 1);
1365 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 99);
1366 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1368 TEST_PRINTERINFO_INT(2, starttime
, 2, starttime
, __LINE__
);
1369 TEST_PRINTERINFO_INT(2, untiltime
, 2, untiltime
, __LINE__
);
1372 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1373 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1376 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1377 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1379 /* FIXME: gd also test devmode and secdesc behavior */
1382 /* verify composition of level 1 description field */
1383 const char *description
;
1387 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1389 description
= talloc_strdup(tctx
, q0
.out
.info
->info1
.description
);
1392 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1394 tmp
= talloc_asprintf(tctx
, "%s,%s,%s",
1395 q0
.out
.info
->info2
.printername
,
1396 q0
.out
.info
->info2
.drivername
,
1397 q0
.out
.info
->info2
.location
);
1399 do { STRING_EQUAL(description
, tmp
, "description")} while (0);
1406 static bool test_ClosePrinter(struct torture_context
*tctx
,
1407 struct dcerpc_pipe
*p
,
1408 struct policy_handle
*handle
)
1411 struct spoolss_ClosePrinter r
;
1413 r
.in
.handle
= handle
;
1414 r
.out
.handle
= handle
;
1416 torture_comment(tctx
, "Testing ClosePrinter\n");
1418 status
= dcerpc_spoolss_ClosePrinter(p
, tctx
, &r
);
1419 torture_assert_ntstatus_ok(tctx
, status
, "ClosePrinter failed");
1420 torture_assert_werr_ok(tctx
, r
.out
.result
, "ClosePrinter failed");
1425 static bool test_GetForm(struct torture_context
*tctx
,
1426 struct dcerpc_pipe
*p
,
1427 struct policy_handle
*handle
,
1428 const char *form_name
,
1432 struct spoolss_GetForm r
;
1435 r
.in
.handle
= handle
;
1436 r
.in
.form_name
= form_name
;
1440 r
.out
.needed
= &needed
;
1442 torture_comment(tctx
, "Testing GetForm level %d\n", r
.in
.level
);
1444 status
= dcerpc_spoolss_GetForm(p
, tctx
, &r
);
1445 torture_assert_ntstatus_ok(tctx
, status
, "GetForm failed");
1447 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1448 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1449 data_blob_clear(&blob
);
1450 r
.in
.buffer
= &blob
;
1451 r
.in
.offered
= needed
;
1452 status
= dcerpc_spoolss_GetForm(p
, tctx
, &r
);
1453 torture_assert_ntstatus_ok(tctx
, status
, "GetForm failed");
1455 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetForm failed");
1457 torture_assert(tctx
, r
.out
.info
, "No form info returned");
1460 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetForm failed");
1465 static bool test_EnumForms(struct torture_context
*tctx
,
1466 struct dcerpc_pipe
*p
,
1467 struct policy_handle
*handle
, bool print_server
)
1470 struct spoolss_EnumForms r
;
1474 uint32_t levels
[] = { 1, 2 };
1477 for (i
=0; i
<ARRAY_SIZE(levels
); i
++) {
1479 union spoolss_FormInfo
*info
;
1481 r
.in
.handle
= handle
;
1482 r
.in
.level
= levels
[i
];
1485 r
.out
.needed
= &needed
;
1486 r
.out
.count
= &count
;
1489 torture_comment(tctx
, "Testing EnumForms level %d\n", levels
[i
]);
1491 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &r
);
1492 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
1494 if ((r
.in
.level
== 2) && (W_ERROR_EQUAL(r
.out
.result
, WERR_UNKNOWN_LEVEL
))) {
1498 if (print_server
&& W_ERROR_EQUAL(r
.out
.result
, WERR_BADFID
))
1499 torture_fail(tctx
, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1501 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1503 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1504 data_blob_clear(&blob
);
1505 r
.in
.buffer
= &blob
;
1506 r
.in
.offered
= needed
;
1508 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &r
);
1510 torture_assert(tctx
, info
, "No forms returned");
1512 for (j
= 0; j
< count
; j
++) {
1514 ret
&= test_GetForm(tctx
, p
, handle
, info
[j
].info1
.form_name
, levels
[i
]);
1518 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
1520 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumForms failed");
1526 static bool test_DeleteForm(struct torture_context
*tctx
,
1527 struct dcerpc_pipe
*p
,
1528 struct policy_handle
*handle
,
1529 const char *form_name
)
1532 struct spoolss_DeleteForm r
;
1534 r
.in
.handle
= handle
;
1535 r
.in
.form_name
= form_name
;
1537 status
= dcerpc_spoolss_DeleteForm(p
, tctx
, &r
);
1539 torture_assert_ntstatus_ok(tctx
, status
, "DeleteForm failed");
1541 torture_assert_werr_ok(tctx
, r
.out
.result
, "DeleteForm failed");
1546 static bool test_AddForm(struct torture_context
*tctx
,
1547 struct dcerpc_pipe
*p
,
1548 struct policy_handle
*handle
, bool print_server
)
1550 struct spoolss_AddForm r
;
1551 struct spoolss_AddFormInfo1 addform
;
1552 const char *form_name
= "testform3";
1556 r
.in
.handle
= handle
;
1558 r
.in
.info
.info1
= &addform
;
1559 addform
.flags
= SPOOLSS_FORM_USER
;
1560 addform
.form_name
= form_name
;
1561 addform
.size
.width
= 50;
1562 addform
.size
.height
= 25;
1563 addform
.area
.left
= 5;
1564 addform
.area
.top
= 10;
1565 addform
.area
.right
= 45;
1566 addform
.area
.bottom
= 15;
1568 status
= dcerpc_spoolss_AddForm(p
, tctx
, &r
);
1570 torture_assert_ntstatus_ok(tctx
, status
, "AddForm failed");
1572 torture_assert_werr_ok(tctx
, r
.out
.result
, "AddForm failed");
1574 if (!print_server
) ret
&= test_GetForm(tctx
, p
, handle
, form_name
, 1);
1577 struct spoolss_SetForm sf
;
1578 struct spoolss_AddFormInfo1 setform
;
1580 sf
.in
.handle
= handle
;
1581 sf
.in
.form_name
= form_name
;
1583 sf
.in
.info
.info1
= &setform
;
1584 setform
.flags
= addform
.flags
;
1585 setform
.form_name
= addform
.form_name
;
1586 setform
.size
= addform
.size
;
1587 setform
.area
= addform
.area
;
1589 setform
.size
.width
= 1234;
1591 status
= dcerpc_spoolss_SetForm(p
, tctx
, &sf
);
1593 torture_assert_ntstatus_ok(tctx
, status
, "SetForm failed");
1595 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetForm failed");
1598 if (!print_server
) ret
&= test_GetForm(tctx
, p
, handle
, form_name
, 1);
1601 struct spoolss_EnumForms e
;
1602 union spoolss_FormInfo
*info
;
1607 e
.in
.handle
= handle
;
1611 e
.out
.needed
= &needed
;
1612 e
.out
.count
= &count
;
1615 torture_comment(tctx
, "Testing EnumForms level 1\n");
1617 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &e
);
1618 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
1620 if (print_server
&& W_ERROR_EQUAL(e
.out
.result
, WERR_BADFID
))
1621 torture_fail(tctx
, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1623 if (W_ERROR_EQUAL(e
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1625 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1626 data_blob_clear(&blob
);
1627 e
.in
.buffer
= &blob
;
1628 e
.in
.offered
= needed
;
1630 status
= dcerpc_spoolss_EnumForms(p
, tctx
, &e
);
1632 torture_assert(tctx
, info
, "No forms returned");
1634 for (j
= 0; j
< count
; j
++) {
1635 if (strequal(form_name
, info
[j
].info1
.form_name
)) {
1641 torture_assert(tctx
, found
, "Newly added form not found in enum call");
1644 if (!test_DeleteForm(tctx
, p
, handle
, form_name
)) {
1651 static bool test_EnumPorts_old(struct torture_context
*tctx
,
1652 struct dcerpc_pipe
*p
)
1655 struct spoolss_EnumPorts r
;
1658 union spoolss_PortInfo
*info
;
1660 r
.in
.servername
= talloc_asprintf(tctx
, "\\\\%s",
1661 dcerpc_server_name(p
));
1665 r
.out
.needed
= &needed
;
1666 r
.out
.count
= &count
;
1669 torture_comment(tctx
, "Testing EnumPorts\n");
1671 status
= dcerpc_spoolss_EnumPorts(p
, tctx
, &r
);
1673 torture_assert_ntstatus_ok(tctx
, status
, "EnumPorts failed");
1675 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1676 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1677 data_blob_clear(&blob
);
1678 r
.in
.buffer
= &blob
;
1679 r
.in
.offered
= needed
;
1681 status
= dcerpc_spoolss_EnumPorts(p
, tctx
, &r
);
1682 torture_assert_ntstatus_ok(tctx
, status
, "EnumPorts failed");
1683 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
1685 torture_assert(tctx
, info
, "No ports returned");
1688 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
1693 static bool test_AddPort(struct torture_context
*tctx
,
1694 struct dcerpc_pipe
*p
)
1697 struct spoolss_AddPort r
;
1699 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s",
1700 dcerpc_server_name(p
));
1702 r
.in
.monitor_name
= "foo";
1704 torture_comment(tctx
, "Testing AddPort\n");
1706 status
= dcerpc_spoolss_AddPort(p
, tctx
, &r
);
1708 torture_assert_ntstatus_ok(tctx
, status
, "AddPort failed");
1710 /* win2k3 returns WERR_NOT_SUPPORTED */
1714 if (!W_ERROR_IS_OK(r
.out
.result
)) {
1715 printf("AddPort failed - %s\n", win_errstr(r
.out
.result
));
1724 static bool test_GetJob(struct torture_context
*tctx
,
1725 struct dcerpc_pipe
*p
,
1726 struct policy_handle
*handle
, uint32_t job_id
)
1729 struct spoolss_GetJob r
;
1730 union spoolss_JobInfo info
;
1732 uint32_t levels
[] = {1, 2 /* 3, 4 */};
1735 r
.in
.handle
= handle
;
1736 r
.in
.job_id
= job_id
;
1740 r
.out
.needed
= &needed
;
1743 torture_comment(tctx
, "Testing GetJob level %d\n", r
.in
.level
);
1745 status
= dcerpc_spoolss_GetJob(p
, tctx
, &r
);
1746 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
, "Unexpected return code");
1748 for (i
= 0; i
< ARRAY_SIZE(levels
); i
++) {
1750 torture_comment(tctx
, "Testing GetJob level %d\n", r
.in
.level
);
1754 r
.in
.level
= levels
[i
];
1758 status
= dcerpc_spoolss_GetJob(p
, tctx
, &r
);
1759 torture_assert_ntstatus_ok(tctx
, status
, "GetJob failed");
1761 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1762 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1763 data_blob_clear(&blob
);
1764 r
.in
.buffer
= &blob
;
1765 r
.in
.offered
= needed
;
1767 status
= dcerpc_spoolss_GetJob(p
, tctx
, &r
);
1768 torture_assert_ntstatus_ok(tctx
, status
, "GetJob failed");
1771 torture_assert(tctx
, r
.out
.info
, "No job info returned");
1772 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetJob failed");
1778 static bool test_SetJob(struct torture_context
*tctx
,
1779 struct dcerpc_pipe
*p
,
1780 struct policy_handle
*handle
, uint32_t job_id
,
1781 enum spoolss_JobControl command
)
1784 struct spoolss_SetJob r
;
1786 r
.in
.handle
= handle
;
1787 r
.in
.job_id
= job_id
;
1789 r
.in
.command
= command
;
1792 case SPOOLSS_JOB_CONTROL_PAUSE
:
1793 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1795 case SPOOLSS_JOB_CONTROL_RESUME
:
1796 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1798 case SPOOLSS_JOB_CONTROL_CANCEL
:
1799 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1801 case SPOOLSS_JOB_CONTROL_RESTART
:
1802 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1804 case SPOOLSS_JOB_CONTROL_DELETE
:
1805 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1807 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER
:
1808 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1810 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED
:
1811 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1813 case SPOOLSS_JOB_CONTROL_RETAIN
:
1814 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1816 case SPOOLSS_JOB_CONTROL_RELEASE
:
1817 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1820 torture_comment(tctx
, "Testing SetJob\n");
1824 status
= dcerpc_spoolss_SetJob(p
, tctx
, &r
);
1825 torture_assert_ntstatus_ok(tctx
, status
, "SetJob failed");
1826 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetJob failed");
1831 static bool test_AddJob(struct torture_context
*tctx
,
1832 struct dcerpc_pipe
*p
,
1833 struct policy_handle
*handle
)
1836 struct spoolss_AddJob r
;
1840 r
.in
.handle
= handle
;
1842 r
.out
.needed
= &needed
;
1843 r
.in
.buffer
= r
.out
.buffer
= NULL
;
1845 torture_comment(tctx
, "Testing AddJob\n");
1847 status
= dcerpc_spoolss_AddJob(p
, tctx
, &r
);
1848 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
, "AddJob failed");
1852 status
= dcerpc_spoolss_AddJob(p
, tctx
, &r
);
1853 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
, "AddJob failed");
1859 static bool test_EnumJobs(struct torture_context
*tctx
,
1860 struct dcerpc_pipe
*p
,
1861 struct policy_handle
*handle
)
1864 struct spoolss_EnumJobs r
;
1867 union spoolss_JobInfo
*info
;
1869 r
.in
.handle
= handle
;
1871 r
.in
.numjobs
= 0xffffffff;
1875 r
.out
.needed
= &needed
;
1876 r
.out
.count
= &count
;
1879 torture_comment(tctx
, "Testing EnumJobs\n");
1881 status
= dcerpc_spoolss_EnumJobs(p
, tctx
, &r
);
1883 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
1885 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
1887 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
1888 data_blob_clear(&blob
);
1889 r
.in
.buffer
= &blob
;
1890 r
.in
.offered
= needed
;
1892 status
= dcerpc_spoolss_EnumJobs(p
, tctx
, &r
);
1894 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
1895 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumJobs failed");
1896 torture_assert(tctx
, info
, "No jobs returned");
1898 for (j
= 0; j
< count
; j
++) {
1900 torture_assert(tctx
, test_GetJob(tctx
, p
, handle
, info
[j
].info1
.job_id
),
1901 "failed to call test_GetJob");
1904 if (!torture_setting_bool(tctx
, "samba3", false)) {
1905 test_SetJob(tctx
, p
, handle
, info
[j
].info1
.job_id
, SPOOLSS_JOB_CONTROL_PAUSE
);
1906 test_SetJob(tctx
, p
, handle
, info
[j
].info1
.job_id
, SPOOLSS_JOB_CONTROL_RESUME
);
1911 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumJobs failed");
1917 static bool test_DoPrintTest(struct torture_context
*tctx
,
1918 struct dcerpc_pipe
*p
,
1919 struct policy_handle
*handle
)
1923 struct spoolss_StartDocPrinter s
;
1924 struct spoolss_DocumentInfo1 info1
;
1925 struct spoolss_StartPagePrinter sp
;
1926 struct spoolss_WritePrinter w
;
1927 struct spoolss_EndPagePrinter ep
;
1928 struct spoolss_EndDocPrinter e
;
1931 uint32_t num_written
;
1933 torture_comment(tctx
, "Testing StartDocPrinter\n");
1935 s
.in
.handle
= handle
;
1937 s
.in
.info
.info1
= &info1
;
1938 s
.out
.job_id
= &job_id
;
1939 info1
.document_name
= "TorturePrintJob";
1940 info1
.output_file
= NULL
;
1941 info1
.datatype
= "RAW";
1943 status
= dcerpc_spoolss_StartDocPrinter(p
, tctx
, &s
);
1944 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_StartDocPrinter failed");
1945 torture_assert_werr_ok(tctx
, s
.out
.result
, "StartDocPrinter failed");
1947 for (i
=1; i
< 4; i
++) {
1948 torture_comment(tctx
, "Testing StartPagePrinter: Page[%d]\n", i
);
1950 sp
.in
.handle
= handle
;
1952 status
= dcerpc_spoolss_StartPagePrinter(p
, tctx
, &sp
);
1953 torture_assert_ntstatus_ok(tctx
, status
,
1954 "dcerpc_spoolss_StartPagePrinter failed");
1955 torture_assert_werr_ok(tctx
, sp
.out
.result
, "StartPagePrinter failed");
1957 torture_comment(tctx
, "Testing WritePrinter: Page[%d]\n", i
);
1959 w
.in
.handle
= handle
;
1960 w
.in
.data
= data_blob_string_const(talloc_asprintf(tctx
,"TortureTestPage: %d\nData\n",i
));
1961 w
.out
.num_written
= &num_written
;
1963 status
= dcerpc_spoolss_WritePrinter(p
, tctx
, &w
);
1964 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_WritePrinter failed");
1965 torture_assert_werr_ok(tctx
, w
.out
.result
, "WritePrinter failed");
1967 torture_comment(tctx
, "Testing EndPagePrinter: Page[%d]\n", i
);
1969 ep
.in
.handle
= handle
;
1971 status
= dcerpc_spoolss_EndPagePrinter(p
, tctx
, &ep
);
1972 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndPagePrinter failed");
1973 torture_assert_werr_ok(tctx
, ep
.out
.result
, "EndPagePrinter failed");
1976 torture_comment(tctx
, "Testing EndDocPrinter\n");
1978 e
.in
.handle
= handle
;
1980 status
= dcerpc_spoolss_EndDocPrinter(p
, tctx
, &e
);
1981 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndDocPrinter failed");
1982 torture_assert_werr_ok(tctx
, e
.out
.result
, "EndDocPrinter failed");
1984 ret
&= test_AddJob(tctx
, p
, handle
);
1985 ret
&= test_EnumJobs(tctx
, p
, handle
);
1987 ret
&= test_SetJob(tctx
, p
, handle
, job_id
, SPOOLSS_JOB_CONTROL_DELETE
);
1992 static bool test_PausePrinter(struct torture_context
*tctx
,
1993 struct dcerpc_pipe
*p
,
1994 struct policy_handle
*handle
)
1997 struct spoolss_SetPrinter r
;
1998 struct spoolss_SetPrinterInfoCtr info_ctr
;
1999 struct spoolss_DevmodeContainer devmode_ctr
;
2000 struct sec_desc_buf secdesc_ctr
;
2003 info_ctr
.info
.info0
= NULL
;
2005 ZERO_STRUCT(devmode_ctr
);
2006 ZERO_STRUCT(secdesc_ctr
);
2008 r
.in
.handle
= handle
;
2009 r
.in
.info_ctr
= &info_ctr
;
2010 r
.in
.devmode_ctr
= &devmode_ctr
;
2011 r
.in
.secdesc_ctr
= &secdesc_ctr
;
2012 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
2014 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
2016 status
= dcerpc_spoolss_SetPrinter(p
, tctx
, &r
);
2018 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
2020 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
2025 static bool test_ResumePrinter(struct torture_context
*tctx
,
2026 struct dcerpc_pipe
*p
,
2027 struct policy_handle
*handle
)
2030 struct spoolss_SetPrinter r
;
2031 struct spoolss_SetPrinterInfoCtr info_ctr
;
2032 struct spoolss_DevmodeContainer devmode_ctr
;
2033 struct sec_desc_buf secdesc_ctr
;
2036 info_ctr
.info
.info0
= NULL
;
2038 ZERO_STRUCT(devmode_ctr
);
2039 ZERO_STRUCT(secdesc_ctr
);
2041 r
.in
.handle
= handle
;
2042 r
.in
.info_ctr
= &info_ctr
;
2043 r
.in
.devmode_ctr
= &devmode_ctr
;
2044 r
.in
.secdesc_ctr
= &secdesc_ctr
;
2045 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
2047 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2049 status
= dcerpc_spoolss_SetPrinter(p
, tctx
, &r
);
2051 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
2053 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
2058 static bool test_GetPrinterData(struct torture_context
*tctx
,
2059 struct dcerpc_pipe
*p
,
2060 struct policy_handle
*handle
,
2061 const char *value_name
,
2062 enum winreg_Type
*type_p
,
2063 union spoolss_PrinterData
*data_p
)
2066 struct spoolss_GetPrinterData r
;
2068 enum winreg_Type type
;
2069 union spoolss_PrinterData data
;
2071 r
.in
.handle
= handle
;
2072 r
.in
.value_name
= value_name
;
2074 r
.out
.needed
= &needed
;
2078 torture_comment(tctx
, "Testing GetPrinterData(%s)\n", r
.in
.value_name
);
2080 status
= dcerpc_spoolss_GetPrinterData(p
, tctx
, &r
);
2081 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
2083 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
2084 r
.in
.offered
= needed
;
2086 status
= dcerpc_spoolss_GetPrinterData(p
, tctx
, &r
);
2087 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
2090 torture_assert_werr_ok(tctx
, r
.out
.result
,
2091 talloc_asprintf(tctx
, "GetPrinterData(%s) failed", r
.in
.value_name
));
2104 static bool test_GetPrinterDataEx(struct torture_context
*tctx
,
2105 struct dcerpc_pipe
*p
,
2106 struct policy_handle
*handle
,
2107 const char *key_name
,
2108 const char *value_name
,
2109 enum winreg_Type
*type_p
,
2110 union spoolss_PrinterData
*data_p
)
2113 struct spoolss_GetPrinterDataEx r
;
2114 enum winreg_Type type
;
2116 union spoolss_PrinterData data
;
2118 r
.in
.handle
= handle
;
2119 r
.in
.key_name
= key_name
;
2120 r
.in
.value_name
= value_name
;
2123 r
.out
.needed
= &needed
;
2126 torture_comment(tctx
, "Testing GetPrinterDataEx(%s - %s)\n",
2127 r
.in
.key_name
, r
.in
.value_name
);
2129 status
= dcerpc_spoolss_GetPrinterDataEx(p
, tctx
, &r
);
2130 if (!NT_STATUS_IS_OK(status
)) {
2131 if (NT_STATUS_EQUAL(status
,NT_STATUS_NET_WRITE_FAULT
) &&
2132 p
->last_fault_code
== DCERPC_FAULT_OP_RNG_ERROR
) {
2133 torture_skip(tctx
, "GetPrinterDataEx not supported by server\n");
2135 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
2138 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
2139 r
.in
.offered
= needed
;
2140 status
= dcerpc_spoolss_GetPrinterDataEx(p
, tctx
, &r
);
2141 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
2144 torture_assert_werr_ok(tctx
, r
.out
.result
,
2145 talloc_asprintf(tctx
, "GetPrinterDataEx(%s - %s) failed", r
.in
.key_name
, r
.in
.value_name
));
2158 static bool test_GetPrinterData_list(struct torture_context
*tctx
,
2159 struct dcerpc_pipe
*p
,
2160 struct policy_handle
*handle
)
2162 const char *list
[] = {
2166 /* "NetPopup", not on w2k8 */
2167 /* "NetPopupToComputer", not on w2k8 */
2170 "DefaultSpoolDirectory",
2174 /* "OSVersionEx", not on s3 */
2179 for (i
=0; i
< ARRAY_SIZE(list
); i
++) {
2180 enum winreg_Type type
, type_ex
;
2181 union spoolss_PrinterData data
, data_ex
;
2183 torture_assert(tctx
, test_GetPrinterData(tctx
, p
, handle
, list
[i
], &type
, &data
),
2184 talloc_asprintf(tctx
, "GetPrinterData failed on %s\n", list
[i
]));
2185 torture_assert(tctx
, test_GetPrinterDataEx(tctx
, p
, handle
, "random_string", list
[i
], &type_ex
, &data_ex
),
2186 talloc_asprintf(tctx
, "GetPrinterDataEx failed on %s\n", list
[i
]));
2187 torture_assert_int_equal(tctx
, type
, type_ex
, "type mismatch");
2190 torture_assert_str_equal(tctx
, data
.string
, data_ex
.string
, "REG_SZ mismatch");
2193 torture_assert_int_equal(tctx
, data
.value
, data_ex
.value
, "REG_DWORD mismatch");
2196 torture_assert_data_blob_equal(tctx
, data
.binary
, data_ex
.binary
, "REG_BINARY mismatch");
2206 static bool test_EnumPrinterData(struct torture_context
*tctx
, struct dcerpc_pipe
*p
,
2207 struct policy_handle
*handle
)
2210 struct spoolss_EnumPrinterData r
;
2213 r
.in
.handle
= handle
;
2214 r
.in
.enum_index
= 0;
2217 uint32_t value_size
= 0;
2218 uint32_t data_size
= 0;
2219 enum winreg_Type type
= 0;
2221 r
.in
.value_offered
= value_size
;
2222 r
.out
.value_needed
= &value_size
;
2223 r
.in
.data_offered
= data_size
;
2224 r
.out
.data_needed
= &data_size
;
2227 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, 0);
2229 torture_comment(tctx
, "Testing EnumPrinterData\n");
2231 status
= dcerpc_spoolss_EnumPrinterData(p
, tctx
, &r
);
2233 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterData failed");
2234 if (W_ERROR_EQUAL(r
.out
.result
, WERR_NO_MORE_ITEMS
)) {
2237 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterData");
2239 r
.in
.value_offered
= value_size
;
2240 r
.out
.value_name
= talloc_zero_array(tctx
, const char, value_size
);
2241 r
.in
.data_offered
= data_size
;
2242 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, data_size
);
2244 status
= dcerpc_spoolss_EnumPrinterData(p
, tctx
, &r
);
2246 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterData failed");
2247 if (W_ERROR_EQUAL(r
.out
.result
, WERR_NO_MORE_ITEMS
)) {
2251 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterData failed");
2253 torture_assert(tctx
, test_GetPrinterData(tctx
, p
, handle
, r
.out
.value_name
, NULL
, NULL
),
2254 talloc_asprintf(tctx
, "failed to call GetPrinterData for %s\n", r
.out
.value_name
));
2256 torture_assert(tctx
, test_GetPrinterDataEx(tctx
, p
, handle
, "PrinterDriverData", r
.out
.value_name
, NULL
, NULL
),
2257 talloc_asprintf(tctx
, "failed to call GetPrinterDataEx on PrinterDriverData for %s\n", r
.out
.value_name
));
2261 } while (W_ERROR_IS_OK(r
.out
.result
));
2266 static bool test_EnumPrinterDataEx(struct torture_context
*tctx
,
2267 struct dcerpc_pipe
*p
,
2268 struct policy_handle
*handle
,
2269 const char *key_name
)
2271 struct spoolss_EnumPrinterDataEx r
;
2272 struct spoolss_PrinterEnumValues
*info
;
2276 r
.in
.handle
= handle
;
2277 r
.in
.key_name
= key_name
;
2279 r
.out
.needed
= &needed
;
2280 r
.out
.count
= &count
;
2283 torture_comment(tctx
, "Testing EnumPrinterDataEx(%s)\n", key_name
);
2285 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterDataEx(p
, tctx
, &r
),
2286 "EnumPrinterDataEx failed");
2287 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
2288 r
.in
.offered
= needed
;
2289 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterDataEx(p
, tctx
, &r
),
2290 "EnumPrinterDataEx failed");
2293 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDataEx failed");
2299 static bool test_DeletePrinterData(struct torture_context
*tctx
,
2300 struct dcerpc_pipe
*p
,
2301 struct policy_handle
*handle
,
2302 const char *value_name
)
2305 struct spoolss_DeletePrinterData r
;
2307 r
.in
.handle
= handle
;
2308 r
.in
.value_name
= value_name
;
2310 torture_comment(tctx
, "Testing DeletePrinterData(%s)\n",
2313 status
= dcerpc_spoolss_DeletePrinterData(p
, tctx
, &r
);
2315 torture_assert_ntstatus_ok(tctx
, status
, "DeletePrinterData failed");
2316 torture_assert_werr_ok(tctx
, r
.out
.result
, "DeletePrinterData failed");
2321 static bool test_DeletePrinterDataEx(struct torture_context
*tctx
,
2322 struct dcerpc_pipe
*p
,
2323 struct policy_handle
*handle
,
2324 const char *key_name
,
2325 const char *value_name
)
2327 struct spoolss_DeletePrinterDataEx r
;
2329 r
.in
.handle
= handle
;
2330 r
.in
.key_name
= key_name
;
2331 r
.in
.value_name
= value_name
;
2333 torture_comment(tctx
, "Testing DeletePrinterDataEx(%s - %s)\n",
2334 r
.in
.key_name
, r
.in
.value_name
);
2336 torture_assert_ntstatus_ok(tctx
,
2337 dcerpc_spoolss_DeletePrinterDataEx(p
, tctx
, &r
),
2338 "DeletePrinterDataEx failed");
2339 torture_assert_werr_ok(tctx
, r
.out
.result
,
2340 "DeletePrinterDataEx failed");
2345 static bool test_DeletePrinterKey(struct torture_context
*tctx
,
2346 struct dcerpc_pipe
*p
,
2347 struct policy_handle
*handle
,
2348 const char *key_name
)
2350 struct spoolss_DeletePrinterKey r
;
2352 r
.in
.handle
= handle
;
2353 r
.in
.key_name
= key_name
;
2355 torture_comment(tctx
, "Testing DeletePrinterKey(%s)\n", r
.in
.key_name
);
2357 if (strequal(key_name
, "") && !torture_setting_bool(tctx
, "dangerous", false)) {
2358 torture_skip(tctx
, "not wiping out printer registry - enable dangerous tests to use\n");
2362 torture_assert_ntstatus_ok(tctx
,
2363 dcerpc_spoolss_DeletePrinterKey(p
, tctx
, &r
),
2364 "DeletePrinterKey failed");
2365 torture_assert_werr_ok(tctx
, r
.out
.result
,
2366 "DeletePrinterKey failed");
2371 static bool test_SetPrinterData(struct torture_context
*tctx
,
2372 struct dcerpc_pipe
*p
,
2373 struct policy_handle
*handle
)
2376 struct spoolss_SetPrinterData r
;
2377 const char *values
[] = {
2381 /* FIXME: not working with s3 atm. */
2387 /* FIXME: not working with s3 atm. */
2394 for (i
=0; i
< ARRAY_SIZE(values
); i
++) {
2396 enum winreg_Type type
;
2397 union spoolss_PrinterData data
;
2399 r
.in
.handle
= handle
;
2400 r
.in
.value_name
= values
[i
];
2402 r
.in
.data
.string
= "dog";
2404 torture_comment(tctx
, "Testing SetPrinterData(%s)\n",
2407 status
= dcerpc_spoolss_SetPrinterData(p
, tctx
, &r
);
2409 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinterData failed");
2410 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinterData failed");
2412 if (!test_GetPrinterData(tctx
, p
, handle
, r
.in
.value_name
, &type
, &data
)) {
2416 torture_assert_int_equal(tctx
, r
.in
.type
, type
, "type mismatch");
2417 torture_assert_str_equal(tctx
, r
.in
.data
.string
, data
.string
, "data mismatch");
2419 if (!test_DeletePrinterData(tctx
, p
, handle
, r
.in
.value_name
)) {
2427 static bool test_EnumPrinterKey(struct torture_context
*tctx
,
2428 struct dcerpc_pipe
*p
,
2429 struct policy_handle
*handle
,
2430 const char *key_name
,
2431 const char ***array
);
2433 static bool test_SetPrinterDataEx(struct torture_context
*tctx
,
2434 struct dcerpc_pipe
*p
,
2435 struct policy_handle
*handle
)
2438 struct spoolss_SetPrinterDataEx r
;
2439 const char *value_name
= "dog";
2440 const char *keys
[] = {
2444 /* FIXME: not working with s3 atm. */
2445 "torturedataex_with_subkey\\subkey",
2446 "torturedataex_with_subkey\\subkey:0",
2447 "torturedataex_with_subkey\\subkey:1",
2448 "torturedataex_with_subkey\\subkey\\subsubkey",
2449 "torturedataex_with_subkey\\subkey\\subsubkey:0",
2450 "torturedataex_with_subkey\\subkey\\subsubkey:1",
2454 /* FIXME: not working with s3 atm. */
2462 DATA_BLOB blob
= data_blob_string_const("catfoobar");
2465 for (i
=0; i
< ARRAY_SIZE(keys
); i
++) {
2469 enum winreg_Type type
;
2470 const char **subkeys
;
2471 union spoolss_PrinterData data
;
2473 r
.in
.handle
= handle
;
2474 r
.in
.key_name
= keys
[i
];
2475 r
.in
.value_name
= value_name
;
2476 r
.in
.type
= REG_BINARY
;
2477 r
.in
.data
.binary
= blob
;
2479 torture_comment(tctx
, "Testing SetPrinterDataEx(%s - %s)\n", r
.in
.key_name
, value_name
);
2481 status
= dcerpc_spoolss_SetPrinterDataEx(p
, tctx
, &r
);
2483 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinterDataEx failed");
2484 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinterDataEx failed");
2486 key
= talloc_strdup(tctx
, r
.in
.key_name
);
2488 if (!test_GetPrinterDataEx(tctx
, p
, handle
, r
.in
.key_name
, value_name
, &type
, &data
)) {
2492 torture_assert_int_equal(tctx
, r
.in
.type
, type
, "type mismatch");
2493 torture_assert_data_blob_equal(tctx
, blob
, data
.binary
, "data mismatch");
2495 if (!test_EnumPrinterDataEx(tctx
, p
, handle
, r
.in
.key_name
)) {
2499 if (!test_DeletePrinterDataEx(tctx
, p
, handle
, r
.in
.key_name
, value_name
)) {
2503 c
= strchr(key
, '\\');
2507 /* we have subkeys */
2511 if (!test_EnumPrinterKey(tctx
, p
, handle
, key
, &subkeys
)) {
2515 for (i
=0; subkeys
&& subkeys
[i
]; i
++) {
2517 const char *current_key
= talloc_asprintf(tctx
, "%s\\%s", key
, subkeys
[i
]);
2519 if (!test_DeletePrinterKey(tctx
, p
, handle
, current_key
)) {
2524 if (!test_DeletePrinterKey(tctx
, p
, handle
, key
)) {
2529 if (!test_DeletePrinterKey(tctx
, p
, handle
, key
)) {
2539 static bool test_SecondaryClosePrinter(struct torture_context
*tctx
,
2540 struct dcerpc_pipe
*p
,
2541 struct policy_handle
*handle
)
2544 struct dcerpc_binding
*b
;
2545 struct dcerpc_pipe
*p2
;
2546 struct spoolss_ClosePrinter cp
;
2548 /* only makes sense on SMB */
2549 if (p
->conn
->transport
.transport
!= NCACN_NP
) {
2553 torture_comment(tctx
, "testing close on secondary pipe\n");
2555 status
= dcerpc_parse_binding(tctx
, p
->conn
->binding_string
, &b
);
2556 torture_assert_ntstatus_ok(tctx
, status
, "Failed to parse dcerpc binding");
2558 status
= dcerpc_secondary_connection(p
, &p2
, b
);
2559 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create secondary connection");
2561 status
= dcerpc_bind_auth_none(p2
, &ndr_table_spoolss
);
2562 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create bind on secondary connection");
2564 cp
.in
.handle
= handle
;
2565 cp
.out
.handle
= handle
;
2567 status
= dcerpc_spoolss_ClosePrinter(p2
, tctx
, &cp
);
2568 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_NET_WRITE_FAULT
,
2569 "ERROR: Allowed close on secondary connection");
2571 torture_assert_int_equal(tctx
, p2
->last_fault_code
, DCERPC_FAULT_CONTEXT_MISMATCH
,
2572 "Unexpected fault code");
2579 static bool test_OpenPrinter_badname(struct torture_context
*tctx
,
2580 struct dcerpc_pipe
*p
, const char *name
)
2583 struct spoolss_OpenPrinter op
;
2584 struct spoolss_OpenPrinterEx opEx
;
2585 struct policy_handle handle
;
2588 op
.in
.printername
= name
;
2589 op
.in
.datatype
= NULL
;
2590 op
.in
.devmode_ctr
.devmode
= NULL
;
2591 op
.in
.access_mask
= 0;
2592 op
.out
.handle
= &handle
;
2594 torture_comment(tctx
, "\nTesting OpenPrinter(%s) with bad name\n", op
.in
.printername
);
2596 status
= dcerpc_spoolss_OpenPrinter(p
, tctx
, &op
);
2597 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
2598 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME
,op
.out
.result
)) {
2599 torture_comment(tctx
, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
2600 name
, win_errstr(op
.out
.result
));
2603 if (W_ERROR_IS_OK(op
.out
.result
)) {
2604 ret
&=test_ClosePrinter(tctx
, p
, &handle
);
2607 opEx
.in
.printername
= name
;
2608 opEx
.in
.datatype
= NULL
;
2609 opEx
.in
.devmode_ctr
.devmode
= NULL
;
2610 opEx
.in
.access_mask
= 0;
2612 opEx
.in
.userlevel
.level1
= NULL
;
2613 opEx
.out
.handle
= &handle
;
2615 torture_comment(tctx
, "Testing OpenPrinterEx(%s) with bad name\n", opEx
.in
.printername
);
2617 status
= dcerpc_spoolss_OpenPrinterEx(p
, tctx
, &opEx
);
2618 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinterEx failed");
2619 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM
,opEx
.out
.result
)) {
2620 torture_comment(tctx
, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
2621 name
, win_errstr(opEx
.out
.result
));
2624 if (W_ERROR_IS_OK(opEx
.out
.result
)) {
2625 ret
&=test_ClosePrinter(tctx
, p
, &handle
);
2631 static bool test_OpenPrinter(struct torture_context
*tctx
,
2632 struct dcerpc_pipe
*p
,
2636 struct spoolss_OpenPrinter r
;
2637 struct policy_handle handle
;
2640 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s\\%s", dcerpc_server_name(p
), name
);
2641 r
.in
.datatype
= NULL
;
2642 r
.in
.devmode_ctr
.devmode
= NULL
;
2643 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
2644 r
.out
.handle
= &handle
;
2646 torture_comment(tctx
, "Testing OpenPrinter(%s)\n", r
.in
.printername
);
2648 status
= dcerpc_spoolss_OpenPrinter(p
, tctx
, &r
);
2650 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
2652 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenPrinter failed");
2654 if (!test_GetPrinter(tctx
, p
, &handle
)) {
2658 if (!torture_setting_bool(tctx
, "samba3", false)) {
2659 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
2664 if (!test_ClosePrinter(tctx
, p
, &handle
)) {
2671 static bool call_OpenPrinterEx(struct torture_context
*tctx
,
2672 struct dcerpc_pipe
*p
,
2673 const char *name
, struct policy_handle
*handle
)
2675 struct spoolss_OpenPrinterEx r
;
2676 struct spoolss_UserLevel1 userlevel1
;
2679 if (name
&& name
[0]) {
2680 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s\\%s",
2681 dcerpc_server_name(p
), name
);
2683 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s",
2684 dcerpc_server_name(p
));
2687 r
.in
.datatype
= NULL
;
2688 r
.in
.devmode_ctr
.devmode
= NULL
;
2689 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
2691 r
.in
.userlevel
.level1
= &userlevel1
;
2692 r
.out
.handle
= handle
;
2694 userlevel1
.size
= 1234;
2695 userlevel1
.client
= "hello";
2696 userlevel1
.user
= "spottyfoot!";
2697 userlevel1
.build
= 1;
2698 userlevel1
.major
= 2;
2699 userlevel1
.minor
= 3;
2700 userlevel1
.processor
= 4;
2702 torture_comment(tctx
, "Testing OpenPrinterEx(%s)\n", r
.in
.printername
);
2704 status
= dcerpc_spoolss_OpenPrinterEx(p
, tctx
, &r
);
2706 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinterEx failed");
2708 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenPrinterEx failed");
2713 static bool test_OpenPrinterEx(struct torture_context
*tctx
,
2714 struct dcerpc_pipe
*p
,
2717 struct policy_handle handle
;
2720 if (!call_OpenPrinterEx(tctx
, p
, name
, &handle
)) {
2724 if (!test_GetPrinter(tctx
, p
, &handle
)) {
2728 if (!test_EnumForms(tctx
, p
, &handle
, false)) {
2732 if (!test_AddForm(tctx
, p
, &handle
, false)) {
2736 if (!test_EnumPrinterData(tctx
, p
, &handle
)) {
2740 if (!test_EnumPrinterDataEx(tctx
, p
, &handle
, "PrinterDriverData")) {
2744 if (!test_printer_keys(tctx
, p
, &handle
)) {
2748 if (!test_PausePrinter(tctx
, p
, &handle
)) {
2752 if (!test_DoPrintTest(tctx
, p
, &handle
)) {
2756 if (!test_ResumePrinter(tctx
, p
, &handle
)) {
2760 if (!test_SetPrinterData(tctx
, p
, &handle
)) {
2764 if (!test_SetPrinterDataEx(tctx
, p
, &handle
)) {
2768 if (!torture_setting_bool(tctx
, "samba3", false)) {
2769 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
2774 if (!test_ClosePrinter(tctx
, p
, &handle
)) {
2781 static bool test_EnumPrinters_old(struct torture_context
*tctx
, struct dcerpc_pipe
*p
)
2783 struct spoolss_EnumPrinters r
;
2785 uint16_t levels
[] = {1, 2, 4, 5};
2789 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
2790 union spoolss_PrinterInfo
*info
;
2795 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
2797 r
.in
.level
= levels
[i
];
2800 r
.out
.needed
= &needed
;
2801 r
.out
.count
= &count
;
2804 torture_comment(tctx
, "Testing EnumPrinters level %u\n", r
.in
.level
);
2806 status
= dcerpc_spoolss_EnumPrinters(p
, tctx
, &r
);
2807 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
2809 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2810 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2811 data_blob_clear(&blob
);
2812 r
.in
.buffer
= &blob
;
2813 r
.in
.offered
= needed
;
2814 status
= dcerpc_spoolss_EnumPrinters(p
, tctx
, &r
);
2817 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
2819 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
2822 torture_comment(tctx
, "No printers returned\n");
2826 for (j
=0;j
<count
;j
++) {
2827 if (r
.in
.level
== 1) {
2828 char *unc
= talloc_strdup(tctx
, info
[j
].info1
.name
);
2831 if (unc
[0] == '\\' && unc
[1] == '\\') {
2834 slash
= strchr(unc
, '\\');
2839 if (!test_OpenPrinter(tctx
, p
, name
)) {
2842 if (!test_OpenPrinterEx(tctx
, p
, name
)) {
2852 static bool test_GetPrinterDriver(struct torture_context
*tctx
,
2853 struct dcerpc_pipe
*p
,
2854 struct policy_handle
*handle
,
2855 const char *driver_name
)
2857 struct spoolss_GetPrinterDriver r
;
2860 r
.in
.handle
= handle
;
2861 r
.in
.architecture
= "W32X86";
2865 r
.out
.needed
= &needed
;
2867 torture_comment(tctx
, "Testing GetPrinterDriver level %d\n", r
.in
.level
);
2869 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver(p
, tctx
, &r
),
2870 "failed to call GetPrinterDriver");
2871 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2872 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2873 data_blob_clear(&blob
);
2874 r
.in
.buffer
= &blob
;
2875 r
.in
.offered
= needed
;
2876 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver(p
, tctx
, &r
),
2877 "failed to call GetPrinterDriver");
2880 torture_assert_werr_ok(tctx
, r
.out
.result
,
2881 "failed to call GetPrinterDriver");
2886 static bool test_GetPrinterDriver2(struct torture_context
*tctx
,
2887 struct dcerpc_pipe
*p
,
2888 struct policy_handle
*handle
,
2889 const char *driver_name
)
2891 struct spoolss_GetPrinterDriver2 r
;
2893 uint32_t server_major_version
;
2894 uint32_t server_minor_version
;
2896 r
.in
.handle
= handle
;
2897 r
.in
.architecture
= "W32X86";
2901 r
.in
.client_major_version
= 0;
2902 r
.in
.client_minor_version
= 0;
2903 r
.out
.needed
= &needed
;
2904 r
.out
.server_major_version
= &server_major_version
;
2905 r
.out
.server_minor_version
= &server_minor_version
;
2907 torture_comment(tctx
, "Testing GetPrinterDriver2 level %d\n", r
.in
.level
);
2909 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver2(p
, tctx
, &r
),
2910 "failed to call GetPrinterDriver2");
2911 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2912 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2913 data_blob_clear(&blob
);
2914 r
.in
.buffer
= &blob
;
2915 r
.in
.offered
= needed
;
2916 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver2(p
, tctx
, &r
),
2917 "failed to call GetPrinterDriver2");
2920 torture_assert_werr_ok(tctx
, r
.out
.result
,
2921 "failed to call GetPrinterDriver2");
2926 static bool test_EnumPrinterDrivers_old(struct torture_context
*tctx
,
2927 struct dcerpc_pipe
*p
)
2929 struct spoolss_EnumPrinterDrivers r
;
2931 uint16_t levels
[] = {1, 2, 3, 4, 5, 6};
2934 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
2938 union spoolss_DriverInfo
*info
;
2940 r
.in
.server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
2941 r
.in
.environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
2942 r
.in
.level
= levels
[i
];
2945 r
.out
.needed
= &needed
;
2946 r
.out
.count
= &count
;
2949 torture_comment(tctx
, "Testing EnumPrinterDrivers level %u\n", r
.in
.level
);
2951 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, tctx
, &r
);
2953 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterDrivers failed");
2955 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2956 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2957 data_blob_clear(&blob
);
2958 r
.in
.buffer
= &blob
;
2959 r
.in
.offered
= needed
;
2960 status
= dcerpc_spoolss_EnumPrinterDrivers(p
, tctx
, &r
);
2963 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterDrivers failed");
2965 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDrivers failed");
2968 torture_comment(tctx
, "No printer drivers returned\n");
2976 static bool test_DeletePrinter(struct torture_context
*tctx
,
2977 struct dcerpc_pipe
*p
,
2978 struct policy_handle
*handle
)
2980 struct spoolss_DeletePrinter r
;
2982 torture_comment(tctx
, "Testing DeletePrinter\n");
2984 r
.in
.handle
= handle
;
2986 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_DeletePrinter(p
, tctx
, &r
),
2987 "failed to delete printer");
2988 torture_assert_werr_ok(tctx
, r
.out
.result
,
2989 "failed to delete printer");
2994 static bool test_EnumPrinters_findname(struct torture_context
*tctx
,
2995 struct dcerpc_pipe
*p
,
3001 struct spoolss_EnumPrinters e
;
3003 union spoolss_PrinterInfo
*info
;
3014 e
.out
.count
= &count
;
3016 e
.out
.needed
= &needed
;
3018 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters(p
, tctx
, &e
),
3019 "failed to enum printers");
3021 if (W_ERROR_EQUAL(e
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
3022 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
3023 data_blob_clear(&blob
);
3024 e
.in
.buffer
= &blob
;
3025 e
.in
.offered
= needed
;
3027 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters(p
, tctx
, &e
),
3028 "failed to enum printers");
3031 torture_assert_werr_ok(tctx
, e
.out
.result
,
3032 "failed to enum printers");
3034 for (i
=0; i
< count
; i
++) {
3036 const char *current
= NULL
;
3040 current
= info
[i
].info1
.name
;
3044 if (strequal(current
, name
)) {
3053 static bool test_AddPrinter_wellknown(struct torture_context
*tctx
,
3054 struct dcerpc_pipe
*p
,
3055 const char *printername
,
3059 struct spoolss_AddPrinter r
;
3060 struct spoolss_AddPrinterEx rex
;
3061 struct spoolss_SetPrinterInfoCtr info_ctr
;
3062 struct spoolss_SetPrinterInfo1 info1
;
3063 struct spoolss_DevmodeContainer devmode_ctr
;
3064 struct sec_desc_buf secdesc_ctr
;
3065 struct spoolss_UserLevelCtr userlevel_ctr
;
3066 struct policy_handle handle
;
3069 ZERO_STRUCT(devmode_ctr
);
3070 ZERO_STRUCT(secdesc_ctr
);
3071 ZERO_STRUCT(userlevel_ctr
);
3074 torture_comment(tctx
, "Testing AddPrinter%s level 1\n", ex
? "Ex":"");
3076 /* try to add printer to wellknown printer list (level 1) */
3078 userlevel_ctr
.level
= 1;
3080 info_ctr
.info
.info1
= &info1
;
3083 rex
.in
.server
= NULL
;
3084 rex
.in
.info_ctr
= &info_ctr
;
3085 rex
.in
.devmode_ctr
= &devmode_ctr
;
3086 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
3087 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
3088 rex
.out
.handle
= &handle
;
3091 r
.in
.info_ctr
= &info_ctr
;
3092 r
.in
.devmode_ctr
= &devmode_ctr
;
3093 r
.in
.secdesc_ctr
= &secdesc_ctr
;
3094 r
.out
.handle
= &handle
;
3096 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3097 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3098 "failed to add printer");
3099 result
= ex
? rex
.out
.result
: r
.out
.result
;
3100 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
3101 "unexpected result code");
3103 info1
.name
= printername
;
3104 info1
.flags
= PRINTER_ATTRIBUTE_SHARED
;
3106 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3107 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3108 "failed to add printer");
3109 result
= ex
? rex
.out
.result
: r
.out
.result
;
3110 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
3111 "unexpected result code");
3113 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
3114 better do a real check to see the printer is really there */
3116 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, p
,
3117 PRINTER_ENUM_NETWORK
, 1,
3120 "failed to enum printers");
3122 torture_assert(tctx
, found
, "failed to find newly added printer");
3126 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3127 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3128 "failed to add printer");
3129 result
= ex
? rex
.out
.result
: r
.out
.result
;
3130 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
3131 "unexpected result code");
3133 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
3134 better do a real check to see the printer has really been removed
3135 from the well known printer list */
3139 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, p
,
3140 PRINTER_ENUM_NETWORK
, 1,
3143 "failed to enum printers");
3145 torture_assert(tctx
, !found
, "printer still in well known printer list");
3150 static bool test_AddPrinter_normal(struct torture_context
*tctx
,
3151 struct dcerpc_pipe
*p
,
3152 struct policy_handle
*handle_p
,
3153 const char *printername
,
3154 const char *drivername
,
3155 const char *portname
,
3159 struct spoolss_AddPrinter r
;
3160 struct spoolss_AddPrinterEx rex
;
3161 struct spoolss_SetPrinterInfoCtr info_ctr
;
3162 struct spoolss_SetPrinterInfo2 info2
;
3163 struct spoolss_DevmodeContainer devmode_ctr
;
3164 struct sec_desc_buf secdesc_ctr
;
3165 struct spoolss_UserLevelCtr userlevel_ctr
;
3166 struct policy_handle handle
;
3169 ZERO_STRUCT(devmode_ctr
);
3170 ZERO_STRUCT(secdesc_ctr
);
3171 ZERO_STRUCT(userlevel_ctr
);
3173 torture_comment(tctx
, "Testing AddPrinter%s level 2\n", ex
? "Ex":"");
3175 userlevel_ctr
.level
= 1;
3177 rex
.in
.server
= NULL
;
3178 rex
.in
.info_ctr
= &info_ctr
;
3179 rex
.in
.devmode_ctr
= &devmode_ctr
;
3180 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
3181 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
3182 rex
.out
.handle
= &handle
;
3185 r
.in
.info_ctr
= &info_ctr
;
3186 r
.in
.devmode_ctr
= &devmode_ctr
;
3187 r
.in
.secdesc_ctr
= &secdesc_ctr
;
3188 r
.out
.handle
= &handle
;
3192 /* try to add printer to printer list (level 2) */
3196 info_ctr
.info
.info2
= &info2
;
3199 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3200 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3201 "failed to add printer");
3202 result
= ex
? rex
.out
.result
: r
.out
.result
;
3203 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
3204 "unexpected result code");
3206 info2
.printername
= printername
;
3208 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3209 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3210 "failed to add printer");
3211 result
= ex
? rex
.out
.result
: r
.out
.result
;
3213 if (W_ERROR_EQUAL(result
, WERR_PRINTER_ALREADY_EXISTS
)) {
3214 struct policy_handle printer_handle
;
3216 torture_assert(tctx
, call_OpenPrinterEx(tctx
, p
, printername
, &printer_handle
),
3217 "failed to open printer handle");
3219 torture_assert(tctx
, test_DeletePrinter(tctx
, p
, &printer_handle
),
3220 "failed to delete printer");
3222 torture_assert(tctx
, test_ClosePrinter(tctx
, p
, &printer_handle
),
3223 "failed to close server handle");
3228 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PORT
,
3229 "unexpected result code");
3231 info2
.portname
= portname
;
3233 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3234 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3235 "failed to add printer");
3236 result
= ex
? rex
.out
.result
: r
.out
.result
;
3237 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTER_DRIVER
,
3238 "unexpected result code");
3240 info2
.drivername
= drivername
;
3242 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3243 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3244 "failed to add printer");
3245 result
= ex
? rex
.out
.result
: r
.out
.result
;
3246 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTPROCESSOR
,
3247 "unexpected result code");
3249 info2
.printprocessor
= "winprint";
3251 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3252 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3253 "failed to add printer");
3254 result
= ex
? rex
.out
.result
: r
.out
.result
;
3255 torture_assert_werr_ok(tctx
, result
,
3256 "failed to add printer");
3260 /* we are paranoid, really check if the printer is there now */
3262 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, p
,
3263 PRINTER_ENUM_LOCAL
, 1,
3266 "failed to enum printers");
3267 torture_assert(tctx
, found
, "failed to find newly added printer");
3269 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx(p
, tctx
, &rex
) :
3270 dcerpc_spoolss_AddPrinter(p
, tctx
, &r
),
3271 "failed to add printer");
3272 result
= ex
? rex
.out
.result
: r
.out
.result
;
3273 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
3274 "unexpected result code");
3279 static bool test_AddPrinterEx(struct torture_context
*tctx
,
3280 struct dcerpc_pipe
*p
,
3281 struct policy_handle
*handle_p
,
3282 const char *printername
,
3283 const char *drivername
,
3284 const char *portname
)
3288 if (!torture_setting_bool(tctx
, "samba3", false)) {
3289 if (!test_AddPrinter_wellknown(tctx
, p
, TORTURE_WELLKNOWN_PRINTER_EX
, true)) {
3290 torture_comment(tctx
, "failed to add printer to well known list\n");
3295 if (!test_AddPrinter_normal(tctx
, p
, handle_p
,
3296 printername
, drivername
, portname
,
3298 torture_comment(tctx
, "failed to add printer to printer list\n");
3305 static bool test_AddPrinter(struct torture_context
*tctx
,
3306 struct dcerpc_pipe
*p
,
3307 struct policy_handle
*handle_p
,
3308 const char *printername
,
3309 const char *drivername
,
3310 const char *portname
)
3314 if (!torture_setting_bool(tctx
, "samba3", false)) {
3315 if (!test_AddPrinter_wellknown(tctx
, p
, TORTURE_WELLKNOWN_PRINTER
, false)) {
3316 torture_comment(tctx
, "failed to add printer to well known list\n");
3321 if (!test_AddPrinter_normal(tctx
, p
, handle_p
,
3322 printername
, drivername
, portname
,
3324 torture_comment(tctx
, "failed to add printer to printer list\n");
3331 static bool test_printer_info(struct torture_context
*tctx
,
3332 struct dcerpc_pipe
*p
,
3333 struct policy_handle
*handle
)
3337 if (!test_PrinterInfo(tctx
, p
, handle
)) {
3341 if (!test_SetPrinter_errors(tctx
, p
, handle
)) {
3348 static bool test_EnumPrinterKey(struct torture_context
*tctx
,
3349 struct dcerpc_pipe
*p
,
3350 struct policy_handle
*handle
,
3351 const char *key_name
,
3352 const char ***array
)
3354 struct spoolss_EnumPrinterKey r
;
3356 struct spoolss_StringArray2 key_buffer
;
3357 uint32_t offered
[] = { 0, 512, 1024, 2048 };
3360 r
.in
.handle
= handle
;
3361 r
.in
.key_name
= key_name
;
3362 r
.out
.key_buffer
= &key_buffer
;
3363 r
.out
.needed
= &needed
;
3365 for (i
=0; i
< ARRAY_SIZE(offered
); i
++) {
3366 r
.in
.offered
= offered
[i
];
3368 torture_comment(tctx
, "Testing EnumPrinterKey(%s) with %d offered\n", r
.in
.key_name
, r
.in
.offered
);
3370 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterKey(p
, tctx
, &r
),
3371 "failed to call EnumPrinterKey");
3372 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
3373 torture_assert(tctx
, (key_buffer
._ndr_size
== 0),
3374 talloc_asprintf(tctx
, "EnumPrinterKey did not return 0 _ndr_size (but %d), windows clients would abort here!", key_buffer
._ndr_size
));
3375 r
.in
.offered
= needed
;
3376 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterKey(p
, tctx
, &r
),
3377 "failed to call EnumPrinterKey");
3379 torture_assert_werr_ok(tctx
, r
.out
.result
,
3380 "failed to call EnumPrinterKey");
3382 torture_assert(tctx
, (key_buffer
._ndr_size
* 2 == r
.in
.offered
),
3383 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
3384 key_buffer
._ndr_size
, r
.in
.offered
/2));
3386 torture_assert(tctx
, (*r
.out
.needed
<= r
.in
.offered
),
3387 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r
.out
.needed
, r
.in
.offered
));
3389 torture_assert(tctx
, (*r
.out
.needed
<= key_buffer
._ndr_size
* 2),
3390 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r
.out
.needed
, key_buffer
._ndr_size
));
3395 *array
= key_buffer
.string
;
3401 bool test_printer_keys(struct torture_context
*tctx
,
3402 struct dcerpc_pipe
*p
,
3403 struct policy_handle
*handle
)
3405 const char **key_array
= NULL
;
3408 torture_assert(tctx
, test_EnumPrinterKey(tctx
, p
, handle
, "", &key_array
),
3409 "failed to call test_EnumPrinterKey");
3411 for (i
=0; key_array
&& key_array
[i
]; i
++) {
3412 torture_assert(tctx
, test_EnumPrinterKey(tctx
, p
, handle
, key_array
[i
], NULL
),
3413 "failed to call test_EnumPrinterKey");
3415 for (i
=0; key_array
&& key_array
[i
]; i
++) {
3416 torture_assert(tctx
, test_EnumPrinterDataEx(tctx
, p
, handle
, key_array
[i
]),
3417 "failed to call test_EnumPrinterDataEx");
3423 static bool test_printer(struct torture_context
*tctx
,
3424 struct dcerpc_pipe
*p
)
3427 struct policy_handle handle
[2];
3429 const char *drivername
= "Microsoft XPS Document Writer";
3430 const char *portname
= "LPT1:";
3432 /* test printer created via AddPrinter */
3434 if (!test_AddPrinter(tctx
, p
, &handle
[0], TORTURE_PRINTER
, drivername
, portname
)) {
3438 if (!test_printer_info(tctx
, p
, &handle
[0])) {
3442 if (!test_printer_keys(tctx
, p
, &handle
[0])) {
3446 if (!test_DeletePrinter(tctx
, p
, &handle
[0])) {
3450 if (!test_EnumPrinters_findname(tctx
, p
, PRINTER_ENUM_LOCAL
, 1,
3451 TORTURE_PRINTER
, &found
)) {
3455 torture_assert(tctx
, !found
, "deleted printer still there");
3457 /* test printer created via AddPrinterEx */
3459 if (!test_AddPrinterEx(tctx
, p
, &handle
[1], TORTURE_PRINTER_EX
, drivername
, portname
)) {
3463 if (!test_printer_info(tctx
, p
, &handle
[1])) {
3467 if (!test_printer_keys(tctx
, p
, &handle
[1])) {
3471 if (!test_DeletePrinter(tctx
, p
, &handle
[1])) {
3475 if (!test_EnumPrinters_findname(tctx
, p
, PRINTER_ENUM_LOCAL
, 1,
3476 TORTURE_PRINTER_EX
, &found
)) {
3480 torture_assert(tctx
, !found
, "deleted printer still there");
3485 bool torture_rpc_spoolss(struct torture_context
*torture
)
3488 struct dcerpc_pipe
*p
;
3490 struct test_spoolss_context
*ctx
;
3492 status
= torture_rpc_connection(torture
, &p
, &ndr_table_spoolss
);
3493 if (!NT_STATUS_IS_OK(status
)) {
3497 ctx
= talloc_zero(torture
, struct test_spoolss_context
);
3499 ret
&= test_OpenPrinter_server(torture
, p
, &ctx
->server_handle
);
3500 ret
&= test_GetPrinterData_list(torture
, p
, &ctx
->server_handle
);
3501 ret
&= test_EnumForms(torture
, p
, &ctx
->server_handle
, true);
3502 ret
&= test_AddForm(torture
, p
, &ctx
->server_handle
, true);
3503 ret
&= test_EnumPorts(torture
, p
, ctx
);
3504 ret
&= test_GetPrinterDriverDirectory(torture
, p
, ctx
);
3505 ret
&= test_GetPrintProcessorDirectory(torture
, p
, ctx
);
3506 ret
&= test_EnumPrinterDrivers(torture
, p
, ctx
, SPOOLSS_ARCHITECTURE_NT_X86
);
3507 ret
&= test_EnumPrinterDrivers(torture
, p
, ctx
, SPOOLSS_ARCHITECTURE_ALL
);
3508 ret
&= test_EnumMonitors(torture
, p
, ctx
);
3509 ret
&= test_EnumPrintProcessors(torture
, p
, ctx
);
3510 ret
&= test_EnumPrintProcDataTypes(torture
, p
, ctx
);
3511 ret
&= test_EnumPrinters(torture
, p
, ctx
);
3512 ret
&= test_OpenPrinter_badname(torture
, p
, "__INVALID_PRINTER__");
3513 ret
&= test_OpenPrinter_badname(torture
, p
, "\\\\__INVALID_HOST__");
3514 ret
&= test_OpenPrinter_badname(torture
, p
, "");
3515 ret
&= test_OpenPrinter_badname(torture
, p
, "\\\\\\");
3516 ret
&= test_OpenPrinter_badname(torture
, p
, "\\\\\\__INVALID_PRINTER__");
3517 ret
&= test_OpenPrinter_badname(torture
, p
, talloc_asprintf(torture
, "\\\\%s\\", dcerpc_server_name(p
)));
3518 ret
&= test_OpenPrinter_badname(torture
, p
,
3519 talloc_asprintf(torture
, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p
)));
3522 ret
&= test_AddPort(torture
, p
);
3523 ret
&= test_EnumPorts_old(torture
, p
);
3524 ret
&= test_EnumPrinters_old(torture
, p
);
3525 ret
&= test_EnumPrinterDrivers_old(torture
, p
);
3530 struct torture_suite
*torture_rpc_spoolss_printer(TALLOC_CTX
*mem_ctx
)
3532 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "SPOOLSS-PRINTER");
3534 struct torture_rpc_tcase
*tcase
= torture_suite_add_rpc_iface_tcase(suite
,
3535 "printer", &ndr_table_spoolss
);
3537 torture_rpc_tcase_add_test(tcase
, "printer", test_printer
);