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-2010
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 "librpc/gen_ndr/ndr_misc.h"
27 #include "librpc/gen_ndr/ndr_spoolss.h"
28 #include "librpc/gen_ndr/ndr_spoolss_c.h"
29 #include "librpc/gen_ndr/ndr_winreg_c.h"
30 #include "librpc/gen_ndr/ndr_security.h"
31 #include "libcli/security/security.h"
32 #include "torture/rpc/rpc.h"
33 #include "param/param.h"
34 #include "lib/registry/registry.h"
36 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
37 #define TORTURE_PRINTER "torture_printer"
38 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
39 #define TORTURE_PRINTER_EX "torture_printer_ex"
41 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
42 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
43 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
44 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
46 struct test_spoolss_context
{
47 /* print server handle */
48 struct policy_handle server_handle
;
51 uint32_t port_count
[3];
52 union spoolss_PortInfo
*ports
[3];
54 /* for EnumPrinterDrivers */
55 uint32_t driver_count
[8];
56 union spoolss_DriverInfo
*drivers
[8];
58 /* for EnumMonitors */
59 uint32_t monitor_count
[3];
60 union spoolss_MonitorInfo
*monitors
[3];
62 /* for EnumPrintProcessors */
63 uint32_t print_processor_count
[2];
64 union spoolss_PrintProcessorInfo
*print_processors
[2];
66 /* for EnumPrinters */
67 uint32_t printer_count
[6];
68 union spoolss_PrinterInfo
*printers
[6];
71 #define COMPARE_STRING(tctx, c,r,e) \
72 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
74 /* not every compiler supports __typeof__() */
76 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
77 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
78 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
80 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
81 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
85 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
88 #define COMPARE_UINT32(tctx, c, r, e) do {\
89 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
90 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
93 #define COMPARE_UINT64(tctx, c, r, e) do {\
94 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
95 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
99 #define COMPARE_NTTIME(tctx, c, r, e) do {\
100 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
101 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
104 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
106 if (!c.e && !r.e) { \
110 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
113 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
115 for (__i=0;c.e[__i] != NULL; __i++) { \
116 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
120 #define CHECK_ALIGN(size, n) do {\
122 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
123 size, n, size + n - (size % n));\
127 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
129 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, ic, needed, align) do { \
130 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
131 uint32_t size = ndr_size_##fn##_info(tctx, ic, level, count, info);\
132 uint32_t round_size = DO_ROUND(size, align);\
133 if (round_size != needed) {\
134 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
135 CHECK_ALIGN(size, align);\
140 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, ic, needed, align) do { \
141 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
142 uint32_t size = ndr_size_##fn##_info(tctx, ic, count, info);\
143 uint32_t round_size = DO_ROUND(size, align);\
144 if (round_size != needed) {\
145 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
146 CHECK_ALIGN(size, align);\
151 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, ic, needed, align) do { \
152 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
153 uint32_t size = ndr_size_##fn(info, level, ic, 0);\
154 uint32_t round_size = DO_ROUND(size, align);\
155 if (round_size != needed) {\
156 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
157 CHECK_ALIGN(size, align);\
162 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context
*tctx
,
163 const union spoolss_PrinterInfo
*i
,
165 union spoolss_SetPrinterInfo
*s
)
169 s
->info0
= talloc(tctx
, struct spoolss_SetPrinterInfo0
);
172 s
->info2
= talloc(tctx
, struct spoolss_SetPrinterInfo2
);
173 s
->info2
->servername
= i
->info2
.servername
;
174 s
->info2
->printername
= i
->info2
.printername
;
175 s
->info2
->sharename
= i
->info2
.sharename
;
176 s
->info2
->portname
= i
->info2
.portname
;
177 s
->info2
->drivername
= i
->info2
.drivername
;
178 s
->info2
->comment
= i
->info2
.comment
;
179 s
->info2
->location
= i
->info2
.location
;
180 s
->info2
->devmode_ptr
= 0;
181 s
->info2
->sepfile
= i
->info2
.sepfile
;
182 s
->info2
->printprocessor
= i
->info2
.printprocessor
;
183 s
->info2
->datatype
= i
->info2
.datatype
;
184 s
->info2
->parameters
= i
->info2
.parameters
;
185 s
->info2
->secdesc_ptr
= 0;
186 s
->info2
->attributes
= i
->info2
.attributes
;
187 s
->info2
->priority
= i
->info2
.priority
;
188 s
->info2
->defaultpriority
= i
->info2
.defaultpriority
;
189 s
->info2
->starttime
= i
->info2
.starttime
;
190 s
->info2
->untiltime
= i
->info2
.untiltime
;
191 s
->info2
->status
= i
->info2
.status
;
192 s
->info2
->cjobs
= i
->info2
.cjobs
;
193 s
->info2
->averageppm
= i
->info2
.averageppm
;
209 static bool test_OpenPrinter_server(struct torture_context
*tctx
,
210 struct dcerpc_pipe
*p
,
211 struct policy_handle
*server_handle
)
214 struct spoolss_OpenPrinter op
;
215 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
217 op
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
218 op
.in
.datatype
= NULL
;
219 op
.in
.devmode_ctr
.devmode
= NULL
;
220 op
.in
.access_mask
= 0;
221 op
.out
.handle
= server_handle
;
223 torture_comment(tctx
, "Testing OpenPrinter(%s)\n", op
.in
.printername
);
225 status
= dcerpc_spoolss_OpenPrinter_r(b
, tctx
, &op
);
226 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_OpenPrinter failed");
227 torture_assert_werr_ok(tctx
, op
.out
.result
, "dcerpc_spoolss_OpenPrinter failed");
232 static bool test_EnumPorts(struct torture_context
*tctx
,
233 struct dcerpc_binding_handle
*b
,
234 struct test_spoolss_context
*ctx
)
237 struct spoolss_EnumPorts r
;
238 uint16_t levels
[] = { 1, 2 };
241 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
242 int level
= levels
[i
];
246 union spoolss_PortInfo
*info
;
248 r
.in
.servername
= "";
252 r
.out
.needed
= &needed
;
253 r
.out
.count
= &count
;
256 torture_comment(tctx
, "Testing EnumPorts level %u\n", r
.in
.level
);
258 status
= dcerpc_spoolss_EnumPorts_r(b
, ctx
, &r
);
259 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPorts failed");
260 if (W_ERROR_IS_OK(r
.out
.result
)) {
261 /* TODO: do some more checks here */
264 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
265 "EnumPorts unexpected return code");
267 blob
= data_blob_talloc(ctx
, NULL
, needed
);
268 data_blob_clear(&blob
);
270 r
.in
.offered
= needed
;
272 status
= dcerpc_spoolss_EnumPorts_r(b
, ctx
, &r
);
273 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPorts failed");
275 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
277 torture_assert(tctx
, info
, "EnumPorts returned no info");
279 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
281 ctx
->port_count
[level
] = count
;
282 ctx
->ports
[level
] = info
;
285 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
286 int level
= levels
[i
];
287 int old_level
= levels
[i
-1];
288 torture_assert_int_equal(tctx
, ctx
->port_count
[level
], ctx
->port_count
[old_level
],
289 "EnumPorts invalid value");
291 /* if the array sizes are not the same we would maybe segfault in the following code */
293 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
294 int level
= levels
[i
];
295 for (j
=0;j
<ctx
->port_count
[level
];j
++) {
296 union spoolss_PortInfo
*cur
= &ctx
->ports
[level
][j
];
297 union spoolss_PortInfo
*ref
= &ctx
->ports
[2][j
];
300 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, port_name
);
303 /* level 2 is our reference, and it makes no sense to compare it to itself */
312 static bool test_GetPrintProcessorDirectory(struct torture_context
*tctx
,
313 struct dcerpc_pipe
*p
,
314 const char *environment
)
317 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
318 struct spoolss_GetPrintProcessorDirectory r
;
333 .server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
))
336 .server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
))
342 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
343 int level
= levels
[i
].level
;
346 r
.in
.server
= levels
[i
].server
;
347 r
.in
.environment
= environment
;
351 r
.out
.needed
= &needed
;
353 torture_comment(tctx
, "Testing GetPrintProcessorDirectory level %u\n", r
.in
.level
);
355 status
= dcerpc_spoolss_GetPrintProcessorDirectory_r(b
, tctx
, &r
);
356 torture_assert_ntstatus_ok(tctx
, status
,
357 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
358 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
359 "GetPrintProcessorDirectory unexpected return code");
361 blob
= data_blob_talloc(tctx
, NULL
, needed
);
362 data_blob_clear(&blob
);
364 r
.in
.offered
= needed
;
366 status
= dcerpc_spoolss_GetPrintProcessorDirectory_r(b
, tctx
, &r
);
367 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
369 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrintProcessorDirectory failed");
371 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 2);
378 static bool test_GetPrinterDriverDirectory(struct torture_context
*tctx
,
379 struct dcerpc_pipe
*p
,
380 const char *environment
)
383 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
384 struct spoolss_GetPrinterDriverDirectory r
;
399 .server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
))
402 .server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
))
408 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
409 int level
= levels
[i
].level
;
412 r
.in
.server
= levels
[i
].server
;
413 r
.in
.environment
= environment
;
417 r
.out
.needed
= &needed
;
419 torture_comment(tctx
, "Testing GetPrinterDriverDirectory level %u\n", r
.in
.level
);
421 status
= dcerpc_spoolss_GetPrinterDriverDirectory_r(b
, tctx
, &r
);
422 torture_assert_ntstatus_ok(tctx
, status
,
423 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
424 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
425 "GetPrinterDriverDirectory unexpected return code");
427 blob
= data_blob_talloc(tctx
, NULL
, needed
);
428 data_blob_clear(&blob
);
430 r
.in
.offered
= needed
;
432 status
= dcerpc_spoolss_GetPrinterDriverDirectory_r(b
, tctx
, &r
);
433 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
435 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrinterDriverDirectory failed");
437 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 2);
443 static bool test_EnumPrinterDrivers(struct torture_context
*tctx
,
444 struct dcerpc_pipe
*p
,
445 struct test_spoolss_context
*ctx
,
446 const char *architecture
)
449 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
450 struct spoolss_EnumPrinterDrivers r
;
451 uint16_t levels
[] = { 1, 2, 3, 4, 5, 6, 8 };
454 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
455 int level
= levels
[i
];
459 union spoolss_DriverInfo
*info
;
461 /* FIXME: gd, come back and fix "" as server, and handle
462 * priority of returned error codes in torture test and samba 3
465 r
.in
.server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
466 r
.in
.environment
= architecture
;
470 r
.out
.needed
= &needed
;
471 r
.out
.count
= &count
;
474 torture_comment(tctx
, "Testing EnumPrinterDrivers level %u (%s)\n", r
.in
.level
, r
.in
.environment
);
476 status
= dcerpc_spoolss_EnumPrinterDrivers_r(b
, ctx
, &r
);
477 torture_assert_ntstatus_ok(tctx
, status
,
478 "dcerpc_spoolss_EnumPrinterDrivers failed");
479 if (W_ERROR_IS_OK(r
.out
.result
)) {
480 /* TODO: do some more checks here */
483 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
484 blob
= data_blob_talloc(ctx
, NULL
, needed
);
485 data_blob_clear(&blob
);
487 r
.in
.offered
= needed
;
489 status
= dcerpc_spoolss_EnumPrinterDrivers_r(b
, ctx
, &r
);
490 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinterDrivers failed");
493 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDrivers failed");
495 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
497 ctx
->driver_count
[level
] = count
;
498 ctx
->drivers
[level
] = info
;
501 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
502 int level
= levels
[i
];
503 int old_level
= levels
[i
-1];
505 torture_assert_int_equal(tctx
, ctx
->driver_count
[level
], ctx
->driver_count
[old_level
],
506 "EnumPrinterDrivers invalid value");
509 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
510 int level
= levels
[i
];
512 for (j
=0;j
<ctx
->driver_count
[level
];j
++) {
513 union spoolss_DriverInfo
*cur
= &ctx
->drivers
[level
][j
];
514 union spoolss_DriverInfo
*ref
= &ctx
->drivers
[8][j
];
518 COMPARE_STRING(tctx
, cur
->info1
, ref
->info8
, driver_name
);
521 COMPARE_UINT32(tctx
, cur
->info2
, ref
->info8
, version
);
522 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, driver_name
);
523 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, architecture
);
524 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, driver_path
);
525 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, data_file
);
526 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, config_file
);
529 COMPARE_UINT32(tctx
, cur
->info3
, ref
->info8
, version
);
530 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, driver_name
);
531 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, architecture
);
532 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, driver_path
);
533 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, data_file
);
534 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, config_file
);
535 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, help_file
);
536 COMPARE_STRING_ARRAY(tctx
, cur
->info3
, ref
->info8
, dependent_files
);
537 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, monitor_name
);
538 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, default_datatype
);
541 COMPARE_UINT32(tctx
, cur
->info4
, ref
->info8
, version
);
542 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, driver_name
);
543 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, architecture
);
544 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, driver_path
);
545 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, data_file
);
546 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, config_file
);
547 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, help_file
);
548 COMPARE_STRING_ARRAY(tctx
, cur
->info4
, ref
->info8
, dependent_files
);
549 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, monitor_name
);
550 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, default_datatype
);
551 COMPARE_STRING_ARRAY(tctx
, cur
->info4
, ref
->info8
, previous_names
);
554 COMPARE_UINT32(tctx
, cur
->info5
, ref
->info8
, version
);
555 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, driver_name
);
556 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, architecture
);
557 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, driver_path
);
558 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, data_file
);
559 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, config_file
);
560 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
561 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
562 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
565 COMPARE_UINT32(tctx
, cur
->info6
, ref
->info8
, version
);
566 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, driver_name
);
567 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, architecture
);
568 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, driver_path
);
569 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, data_file
);
570 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, config_file
);
571 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, help_file
);
572 COMPARE_STRING_ARRAY(tctx
, cur
->info6
, ref
->info8
, dependent_files
);
573 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, monitor_name
);
574 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, default_datatype
);
575 COMPARE_STRING_ARRAY(tctx
, cur
->info6
, ref
->info8
, previous_names
);
576 COMPARE_NTTIME(tctx
, cur
->info6
, ref
->info8
, driver_date
);
577 COMPARE_UINT64(tctx
, cur
->info6
, ref
->info8
, driver_version
);
578 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, manufacturer_name
);
579 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, manufacturer_url
);
580 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, hardware_id
);
581 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, provider
);
584 /* level 8 is our reference, and it makes no sense to compare it to itself */
593 static bool test_EnumMonitors(struct torture_context
*tctx
,
594 struct dcerpc_binding_handle
*b
,
595 struct test_spoolss_context
*ctx
)
598 struct spoolss_EnumMonitors r
;
599 uint16_t levels
[] = { 1, 2 };
602 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
603 int level
= levels
[i
];
607 union spoolss_MonitorInfo
*info
;
609 r
.in
.servername
= "";
613 r
.out
.needed
= &needed
;
614 r
.out
.count
= &count
;
617 torture_comment(tctx
, "Testing EnumMonitors level %u\n", r
.in
.level
);
619 status
= dcerpc_spoolss_EnumMonitors_r(b
, ctx
, &r
);
620 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumMonitors failed");
621 if (W_ERROR_IS_OK(r
.out
.result
)) {
622 /* TODO: do some more checks here */
625 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
626 "EnumMonitors failed");
628 blob
= data_blob_talloc(ctx
, NULL
, needed
);
629 data_blob_clear(&blob
);
631 r
.in
.offered
= needed
;
633 status
= dcerpc_spoolss_EnumMonitors_r(b
, ctx
, &r
);
634 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumMonitors failed");
636 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumMonitors failed");
638 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
640 ctx
->monitor_count
[level
] = count
;
641 ctx
->monitors
[level
] = info
;
644 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
645 int level
= levels
[i
];
646 int old_level
= levels
[i
-1];
647 torture_assert_int_equal(tctx
, ctx
->monitor_count
[level
], ctx
->monitor_count
[old_level
],
648 "EnumMonitors invalid value");
651 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
652 int level
= levels
[i
];
653 for (j
=0;j
<ctx
->monitor_count
[level
];j
++) {
654 union spoolss_MonitorInfo
*cur
= &ctx
->monitors
[level
][j
];
655 union spoolss_MonitorInfo
*ref
= &ctx
->monitors
[2][j
];
658 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, monitor_name
);
661 /* level 2 is our reference, and it makes no sense to compare it to itself */
670 static bool test_EnumPrintProcessors(struct torture_context
*tctx
,
671 struct dcerpc_binding_handle
*b
,
672 struct test_spoolss_context
*ctx
,
673 const char *environment
)
676 struct spoolss_EnumPrintProcessors r
;
677 uint16_t levels
[] = { 1 };
680 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
681 int level
= levels
[i
];
685 union spoolss_PrintProcessorInfo
*info
;
687 r
.in
.servername
= "";
688 r
.in
.environment
= environment
;
692 r
.out
.needed
= &needed
;
693 r
.out
.count
= &count
;
696 torture_comment(tctx
, "Testing EnumPrintProcessors level %u\n", r
.in
.level
);
698 status
= dcerpc_spoolss_EnumPrintProcessors_r(b
, ctx
, &r
);
699 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcessors failed");
700 if (W_ERROR_IS_OK(r
.out
.result
)) {
701 /* TODO: do some more checks here */
704 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
705 "EnumPrintProcessors unexpected return code");
707 blob
= data_blob_talloc(ctx
, NULL
, needed
);
708 data_blob_clear(&blob
);
710 r
.in
.offered
= needed
;
712 status
= dcerpc_spoolss_EnumPrintProcessors_r(b
, ctx
, &r
);
713 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcessors failed");
715 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrintProcessors failed");
717 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
719 ctx
->print_processor_count
[level
] = count
;
720 ctx
->print_processors
[level
] = info
;
723 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
724 int level
= levels
[i
];
725 int old_level
= levels
[i
-1];
726 torture_assert_int_equal(tctx
, ctx
->print_processor_count
[level
], ctx
->print_processor_count
[old_level
],
727 "EnumPrintProcessors failed");
730 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
731 int level
= levels
[i
];
732 for (j
=0;j
<ctx
->print_processor_count
[level
];j
++) {
734 union spoolss_PrintProcessorInfo
*cur
= &ctx
->print_processors
[level
][j
];
735 union spoolss_PrintProcessorInfo
*ref
= &ctx
->print_processors
[1][j
];
739 /* level 1 is our reference, and it makes no sense to compare it to itself */
748 static bool test_EnumPrintProcDataTypes(struct torture_context
*tctx
,
749 struct dcerpc_binding_handle
*b
)
752 struct spoolss_EnumPrintProcDataTypes r
;
753 uint16_t levels
[] = { 1 };
756 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
757 int level
= levels
[i
];
761 union spoolss_PrintProcDataTypesInfo
*info
;
763 r
.in
.servername
= "";
764 r
.in
.print_processor_name
= "winprint";
768 r
.out
.needed
= &needed
;
769 r
.out
.count
= &count
;
772 torture_comment(tctx
, "Testing EnumPrintProcDataTypes level %u\n", r
.in
.level
);
774 status
= dcerpc_spoolss_EnumPrintProcDataTypes_r(b
, tctx
, &r
);
775 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcDataType failed");
776 if (W_ERROR_IS_OK(r
.out
.result
)) {
777 /* TODO: do some more checks here */
780 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
781 "EnumPrintProcDataTypes unexpected return code");
783 blob
= data_blob_talloc(tctx
, NULL
, needed
);
784 data_blob_clear(&blob
);
786 r
.in
.offered
= needed
;
788 status
= dcerpc_spoolss_EnumPrintProcDataTypes_r(b
, tctx
, &r
);
789 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
791 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrintProcDataTypes failed");
793 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
801 static bool test_EnumPrinters(struct torture_context
*tctx
,
802 struct dcerpc_binding_handle
*b
,
803 struct test_spoolss_context
*ctx
)
805 struct spoolss_EnumPrinters r
;
807 uint16_t levels
[] = { 0, 1, 2, 4, 5 };
810 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
811 int level
= levels
[i
];
815 union spoolss_PrinterInfo
*info
;
817 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
822 r
.out
.needed
= &needed
;
823 r
.out
.count
= &count
;
826 torture_comment(tctx
, "Testing EnumPrinters level %u\n", r
.in
.level
);
828 status
= dcerpc_spoolss_EnumPrinters_r(b
, ctx
, &r
);
829 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinters failed");
830 if (W_ERROR_IS_OK(r
.out
.result
)) {
831 /* TODO: do some more checks here */
834 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
835 "EnumPrinters unexpected return code");
837 blob
= data_blob_talloc(ctx
, NULL
, needed
);
838 data_blob_clear(&blob
);
840 r
.in
.offered
= needed
;
842 status
= dcerpc_spoolss_EnumPrinters_r(b
, ctx
, &r
);
843 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinters failed");
845 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
847 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
849 ctx
->printer_count
[level
] = count
;
850 ctx
->printers
[level
] = info
;
853 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
854 int level
= levels
[i
];
855 int old_level
= levels
[i
-1];
856 torture_assert_int_equal(tctx
, ctx
->printer_count
[level
], ctx
->printer_count
[old_level
],
857 "EnumPrinters invalid value");
860 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
861 int level
= levels
[i
];
862 for (j
=0;j
<ctx
->printer_count
[level
];j
++) {
863 union spoolss_PrinterInfo
*cur
= &ctx
->printers
[level
][j
];
864 union spoolss_PrinterInfo
*ref
= &ctx
->printers
[2][j
];
867 COMPARE_STRING(tctx
, cur
->info0
, ref
->info2
, printername
);
868 COMPARE_STRING(tctx
, cur
->info0
, ref
->info2
, servername
);
869 COMPARE_UINT32(tctx
, cur
->info0
, ref
->info2
, cjobs
);
870 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
871 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
872 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
873 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
874 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
875 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
876 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
877 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
878 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
879 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
880 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
881 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
882 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
883 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
884 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
885 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
886 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
887 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
888 COMPARE_UINT32(tctx
, cur
->info0
, ref
->info2
, status
);
889 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
890 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
891 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
892 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
893 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
894 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
895 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
898 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
899 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
900 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
901 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, comment
);
904 /* level 2 is our reference, and it makes no sense to compare it to itself */
907 COMPARE_STRING(tctx
, cur
->info4
, ref
->info2
, printername
);
908 COMPARE_STRING(tctx
, cur
->info4
, ref
->info2
, servername
);
909 COMPARE_UINT32(tctx
, cur
->info4
, ref
->info2
, attributes
);
912 COMPARE_STRING(tctx
, cur
->info5
, ref
->info2
, printername
);
913 COMPARE_STRING(tctx
, cur
->info5
, ref
->info2
, portname
);
914 COMPARE_UINT32(tctx
, cur
->info5
, ref
->info2
, attributes
);
915 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
916 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
923 * - verify that the port of a printer was in the list returned by EnumPorts
929 static bool test_GetPrinterDriver2(struct torture_context
*tctx
,
930 struct dcerpc_binding_handle
*b
,
931 struct policy_handle
*handle
,
932 const char *driver_name
,
933 const char *environment
);
935 bool test_GetPrinter_level(struct torture_context
*tctx
,
936 struct dcerpc_binding_handle
*b
,
937 struct policy_handle
*handle
,
939 union spoolss_PrinterInfo
*info
)
941 struct spoolss_GetPrinter r
;
944 r
.in
.handle
= handle
;
948 r
.out
.needed
= &needed
;
950 torture_comment(tctx
, "Testing GetPrinter level %u\n", r
.in
.level
);
952 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinter_r(b
, tctx
, &r
),
953 "GetPrinter failed");
955 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
956 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
957 data_blob_clear(&blob
);
959 r
.in
.offered
= needed
;
961 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinter_r(b
, tctx
, &r
),
962 "GetPrinter failed");
965 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrinter failed");
967 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
969 if (info
&& r
.out
.info
) {
977 static bool test_GetPrinter(struct torture_context
*tctx
,
978 struct dcerpc_binding_handle
*b
,
979 struct policy_handle
*handle
,
980 const char *environment
)
982 uint32_t levels
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
985 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
987 union spoolss_PrinterInfo info
;
991 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, levels
[i
], &info
),
992 "failed to call GetPrinter");
994 if ((levels
[i
] == 2) && info
.info2
.drivername
&& strlen(info
.info2
.drivername
)) {
996 test_GetPrinterDriver2(tctx
, b
, handle
, info
.info2
.drivername
, environment
),
997 "failed to call test_GetPrinterDriver2");
1004 static bool test_SetPrinter(struct torture_context
*tctx
,
1005 struct dcerpc_binding_handle
*b
,
1006 struct policy_handle
*handle
,
1007 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
1008 struct spoolss_DevmodeContainer
*devmode_ctr
,
1009 struct sec_desc_buf
*secdesc_ctr
,
1010 enum spoolss_PrinterControl command
)
1012 struct spoolss_SetPrinter r
;
1014 r
.in
.handle
= handle
;
1015 r
.in
.info_ctr
= info_ctr
;
1016 r
.in
.devmode_ctr
= devmode_ctr
;
1017 r
.in
.secdesc_ctr
= secdesc_ctr
;
1018 r
.in
.command
= command
;
1020 torture_comment(tctx
, "Testing SetPrinter level %d\n", r
.in
.info_ctr
->level
);
1022 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
),
1023 "failed to call SetPrinter");
1024 torture_assert_werr_ok(tctx
, r
.out
.result
,
1025 "failed to call SetPrinter");
1030 static bool test_SetPrinter_errors(struct torture_context
*tctx
,
1031 struct dcerpc_binding_handle
*b
,
1032 struct policy_handle
*handle
)
1034 struct spoolss_SetPrinter r
;
1035 uint16_t levels
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1038 struct spoolss_SetPrinterInfoCtr info_ctr
;
1039 struct spoolss_DevmodeContainer devmode_ctr
;
1040 struct sec_desc_buf secdesc_ctr
;
1043 info_ctr
.info
.info0
= NULL
;
1045 ZERO_STRUCT(devmode_ctr
);
1046 ZERO_STRUCT(secdesc_ctr
);
1048 r
.in
.handle
= handle
;
1049 r
.in
.info_ctr
= &info_ctr
;
1050 r
.in
.devmode_ctr
= &devmode_ctr
;
1051 r
.in
.secdesc_ctr
= &secdesc_ctr
;
1054 torture_comment(tctx
, "Testing SetPrinter all zero\n");
1056 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
),
1057 "failed to call SetPrinter");
1058 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
1059 "failed to call SetPrinter");
1062 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
1064 struct spoolss_SetPrinterInfo0 info0
;
1065 struct spoolss_SetPrinterInfo1 info1
;
1066 struct spoolss_SetPrinterInfo2 info2
;
1067 struct spoolss_SetPrinterInfo3 info3
;
1068 struct spoolss_SetPrinterInfo4 info4
;
1069 struct spoolss_SetPrinterInfo5 info5
;
1070 struct spoolss_SetPrinterInfo6 info6
;
1071 struct spoolss_SetPrinterInfo7 info7
;
1072 struct spoolss_SetPrinterInfo8 info8
;
1073 struct spoolss_SetPrinterInfo9 info9
;
1076 info_ctr
.level
= levels
[i
];
1077 switch (levels
[i
]) {
1080 info_ctr
.info
.info0
= &info0
;
1084 info_ctr
.info
.info1
= &info1
;
1088 info_ctr
.info
.info2
= &info2
;
1092 info_ctr
.info
.info3
= &info3
;
1096 info_ctr
.info
.info4
= &info4
;
1100 info_ctr
.info
.info5
= &info5
;
1104 info_ctr
.info
.info6
= &info6
;
1108 info_ctr
.info
.info7
= &info7
;
1112 info_ctr
.info
.info8
= &info8
;
1116 info_ctr
.info
.info9
= &info9
;
1120 torture_comment(tctx
, "Testing SetPrinter level %d, command %d\n",
1121 info_ctr
.level
, r
.in
.command
);
1123 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
),
1124 "failed to call SetPrinter");
1126 switch (r
.in
.command
) {
1127 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
: /* 0 */
1128 /* is ignored for all levels other then 0 */
1129 if (info_ctr
.level
> 0) {
1133 case SPOOLSS_PRINTER_CONTROL_PAUSE
: /* 1 */
1134 case SPOOLSS_PRINTER_CONTROL_RESUME
: /* 2 */
1135 case SPOOLSS_PRINTER_CONTROL_PURGE
: /* 3 */
1136 if (info_ctr
.level
> 0) {
1137 /* is invalid for all levels other then 0 */
1138 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PRINTER_COMMAND
,
1139 "unexpected error code returned");
1142 torture_assert_werr_ok(tctx
, r
.out
.result
,
1143 "failed to call SetPrinter with non 0 command");
1148 case SPOOLSS_PRINTER_CONTROL_SET_STATUS
: /* 4 */
1149 /* FIXME: gd needs further investigation */
1151 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PRINTER_COMMAND
,
1152 "unexpected error code returned");
1156 switch (info_ctr
.level
) {
1158 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
,
1159 "unexpected error code returned");
1162 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_PRINTER_DRIVER
,
1163 "unexpected error code returned");
1169 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
1170 "unexpected error code returned");
1173 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_NOT_SUPPORTED
,
1174 "unexpected error code returned");
1177 torture_assert_werr_ok(tctx
, r
.out
.result
,
1178 "failed to call SetPrinter");
1183 if (r
.in
.command
< 5) {
1191 static void clear_info2(struct spoolss_SetPrinterInfoCtr
*r
)
1193 if ((r
->level
== 2) && (r
->info
.info2
)) {
1194 r
->info
.info2
->secdesc_ptr
= 0;
1195 r
->info
.info2
->devmode_ptr
= 0;
1199 static bool test_PrinterInfo(struct torture_context
*tctx
,
1200 struct dcerpc_binding_handle
*b
,
1201 struct policy_handle
*handle
)
1204 struct spoolss_SetPrinter s
;
1205 struct spoolss_GetPrinter q
;
1206 struct spoolss_GetPrinter q0
;
1207 struct spoolss_SetPrinterInfoCtr info_ctr
;
1208 union spoolss_PrinterInfo info
;
1209 struct spoolss_DevmodeContainer devmode_ctr
;
1210 struct sec_desc_buf secdesc_ctr
;
1215 uint32_t status_list
[] = {
1216 /* these do not stick
1217 PRINTER_STATUS_PAUSED,
1218 PRINTER_STATUS_ERROR,
1219 PRINTER_STATUS_PENDING_DELETION, */
1220 PRINTER_STATUS_PAPER_JAM
,
1221 PRINTER_STATUS_PAPER_OUT
,
1222 PRINTER_STATUS_MANUAL_FEED
,
1223 PRINTER_STATUS_PAPER_PROBLEM
,
1224 PRINTER_STATUS_OFFLINE
,
1225 PRINTER_STATUS_IO_ACTIVE
,
1226 PRINTER_STATUS_BUSY
,
1227 PRINTER_STATUS_PRINTING
,
1228 PRINTER_STATUS_OUTPUT_BIN_FULL
,
1229 PRINTER_STATUS_NOT_AVAILABLE
,
1230 PRINTER_STATUS_WAITING
,
1231 PRINTER_STATUS_PROCESSING
,
1232 PRINTER_STATUS_INITIALIZING
,
1233 PRINTER_STATUS_WARMING_UP
,
1234 PRINTER_STATUS_TONER_LOW
,
1235 PRINTER_STATUS_NO_TONER
,
1236 PRINTER_STATUS_PAGE_PUNT
,
1237 PRINTER_STATUS_USER_INTERVENTION
,
1238 PRINTER_STATUS_OUT_OF_MEMORY
,
1239 PRINTER_STATUS_DOOR_OPEN
,
1240 PRINTER_STATUS_SERVER_UNKNOWN
,
1241 PRINTER_STATUS_POWER_SAVE
,
1242 /* these do not stick
1251 uint32_t default_attribute
= PRINTER_ATTRIBUTE_LOCAL
;
1252 uint32_t attribute_list
[] = {
1253 PRINTER_ATTRIBUTE_QUEUED
,
1254 /* fails with WERR_INVALID_DATATYPE:
1255 PRINTER_ATTRIBUTE_DIRECT, */
1257 PRINTER_ATTRIBUTE_DEFAULT, */
1258 PRINTER_ATTRIBUTE_SHARED
,
1260 PRINTER_ATTRIBUTE_NETWORK, */
1261 PRINTER_ATTRIBUTE_HIDDEN
,
1262 PRINTER_ATTRIBUTE_LOCAL
,
1263 PRINTER_ATTRIBUTE_ENABLE_DEVQ
,
1264 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
,
1265 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST
,
1266 PRINTER_ATTRIBUTE_WORK_OFFLINE
,
1268 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1269 /* fails with WERR_INVALID_DATATYPE:
1270 PRINTER_ATTRIBUTE_RAW_ONLY, */
1271 /* these do not stick
1272 PRINTER_ATTRIBUTE_PUBLISHED,
1273 PRINTER_ATTRIBUTE_FAX,
1274 PRINTER_ATTRIBUTE_TS,
1293 ZERO_STRUCT(devmode_ctr
);
1294 ZERO_STRUCT(secdesc_ctr
);
1296 s
.in
.handle
= handle
;
1298 s
.in
.info_ctr
= &info_ctr
;
1299 s
.in
.devmode_ctr
= &devmode_ctr
;
1300 s
.in
.secdesc_ctr
= &secdesc_ctr
;
1302 q
.in
.handle
= handle
;
1306 #define TESTGETCALL(call, r) \
1307 r.in.buffer = NULL; \
1309 r.out.needed = &needed; \
1310 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1311 if (!NT_STATUS_IS_OK(status)) { \
1312 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1313 r.in.level, nt_errstr(status), __location__); \
1317 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1318 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1319 data_blob_clear(&blob); \
1320 r.in.buffer = &blob; \
1321 r.in.offered = needed; \
1323 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1324 if (!NT_STATUS_IS_OK(status)) { \
1325 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1326 r.in.level, nt_errstr(status), __location__); \
1330 if (!W_ERROR_IS_OK(r.out.result)) { \
1331 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1332 r.in.level, win_errstr(r.out.result), __location__); \
1338 #define TESTSETCALL_EXP(call, r, err) \
1339 clear_info2(&info_ctr);\
1340 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1341 if (!NT_STATUS_IS_OK(status)) { \
1342 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1343 r.in.info_ctr->level, nt_errstr(status), __location__); \
1347 if (!W_ERROR_IS_OK(err)) { \
1348 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1349 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1350 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1355 if (!W_ERROR_IS_OK(r.out.result)) { \
1356 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1357 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1362 #define TESTSETCALL(call, r) \
1363 TESTSETCALL_EXP(call, r, WERR_OK)
1365 #define STRING_EQUAL(s1, s2, field) \
1366 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1367 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1368 #field, s2, __location__); \
1373 #define MEM_EQUAL(s1, s2, length, field) \
1374 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1375 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1376 #field, (const char *)s2, __location__); \
1381 #define INT_EQUAL(i1, i2, field) \
1383 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1384 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1389 #define SD_EQUAL(sd1, sd2, field) \
1390 if (!security_descriptor_equal(sd1, sd2)) { \
1391 torture_comment(tctx, "Failed to set %s (%s)\n", \
1392 #field, __location__); \
1397 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1398 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1399 q.in.level = lvl1; \
1400 TESTGETCALL(GetPrinter, q) \
1401 info_ctr.level = lvl1; \
1402 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1403 info_ctr.info.info ## lvl1->field1 = value;\
1404 TESTSETCALL_EXP(SetPrinter, s, err) \
1405 info_ctr.info.info ## lvl1->field1 = ""; \
1406 TESTGETCALL(GetPrinter, q) \
1407 info_ctr.info.info ## lvl1->field1 = value; \
1408 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1409 q.in.level = lvl2; \
1410 TESTGETCALL(GetPrinter, q) \
1411 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1412 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1415 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1416 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1419 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1420 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1421 q.in.level = lvl1; \
1422 TESTGETCALL(GetPrinter, q) \
1423 info_ctr.level = lvl1; \
1424 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1425 info_ctr.info.info ## lvl1->field1 = value; \
1426 TESTSETCALL(SetPrinter, s) \
1427 info_ctr.info.info ## lvl1->field1 = 0; \
1428 TESTGETCALL(GetPrinter, q) \
1429 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1430 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1431 q.in.level = lvl2; \
1432 TESTGETCALL(GetPrinter, q) \
1433 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1434 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1437 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1438 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1442 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1444 TEST_PRINTERINFO_STRING(2, comment
, 1, comment
, "xx2-1 comment");
1445 TEST_PRINTERINFO_STRING(2, comment
, 2, comment
, "xx2-2 comment");
1447 /* level 0 printername does not stick */
1448 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1449 TEST_PRINTERINFO_STRING(2, printername
, 1, name
, "xx2-1 printer");
1450 TEST_PRINTERINFO_STRING(2, printername
, 2, printername
, "xx2-2 printer");
1451 TEST_PRINTERINFO_STRING(2, printername
, 4, printername
, "xx2-4 printer");
1452 TEST_PRINTERINFO_STRING(2, printername
, 5, printername
, "xx2-5 printer");
1453 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1454 TEST_PRINTERINFO_STRING(4, printername
, 1, name
, "xx4-1 printer");
1455 TEST_PRINTERINFO_STRING(4, printername
, 2, printername
, "xx4-2 printer");
1456 TEST_PRINTERINFO_STRING(4, printername
, 4, printername
, "xx4-4 printer");
1457 TEST_PRINTERINFO_STRING(4, printername
, 5, printername
, "xx4-5 printer");
1458 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1459 TEST_PRINTERINFO_STRING(5, printername
, 1, name
, "xx5-1 printer");
1460 TEST_PRINTERINFO_STRING(5, printername
, 2, printername
, "xx5-2 printer");
1461 TEST_PRINTERINFO_STRING(5, printername
, 4, printername
, "xx5-4 printer");
1462 TEST_PRINTERINFO_STRING(5, printername
, 5, printername
, "xx5-5 printer");
1464 /* servername can be set but does not stick
1465 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1466 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1467 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1470 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1471 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname
, 2, portname
, "xx2-2 portname", WERR_UNKNOWN_PORT
);
1472 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname
, 5, portname
, "xx2-5 portname", WERR_UNKNOWN_PORT
);
1473 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname
, 2, portname
, "xx5-2 portname", WERR_UNKNOWN_PORT
);
1474 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname
, 5, portname
, "xx5-5 portname", WERR_UNKNOWN_PORT
);
1476 TEST_PRINTERINFO_STRING(2, sharename
, 2, sharename
, "xx2-2 sharename");
1477 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1478 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername
, 2, drivername
, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER
);
1479 TEST_PRINTERINFO_STRING(2, location
, 2, location
, "xx2-2 location");
1480 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1481 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile
, 2, sepfile
, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE
);
1482 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1483 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor
, 2, printprocessor
, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR
);
1484 TEST_PRINTERINFO_STRING(2, datatype
, 2, datatype
, "xx2-2 datatype");
1485 TEST_PRINTERINFO_STRING(2, parameters
, 2, parameters
, "xx2-2 parameters");
1487 for (i
=0; i
< ARRAY_SIZE(attribute_list
); i
++) {
1488 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1490 (attribute_list[i] | default_attribute)
1492 TEST_PRINTERINFO_INT_EXP(2, attributes
, 2, attributes
,
1494 (attribute_list
[i
] | default_attribute
)
1496 TEST_PRINTERINFO_INT_EXP(2, attributes
, 4, attributes
,
1498 (attribute_list
[i
] | default_attribute
)
1500 TEST_PRINTERINFO_INT_EXP(2, attributes
, 5, attributes
,
1502 (attribute_list
[i
] | default_attribute
)
1504 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1506 (attribute_list[i] | default_attribute)
1508 TEST_PRINTERINFO_INT_EXP(4, attributes
, 2, attributes
,
1510 (attribute_list
[i
] | default_attribute
)
1512 TEST_PRINTERINFO_INT_EXP(4, attributes
, 4, attributes
,
1514 (attribute_list
[i
] | default_attribute
)
1516 TEST_PRINTERINFO_INT_EXP(4, attributes
, 5, attributes
,
1518 (attribute_list
[i
] | default_attribute
)
1520 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1522 (attribute_list[i] | default_attribute)
1524 TEST_PRINTERINFO_INT_EXP(5, attributes
, 2, attributes
,
1526 (attribute_list
[i
] | default_attribute
)
1528 TEST_PRINTERINFO_INT_EXP(5, attributes
, 4, attributes
,
1530 (attribute_list
[i
] | default_attribute
)
1532 TEST_PRINTERINFO_INT_EXP(5, attributes
, 5, attributes
,
1534 (attribute_list
[i
] | default_attribute
)
1538 for (i
=0; i
< ARRAY_SIZE(status_list
); i
++) {
1539 /* level 2 sets do not stick
1540 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1541 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1542 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1543 TEST_PRINTERINFO_INT(6, status
, 0, status
, status_list
[i
]);
1544 TEST_PRINTERINFO_INT(6, status
, 2, status
, status_list
[i
]);
1545 TEST_PRINTERINFO_INT(6, status
, 6, status
, status_list
[i
]);
1548 /* priorities need to be between 0 and 99
1549 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1550 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 0);
1551 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 1);
1552 TEST_PRINTERINFO_INT(2, priority
, 2, priority
, 99);
1553 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1554 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 0);
1555 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 1);
1556 TEST_PRINTERINFO_INT(2, defaultpriority
,2, defaultpriority
, 99);
1557 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1559 TEST_PRINTERINFO_INT(2, starttime
, 2, starttime
, __LINE__
);
1560 TEST_PRINTERINFO_INT(2, untiltime
, 2, untiltime
, __LINE__
);
1563 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1564 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1567 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1568 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1570 /* FIXME: gd also test devmode and secdesc behavior */
1573 /* verify composition of level 1 description field */
1574 const char *description
;
1578 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1580 description
= talloc_strdup(tctx
, q0
.out
.info
->info1
.description
);
1583 do { TESTGETCALL(GetPrinter
, q0
) } while (0);
1585 tmp
= talloc_asprintf(tctx
, "%s,%s,%s",
1586 q0
.out
.info
->info2
.printername
,
1587 q0
.out
.info
->info2
.drivername
,
1588 q0
.out
.info
->info2
.location
);
1590 do { STRING_EQUAL(description
, tmp
, "description")} while (0);
1596 #define torture_assert_sid_equal(torture_ctx,got,expected,cmt)\
1597 do { struct dom_sid *__got = (got), *__expected = (expected); \
1598 if (!dom_sid_equal(__got, __expected)) { \
1599 torture_result(torture_ctx, TORTURE_FAIL, \
1600 __location__": "#got" was %s, expected %s: %s", \
1601 dom_sid_string(torture_ctx, __got), dom_sid_string(torture_ctx, __expected), cmt); \
1606 static bool test_security_descriptor_equal(struct torture_context
*tctx
,
1607 const struct security_descriptor
*sd1
,
1608 const struct security_descriptor
*sd2
)
1615 torture_comment(tctx
, "%s\n", __location__
);
1619 torture_assert_int_equal(tctx
, sd1
->revision
, sd2
->revision
, "revision mismatch");
1620 torture_assert_int_equal(tctx
, sd1
->type
, sd2
->type
, "type mismatch");
1622 torture_assert_sid_equal(tctx
, sd1
->owner_sid
, sd2
->owner_sid
, "owner mismatch");
1623 torture_assert_sid_equal(tctx
, sd1
->group_sid
, sd2
->group_sid
, "group mismatch");
1625 if (!security_acl_equal(sd1
->sacl
, sd2
->sacl
)) {
1626 torture_comment(tctx
, "%s: sacl mismatch\n", __location__
);
1627 NDR_PRINT_DEBUG(security_acl
, sd1
->sacl
);
1628 NDR_PRINT_DEBUG(security_acl
, sd2
->sacl
);
1631 if (!security_acl_equal(sd1
->dacl
, sd2
->dacl
)) {
1632 torture_comment(tctx
, "%s: dacl mismatch\n", __location__
);
1633 NDR_PRINT_DEBUG(security_acl
, sd1
->dacl
);
1634 NDR_PRINT_DEBUG(security_acl
, sd2
->dacl
);
1641 static bool test_sd_set_level(struct torture_context
*tctx
,
1642 struct dcerpc_binding_handle
*b
,
1643 struct policy_handle
*handle
,
1645 struct security_descriptor
*sd
)
1647 struct spoolss_SetPrinterInfoCtr info_ctr
;
1648 struct spoolss_DevmodeContainer devmode_ctr
;
1649 struct sec_desc_buf secdesc_ctr
;
1650 union spoolss_SetPrinterInfo sinfo
;
1652 ZERO_STRUCT(devmode_ctr
);
1653 ZERO_STRUCT(secdesc_ctr
);
1657 union spoolss_PrinterInfo info
;
1658 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
1659 torture_assert(tctx
, PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
1662 info_ctr
.info
= sinfo
;
1667 struct spoolss_SetPrinterInfo3 info3
;
1669 info3
.sec_desc_ptr
= 0;
1672 info_ctr
.info
.info3
= &info3
;
1680 secdesc_ctr
.sd
= sd
;
1682 torture_assert(tctx
,
1683 test_SetPrinter(tctx
, b
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0), "");
1688 static bool test_PrinterInfo_SDs(struct torture_context
*tctx
,
1689 struct dcerpc_binding_handle
*b
,
1690 struct policy_handle
*handle
)
1692 union spoolss_PrinterInfo info
;
1693 struct security_descriptor
*sd1
, *sd2
;
1696 /* just compare level 2 and level 3 */
1698 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
1700 sd1
= info
.info2
.secdesc
;
1702 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 3, &info
), "");
1704 sd2
= info
.info3
.secdesc
;
1706 torture_assert(tctx
, test_security_descriptor_equal(tctx
, sd1
, sd2
),
1707 "SD level 2 != SD level 3");
1710 /* query level 2, set level 2, query level 2 */
1712 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
1714 sd1
= info
.info2
.secdesc
;
1716 torture_assert(tctx
, test_sd_set_level(tctx
, b
, handle
, 2, sd1
), "");
1718 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
1720 sd2
= info
.info2
.secdesc
;
1721 if (sd1
->type
& SEC_DESC_DACL_DEFAULTED
) {
1722 torture_comment(tctx
, "removing SEC_DESC_DACL_DEFAULTED\n");
1723 sd1
->type
&= ~SEC_DESC_DACL_DEFAULTED
;
1726 torture_assert(tctx
, test_security_descriptor_equal(tctx
, sd1
, sd2
),
1727 "SD level 2 != SD level 2 after SD has been set via level 2");
1730 /* query level 2, set level 3, query level 2 */
1732 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
1734 sd1
= info
.info2
.secdesc
;
1736 torture_assert(tctx
, test_sd_set_level(tctx
, b
, handle
, 3, sd1
), "");
1738 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
1740 sd2
= info
.info2
.secdesc
;
1742 torture_assert(tctx
, test_security_descriptor_equal(tctx
, sd1
, sd2
),
1743 "SD level 2 != SD level 2 after SD has been set via level 3");
1745 /* set modified sd level 3, query level 2 */
1747 for (i
=0; i
< 93; i
++) {
1748 struct security_ace a
;
1749 const char *sid_string
= talloc_asprintf(tctx
, "S-1-5-32-9999%i", i
);
1750 a
.type
= SEC_ACE_TYPE_ACCESS_ALLOWED
;
1752 a
.size
= 0; /* autogenerated */
1754 a
.trustee
= *dom_sid_parse_talloc(tctx
, sid_string
);
1755 torture_assert_ntstatus_ok(tctx
, security_descriptor_dacl_add(sd1
, &a
), "");
1758 torture_assert(tctx
, test_sd_set_level(tctx
, b
, handle
, 3, sd1
), "");
1760 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
1761 sd2
= info
.info2
.secdesc
;
1763 if (sd1
->type
& SEC_DESC_DACL_DEFAULTED
) {
1764 torture_comment(tctx
, "removing SEC_DESC_DACL_DEFAULTED\n");
1765 sd1
->type
&= ~SEC_DESC_DACL_DEFAULTED
;
1768 torture_assert(tctx
, test_security_descriptor_equal(tctx
, sd1
, sd2
),
1769 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1776 * wrapper call that saves original sd, runs tests, and restores sd
1779 static bool test_PrinterInfo_SD(struct torture_context
*tctx
,
1780 struct dcerpc_binding_handle
*b
,
1781 struct policy_handle
*handle
)
1783 union spoolss_PrinterInfo info
;
1784 struct security_descriptor
*sd
;
1787 torture_comment(tctx
, "Testing Printer Security Descriptors\n");
1789 /* save original sd */
1791 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
1792 "failed to get initial security descriptor");
1794 sd
= security_descriptor_copy(tctx
, info
.info2
.secdesc
);
1798 ret
= test_PrinterInfo_SDs(tctx
, b
, handle
);
1800 /* restore original sd */
1802 torture_assert(tctx
, test_sd_set_level(tctx
, b
, handle
, 3, sd
),
1803 "failed to restore initial security descriptor");
1805 torture_comment(tctx
, "Printer Security Descriptors test %s\n\n",
1806 ret
? "succeeded" : "failed");
1812 static bool test_devmode_set_level(struct torture_context
*tctx
,
1813 struct dcerpc_binding_handle
*b
,
1814 struct policy_handle
*handle
,
1816 struct spoolss_DeviceMode
*devmode
)
1818 struct spoolss_SetPrinterInfoCtr info_ctr
;
1819 struct spoolss_DevmodeContainer devmode_ctr
;
1820 struct sec_desc_buf secdesc_ctr
;
1821 union spoolss_SetPrinterInfo sinfo
;
1823 ZERO_STRUCT(devmode_ctr
);
1824 ZERO_STRUCT(secdesc_ctr
);
1828 union spoolss_PrinterInfo info
;
1829 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
1830 torture_assert(tctx
, PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
1833 info_ctr
.info
= sinfo
;
1838 struct spoolss_SetPrinterInfo8 info8
;
1840 info8
.devmode_ptr
= 0;
1843 info_ctr
.info
.info8
= &info8
;
1851 devmode_ctr
.devmode
= devmode
;
1853 torture_assert(tctx
,
1854 test_SetPrinter(tctx
, b
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0), "");
1860 static bool test_devicemode_equal(struct torture_context
*tctx
,
1861 const struct spoolss_DeviceMode
*d1
,
1862 const struct spoolss_DeviceMode
*d2
)
1869 torture_comment(tctx
, "%s\n", __location__
);
1872 torture_assert_str_equal(tctx
, d1
->devicename
, d2
->devicename
, "devicename mismatch");
1873 torture_assert_int_equal(tctx
, d1
->specversion
, d2
->specversion
, "specversion mismatch");
1874 torture_assert_int_equal(tctx
, d1
->driverversion
, d2
->driverversion
, "driverversion mismatch");
1875 torture_assert_int_equal(tctx
, d1
->size
, d2
->size
, "size mismatch");
1876 torture_assert_int_equal(tctx
, d1
->__driverextra_length
, d2
->__driverextra_length
, "__driverextra_length mismatch");
1877 torture_assert_int_equal(tctx
, d1
->fields
, d2
->fields
, "fields mismatch");
1878 torture_assert_int_equal(tctx
, d1
->orientation
, d2
->orientation
, "orientation mismatch");
1879 torture_assert_int_equal(tctx
, d1
->papersize
, d2
->papersize
, "papersize mismatch");
1880 torture_assert_int_equal(tctx
, d1
->paperlength
, d2
->paperlength
, "paperlength mismatch");
1881 torture_assert_int_equal(tctx
, d1
->paperwidth
, d2
->paperwidth
, "paperwidth mismatch");
1882 torture_assert_int_equal(tctx
, d1
->scale
, d2
->scale
, "scale mismatch");
1883 torture_assert_int_equal(tctx
, d1
->copies
, d2
->copies
, "copies mismatch");
1884 torture_assert_int_equal(tctx
, d1
->defaultsource
, d2
->defaultsource
, "defaultsource mismatch");
1885 torture_assert_int_equal(tctx
, d1
->printquality
, d2
->printquality
, "printquality mismatch");
1886 torture_assert_int_equal(tctx
, d1
->color
, d2
->color
, "color mismatch");
1887 torture_assert_int_equal(tctx
, d1
->duplex
, d2
->duplex
, "duplex mismatch");
1888 torture_assert_int_equal(tctx
, d1
->yresolution
, d2
->yresolution
, "yresolution mismatch");
1889 torture_assert_int_equal(tctx
, d1
->ttoption
, d2
->ttoption
, "ttoption mismatch");
1890 torture_assert_int_equal(tctx
, d1
->collate
, d2
->collate
, "collate mismatch");
1891 torture_assert_str_equal(tctx
, d1
->formname
, d2
->formname
, "formname mismatch");
1892 torture_assert_int_equal(tctx
, d1
->logpixels
, d2
->logpixels
, "logpixels mismatch");
1893 torture_assert_int_equal(tctx
, d1
->bitsperpel
, d2
->bitsperpel
, "bitsperpel mismatch");
1894 torture_assert_int_equal(tctx
, d1
->pelswidth
, d2
->pelswidth
, "pelswidth mismatch");
1895 torture_assert_int_equal(tctx
, d1
->pelsheight
, d2
->pelsheight
, "pelsheight mismatch");
1896 torture_assert_int_equal(tctx
, d1
->displayflags
, d2
->displayflags
, "displayflags mismatch");
1897 torture_assert_int_equal(tctx
, d1
->displayfrequency
, d2
->displayfrequency
, "displayfrequency mismatch");
1898 torture_assert_int_equal(tctx
, d1
->icmmethod
, d2
->icmmethod
, "icmmethod mismatch");
1899 torture_assert_int_equal(tctx
, d1
->icmintent
, d2
->icmintent
, "icmintent mismatch");
1900 torture_assert_int_equal(tctx
, d1
->mediatype
, d2
->mediatype
, "mediatype mismatch");
1901 torture_assert_int_equal(tctx
, d1
->dithertype
, d2
->dithertype
, "dithertype mismatch");
1902 torture_assert_int_equal(tctx
, d1
->reserved1
, d2
->reserved1
, "reserved1 mismatch");
1903 torture_assert_int_equal(tctx
, d1
->reserved2
, d2
->reserved2
, "reserved2 mismatch");
1904 torture_assert_int_equal(tctx
, d1
->panningwidth
, d2
->panningwidth
, "panningwidth mismatch");
1905 torture_assert_int_equal(tctx
, d1
->panningheight
, d2
->panningheight
, "panningheight mismatch");
1906 torture_assert_data_blob_equal(tctx
, d1
->driverextra_data
, d2
->driverextra_data
, "driverextra_data mismatch");
1911 static bool test_devicemode_full(struct torture_context
*tctx
,
1912 struct dcerpc_binding_handle
*b
,
1913 struct policy_handle
*handle
)
1915 struct spoolss_SetPrinter s
;
1916 struct spoolss_GetPrinter q
;
1917 struct spoolss_GetPrinter q0
;
1918 struct spoolss_SetPrinterInfoCtr info_ctr
;
1919 struct spoolss_SetPrinterInfo8 info8
;
1920 union spoolss_PrinterInfo info
;
1921 struct spoolss_DevmodeContainer devmode_ctr
;
1922 struct sec_desc_buf secdesc_ctr
;
1927 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1928 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1929 q.in.level = lvl1; \
1930 TESTGETCALL(GetPrinter, q) \
1931 info_ctr.level = lvl1; \
1933 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1934 } else if (lvl1 == 8) {\
1935 info_ctr.info.info ## lvl1 = &info8; \
1937 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
1938 devmode_ctr.devmode->field1 = value; \
1939 TESTSETCALL(SetPrinter, s) \
1940 TESTGETCALL(GetPrinter, q) \
1941 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
1942 q.in.level = lvl2; \
1943 TESTGETCALL(GetPrinter, q) \
1944 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
1947 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
1948 TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1951 ZERO_STRUCT(devmode_ctr
);
1952 ZERO_STRUCT(secdesc_ctr
);
1955 s
.in
.handle
= handle
;
1957 s
.in
.info_ctr
= &info_ctr
;
1958 s
.in
.devmode_ctr
= &devmode_ctr
;
1959 s
.in
.secdesc_ctr
= &secdesc_ctr
;
1961 q
.in
.handle
= handle
;
1966 const char *devicename
;/* [charset(UTF16)] */
1967 enum spoolss_DeviceModeSpecVersion specversion
;
1968 uint16_t driverversion
;
1970 uint16_t __driverextra_length
;/* [value(r->driverextra_data.length)] */
1974 TEST_DEVMODE_INT(8, orientation
, 8, orientation
, __LINE__
);
1975 TEST_DEVMODE_INT(8, papersize
, 8, papersize
, __LINE__
);
1976 TEST_DEVMODE_INT(8, paperlength
, 8, paperlength
, __LINE__
);
1977 TEST_DEVMODE_INT(8, paperwidth
, 8, paperwidth
, __LINE__
);
1978 TEST_DEVMODE_INT(8, scale
, 8, scale
, __LINE__
);
1979 TEST_DEVMODE_INT(8, copies
, 8, copies
, __LINE__
);
1980 TEST_DEVMODE_INT(8, defaultsource
, 8, defaultsource
, __LINE__
);
1981 TEST_DEVMODE_INT(8, printquality
, 8, printquality
, __LINE__
);
1982 TEST_DEVMODE_INT(8, color
, 8, color
, __LINE__
);
1983 TEST_DEVMODE_INT(8, duplex
, 8, duplex
, __LINE__
);
1984 TEST_DEVMODE_INT(8, yresolution
, 8, yresolution
, __LINE__
);
1985 TEST_DEVMODE_INT(8, ttoption
, 8, ttoption
, __LINE__
);
1986 TEST_DEVMODE_INT(8, collate
, 8, collate
, __LINE__
);
1988 const char *formname
;/* [charset(UTF16)] */
1990 TEST_DEVMODE_INT(8, logpixels
, 8, logpixels
, __LINE__
);
1991 TEST_DEVMODE_INT(8, bitsperpel
, 8, bitsperpel
, __LINE__
);
1992 TEST_DEVMODE_INT(8, pelswidth
, 8, pelswidth
, __LINE__
);
1993 TEST_DEVMODE_INT(8, pelsheight
, 8, pelsheight
, __LINE__
);
1994 TEST_DEVMODE_INT(8, displayflags
, 8, displayflags
, __LINE__
);
1995 TEST_DEVMODE_INT(8, displayfrequency
, 8, displayfrequency
, __LINE__
);
1996 TEST_DEVMODE_INT(8, icmmethod
, 8, icmmethod
, __LINE__
);
1997 TEST_DEVMODE_INT(8, icmintent
, 8, icmintent
, __LINE__
);
1998 TEST_DEVMODE_INT(8, mediatype
, 8, mediatype
, __LINE__
);
1999 TEST_DEVMODE_INT(8, dithertype
, 8, dithertype
, __LINE__
);
2000 TEST_DEVMODE_INT(8, reserved1
, 8, reserved1
, __LINE__
);
2001 TEST_DEVMODE_INT(8, reserved2
, 8, reserved2
, __LINE__
);
2002 TEST_DEVMODE_INT(8, panningwidth
, 8, panningwidth
, __LINE__
);
2003 TEST_DEVMODE_INT(8, panningheight
, 8, panningheight
, __LINE__
);
2008 static bool call_OpenPrinterEx(struct torture_context
*tctx
,
2009 struct dcerpc_pipe
*p
,
2011 struct spoolss_DeviceMode
*devmode
,
2012 struct policy_handle
*handle
);
2014 static bool test_ClosePrinter(struct torture_context
*tctx
,
2015 struct dcerpc_binding_handle
*b
,
2016 struct policy_handle
*handle
);
2018 static bool test_PrinterInfo_DevModes(struct torture_context
*tctx
,
2019 struct dcerpc_pipe
*p
,
2020 struct policy_handle
*handle
,
2023 union spoolss_PrinterInfo info
;
2024 struct spoolss_DeviceMode
*devmode
;
2025 struct spoolss_DeviceMode
*devmode2
;
2026 struct policy_handle handle_devmode
;
2027 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
2029 /* simply compare level8 and level2 devmode */
2031 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 8, &info
), "");
2033 devmode
= info
.info8
.devmode
;
2035 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
2037 devmode2
= info
.info2
.devmode
;
2039 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2040 "DM level 8 != DM level 2");
2043 /* set devicemode level 8 and see if it persists */
2045 devmode
->copies
= 93;
2046 devmode
->formname
= talloc_strdup(tctx
, "Legal");
2048 torture_assert(tctx
, test_devmode_set_level(tctx
, b
, handle
, 8, devmode
), "");
2050 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 8, &info
), "");
2052 devmode2
= info
.info8
.devmode
;
2054 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2055 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2057 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
2059 devmode2
= info
.info2
.devmode
;
2061 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2062 "modified DM level 8 != DM level 2");
2065 /* set devicemode level 2 and see if it persists */
2067 devmode
->copies
= 39;
2068 devmode
->formname
= talloc_strdup(tctx
, "Executive");
2070 torture_assert(tctx
, test_devmode_set_level(tctx
, b
, handle
, 2, devmode
), "");
2072 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 8, &info
), "");
2074 devmode2
= info
.info8
.devmode
;
2076 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2077 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2079 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
), "");
2081 devmode2
= info
.info2
.devmode
;
2083 torture_assert(tctx
, test_devicemode_equal(tctx
, devmode
, devmode2
),
2084 "modified DM level 8 != DM level 2");
2087 /* check every single bit in public part of devicemode */
2089 torture_assert(tctx
, test_devicemode_full(tctx
, b
, handle
),
2090 "failed to set every single devicemode component");
2093 /* change formname upon open and see if it persists in getprinter calls */
2095 devmode
->formname
= talloc_strdup(tctx
, "A4");
2096 devmode
->copies
= 42;
2098 torture_assert(tctx
, call_OpenPrinterEx(tctx
, p
, name
, devmode
, &handle_devmode
),
2099 "failed to open printer handle");
2101 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, &handle_devmode
, 8, &info
), "");
2103 devmode2
= info
.info8
.devmode
;
2105 if (strequal(devmode
->devicename
, devmode2
->devicename
)) {
2106 torture_warning(tctx
, "devicenames are the same\n");
2108 torture_comment(tctx
, "devicename passed in for open: %s\n", devmode
->devicename
);
2109 torture_comment(tctx
, "devicename after level 8 get: %s\n", devmode2
->devicename
);
2112 if (strequal(devmode
->formname
, devmode2
->formname
)) {
2113 torture_warning(tctx
, "formname are the same\n");
2115 torture_comment(tctx
, "formname passed in for open: %s\n", devmode
->formname
);
2116 torture_comment(tctx
, "formname after level 8 get: %s\n", devmode2
->formname
);
2119 if (devmode
->copies
== devmode2
->copies
) {
2120 torture_warning(tctx
, "copies are the same\n");
2122 torture_comment(tctx
, "copies passed in for open: %d\n", devmode
->copies
);
2123 torture_comment(tctx
, "copies after level 8 get: %d\n", devmode2
->copies
);
2126 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, &handle_devmode
, 2, &info
), "");
2128 devmode2
= info
.info2
.devmode
;
2130 if (strequal(devmode
->devicename
, devmode2
->devicename
)) {
2131 torture_warning(tctx
, "devicenames are the same\n");
2133 torture_comment(tctx
, "devicename passed in for open: %s\n", devmode
->devicename
);
2134 torture_comment(tctx
, "devicename after level 2 get: %s\n", devmode2
->devicename
);
2137 if (strequal(devmode
->formname
, devmode2
->formname
)) {
2138 torture_warning(tctx
, "formname is the same\n");
2140 torture_comment(tctx
, "formname passed in for open: %s\n", devmode
->formname
);
2141 torture_comment(tctx
, "formname after level 2 get: %s\n", devmode2
->formname
);
2144 if (devmode
->copies
== devmode2
->copies
) {
2145 torture_warning(tctx
, "copies are the same\n");
2147 torture_comment(tctx
, "copies passed in for open: %d\n", devmode
->copies
);
2148 torture_comment(tctx
, "copies after level 2 get: %d\n", devmode2
->copies
);
2151 test_ClosePrinter(tctx
, b
, &handle_devmode
);
2157 * wrapper call that saves original devmode, runs tests, and restores devmode
2160 static bool test_PrinterInfo_DevMode(struct torture_context
*tctx
,
2161 struct dcerpc_pipe
*p
,
2162 struct policy_handle
*handle
,
2165 union spoolss_PrinterInfo info
;
2166 struct spoolss_DeviceMode
*devmode
;
2168 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
2170 torture_comment(tctx
, "Testing Printer Devicemodes\n");
2172 /* save original devmode */
2174 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 8, &info
),
2175 "failed to get initial global devicemode");
2177 devmode
= info
.info8
.devmode
;
2181 ret
= test_PrinterInfo_DevModes(tctx
, p
, handle
, name
);
2183 /* restore original devmode */
2185 torture_assert(tctx
, test_devmode_set_level(tctx
, b
, handle
, 8, devmode
),
2186 "failed to restore initial global device mode");
2188 torture_comment(tctx
, "Printer Devicemodes test %s\n\n",
2189 ret
? "succeeded" : "failed");
2195 static bool test_ClosePrinter(struct torture_context
*tctx
,
2196 struct dcerpc_binding_handle
*b
,
2197 struct policy_handle
*handle
)
2200 struct spoolss_ClosePrinter r
;
2202 r
.in
.handle
= handle
;
2203 r
.out
.handle
= handle
;
2205 torture_comment(tctx
, "Testing ClosePrinter\n");
2207 status
= dcerpc_spoolss_ClosePrinter_r(b
, tctx
, &r
);
2208 torture_assert_ntstatus_ok(tctx
, status
, "ClosePrinter failed");
2209 torture_assert_werr_ok(tctx
, r
.out
.result
, "ClosePrinter failed");
2214 static bool test_GetForm_args(struct torture_context
*tctx
,
2215 struct dcerpc_binding_handle
*b
,
2216 struct policy_handle
*handle
,
2217 const char *form_name
,
2219 union spoolss_FormInfo
*info_p
)
2222 struct spoolss_GetForm r
;
2225 r
.in
.handle
= handle
;
2226 r
.in
.form_name
= form_name
;
2230 r
.out
.needed
= &needed
;
2232 torture_comment(tctx
, "Testing GetForm(%s) level %d\n", form_name
, r
.in
.level
);
2234 status
= dcerpc_spoolss_GetForm_r(b
, tctx
, &r
);
2235 torture_assert_ntstatus_ok(tctx
, status
, "GetForm failed");
2237 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2238 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2239 data_blob_clear(&blob
);
2240 r
.in
.buffer
= &blob
;
2241 r
.in
.offered
= needed
;
2242 status
= dcerpc_spoolss_GetForm_r(b
, tctx
, &r
);
2243 torture_assert_ntstatus_ok(tctx
, status
, "GetForm failed");
2245 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetForm failed");
2247 torture_assert(tctx
, r
.out
.info
, "No form info returned");
2250 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetForm failed");
2252 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
2255 *info_p
= *r
.out
.info
;
2261 static bool test_GetForm(struct torture_context
*tctx
,
2262 struct dcerpc_binding_handle
*b
,
2263 struct policy_handle
*handle
,
2264 const char *form_name
,
2267 return test_GetForm_args(tctx
, b
, handle
, form_name
, level
, NULL
);
2270 static bool test_EnumForms(struct torture_context
*tctx
,
2271 struct dcerpc_binding_handle
*b
,
2272 struct policy_handle
*handle
,
2276 union spoolss_FormInfo
**info_p
)
2278 struct spoolss_EnumForms r
;
2281 union spoolss_FormInfo
*info
;
2283 r
.in
.handle
= handle
;
2287 r
.out
.needed
= &needed
;
2288 r
.out
.count
= &count
;
2291 torture_comment(tctx
, "Testing EnumForms level %d\n", r
.in
.level
);
2293 torture_assert_ntstatus_ok(tctx
,
2294 dcerpc_spoolss_EnumForms_r(b
, tctx
, &r
),
2295 "EnumForms failed");
2297 if ((r
.in
.level
== 2) && (W_ERROR_EQUAL(r
.out
.result
, WERR_UNKNOWN_LEVEL
))) {
2298 torture_skip(tctx
, "EnumForms level 2 not supported");
2301 if (print_server
&& W_ERROR_EQUAL(r
.out
.result
, WERR_BADFID
)) {
2302 torture_fail(tctx
, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2305 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2306 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2307 data_blob_clear(&blob
);
2308 r
.in
.buffer
= &blob
;
2309 r
.in
.offered
= needed
;
2311 torture_assert_ntstatus_ok(tctx
,
2312 dcerpc_spoolss_EnumForms_r(b
, tctx
, &r
),
2313 "EnumForms failed");
2315 torture_assert(tctx
, info
, "No forms returned");
2318 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumForms failed");
2320 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
2332 static bool test_EnumForms_all(struct torture_context
*tctx
,
2333 struct dcerpc_binding_handle
*b
,
2334 struct policy_handle
*handle
,
2337 uint32_t levels
[] = { 1, 2 };
2340 for (i
=0; i
<ARRAY_SIZE(levels
); i
++) {
2343 union spoolss_FormInfo
*info
= NULL
;
2345 torture_assert(tctx
,
2346 test_EnumForms(tctx
, b
, handle
, print_server
, levels
[i
], &count
, &info
),
2347 "failed to enum forms");
2349 for (j
= 0; j
< count
; j
++) {
2350 if (!print_server
) {
2351 torture_assert(tctx
,
2352 test_GetForm(tctx
, b
, handle
, info
[j
].info1
.form_name
, levels
[i
]),
2353 "failed to get form");
2361 static bool test_EnumForms_find_one(struct torture_context
*tctx
,
2362 struct dcerpc_binding_handle
*b
,
2363 struct policy_handle
*handle
,
2365 const char *form_name
)
2367 union spoolss_FormInfo
*info
;
2372 torture_assert(tctx
,
2373 test_EnumForms(tctx
, b
, handle
, print_server
, 1, &count
, &info
),
2374 "failed to enumerate forms");
2376 for (i
=0; i
<count
; i
++) {
2377 if (strequal(form_name
, info
[i
].info1
.form_name
)) {
2386 static bool test_DeleteForm(struct torture_context
*tctx
,
2387 struct dcerpc_binding_handle
*b
,
2388 struct policy_handle
*handle
,
2389 const char *form_name
)
2391 struct spoolss_DeleteForm r
;
2393 r
.in
.handle
= handle
;
2394 r
.in
.form_name
= form_name
;
2396 torture_comment(tctx
, "Testing DeleteForm(%s)\n", form_name
);
2398 torture_assert_ntstatus_ok(tctx
,
2399 dcerpc_spoolss_DeleteForm_r(b
, tctx
, &r
),
2400 "DeleteForm failed");
2401 torture_assert_werr_ok(tctx
, r
.out
.result
,
2402 "DeleteForm failed");
2403 torture_assert_ntstatus_ok(tctx
,
2404 dcerpc_spoolss_DeleteForm_r(b
, tctx
, &r
),
2405 "2nd DeleteForm failed");
2406 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_FORM_NAME
,
2407 "2nd DeleteForm failed");
2412 static bool test_AddForm(struct torture_context
*tctx
,
2413 struct dcerpc_binding_handle
*b
,
2414 struct policy_handle
*handle
,
2416 union spoolss_AddFormInfo
*info
)
2418 struct spoolss_AddForm r
;
2421 torture_skip(tctx
, "only level 1 supported");
2424 r
.in
.handle
= handle
;
2428 torture_comment(tctx
, "Testing AddForm(%s) level %d\n",
2429 r
.in
.info
.info1
->form_name
, r
.in
.level
);
2431 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_AddForm_r(b
, tctx
, &r
),
2433 if (W_ERROR_EQUAL(r
.out
.result
, WERR_FILE_EXISTS
)) {
2434 test_DeleteForm(tctx
, b
, handle
, r
.in
.info
.info1
->form_name
);
2435 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_AddForm_r(b
, tctx
, &r
),
2439 torture_assert_werr_ok(tctx
, r
.out
.result
,
2442 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_AddForm_r(b
, tctx
, &r
),
2443 "2nd AddForm failed");
2444 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_FILE_EXISTS
,
2445 "2nd AddForm gave unexpected result");
2450 static bool test_SetForm(struct torture_context
*tctx
,
2451 struct dcerpc_binding_handle
*b
,
2452 struct policy_handle
*handle
,
2453 const char *form_name
,
2455 union spoolss_AddFormInfo
*info
)
2457 struct spoolss_SetForm r
;
2459 r
.in
.handle
= handle
;
2460 r
.in
.form_name
= form_name
;
2464 torture_comment(tctx
, "Testing SetForm(%s) level %d\n",
2465 form_name
, r
.in
.level
);
2467 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_SetForm_r(b
, tctx
, &r
),
2470 torture_assert_werr_ok(tctx
, r
.out
.result
,
2476 static bool test_GetForm_winreg(struct torture_context
*tctx
,
2477 struct dcerpc_binding_handle
*b
,
2478 struct policy_handle
*handle
,
2479 const char *key_name
,
2480 const char *form_name
,
2481 enum winreg_Type
*w_type
,
2486 static bool test_Forms(struct torture_context
*tctx
,
2487 struct dcerpc_binding_handle
*b
,
2488 struct policy_handle
*handle
,
2490 const char *printer_name
,
2491 struct dcerpc_binding_handle
*winreg_handle
,
2492 struct policy_handle
*hive_handle
)
2494 union spoolss_FormInfo info
;
2495 const char *form_name
= "testform3";
2497 union spoolss_AddFormInfo add_info
;
2498 struct spoolss_AddFormInfo1 info1
;
2500 enum winreg_Type w_type
;
2505 info1
.flags
= SPOOLSS_FORM_USER
;
2506 info1
.form_name
= form_name
;
2507 info1
.size
.width
= 50;
2508 info1
.size
.height
= 25;
2509 info1
.area
.left
= 5;
2510 info1
.area
.top
= 10;
2511 info1
.area
.right
= 45;
2512 info1
.area
.bottom
= 15;
2514 add_info
.info1
= &info1
;
2516 torture_assert(tctx
,
2517 test_AddForm(tctx
, b
, handle
, 1, &add_info
),
2518 "failed to add form");
2520 if (winreg_handle
&& hive_handle
) {
2522 torture_assert(tctx
,
2523 test_GetForm_winreg(tctx
, winreg_handle
, hive_handle
, TOP_LEVEL_CONTROL_FORMS_KEY
, form_name
, &w_type
, &w_size
, &w_length
, &w_data
),
2524 "failed to get form via winreg");
2526 torture_assert_int_equal(tctx
, w_type
, REG_BINARY
, "unexpected type");
2527 torture_assert_int_equal(tctx
, w_size
, 0x20, "unexpected size");
2528 torture_assert_int_equal(tctx
, w_length
, 0x20, "unexpected length");
2529 torture_assert_mem_equal(tctx
, &w_data
[0], &add_info
.info1
->size
.width
, 4, "width mismatch");
2530 torture_assert_mem_equal(tctx
, &w_data
[4], &add_info
.info1
->size
.height
, 4, "height mismatch");
2531 torture_assert_mem_equal(tctx
, &w_data
[8], &add_info
.info1
->area
.left
, 4, "left mismatch");
2532 torture_assert_mem_equal(tctx
, &w_data
[12], &add_info
.info1
->area
.top
, 4, "top mismatch");
2533 torture_assert_mem_equal(tctx
, &w_data
[16], &add_info
.info1
->area
.right
, 4, "right mismatch");
2534 torture_assert_mem_equal(tctx
, &w_data
[20], &add_info
.info1
->area
.bottom
, 4, "bottom mismatch");
2535 /* skip index here */
2536 torture_assert_mem_equal(tctx
, &w_data
[28], &add_info
.info1
->flags
, 4, "flags mismatch");
2539 if (!print_server
) {
2540 torture_assert(tctx
,
2541 test_GetForm_args(tctx
, b
, handle
, form_name
, 1, &info
),
2542 "failed to get added form");
2544 torture_assert_int_equal(tctx
, info
.info1
.size
.width
, add_info
.info1
->size
.width
, "width mismatch");
2545 torture_assert_int_equal(tctx
, info
.info1
.size
.height
, add_info
.info1
->size
.height
, "height mismatch");
2546 torture_assert_int_equal(tctx
, info
.info1
.area
.left
, add_info
.info1
->area
.left
, "left mismatch");
2547 torture_assert_int_equal(tctx
, info
.info1
.area
.top
, add_info
.info1
->area
.top
, "top mismatch");
2548 torture_assert_int_equal(tctx
, info
.info1
.area
.right
, add_info
.info1
->area
.right
, "right mismatch");
2549 torture_assert_int_equal(tctx
, info
.info1
.area
.bottom
, add_info
.info1
->area
.bottom
, "bottom mismatch");
2550 torture_assert_int_equal(tctx
, info
.info1
.flags
, add_info
.info1
->flags
, "flags mismatch");
2552 if (winreg_handle
&& hive_handle
) {
2553 torture_assert_mem_equal(tctx
, &w_data
[0], &info
.info1
.size
.width
, 4, "width mismatch");
2554 torture_assert_mem_equal(tctx
, &w_data
[4], &info
.info1
.size
.height
, 4, "height mismatch");
2555 torture_assert_mem_equal(tctx
, &w_data
[8], &info
.info1
.area
.left
, 4, "left mismatch");
2556 torture_assert_mem_equal(tctx
, &w_data
[12], &info
.info1
.area
.top
, 4, "top mismatch");
2557 torture_assert_mem_equal(tctx
, &w_data
[16], &info
.info1
.area
.right
, 4, "right mismatch");
2558 torture_assert_mem_equal(tctx
, &w_data
[20], &info
.info1
.area
.bottom
, 4, "bottom mismatch");
2559 /* skip index here */
2560 torture_assert_mem_equal(tctx
, &w_data
[28], &info
.info1
.flags
, 4, "flags mismatch");
2563 add_info
.info1
->size
.width
= 1234;
2565 torture_assert(tctx
,
2566 test_SetForm(tctx
, b
, handle
, form_name
, 1, &add_info
),
2567 "failed to set form");
2568 torture_assert(tctx
,
2569 test_GetForm_args(tctx
, b
, handle
, form_name
, 1, &info
),
2570 "failed to get setted form");
2572 torture_assert_int_equal(tctx
, info
.info1
.size
.width
, add_info
.info1
->size
.width
, "width mismatch");
2575 torture_assert(tctx
,
2576 test_EnumForms_find_one(tctx
, b
, handle
, print_server
, form_name
),
2577 "Newly added form not found in enum call");
2579 torture_assert(tctx
,
2580 test_DeleteForm(tctx
, b
, handle
, form_name
),
2581 "failed to delete form");
2586 static bool test_EnumPorts_old(struct torture_context
*tctx
,
2587 struct dcerpc_pipe
*p
)
2590 struct spoolss_EnumPorts r
;
2593 union spoolss_PortInfo
*info
;
2594 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
2596 r
.in
.servername
= talloc_asprintf(tctx
, "\\\\%s",
2597 dcerpc_server_name(p
));
2601 r
.out
.needed
= &needed
;
2602 r
.out
.count
= &count
;
2605 torture_comment(tctx
, "Testing EnumPorts\n");
2607 status
= dcerpc_spoolss_EnumPorts_r(b
, tctx
, &r
);
2609 torture_assert_ntstatus_ok(tctx
, status
, "EnumPorts failed");
2611 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2612 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2613 data_blob_clear(&blob
);
2614 r
.in
.buffer
= &blob
;
2615 r
.in
.offered
= needed
;
2617 status
= dcerpc_spoolss_EnumPorts_r(b
, tctx
, &r
);
2618 torture_assert_ntstatus_ok(tctx
, status
, "EnumPorts failed");
2619 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
2621 torture_assert(tctx
, info
, "No ports returned");
2624 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
2626 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts
, info
, 2, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
2631 static bool test_AddPort(struct torture_context
*tctx
,
2632 struct dcerpc_pipe
*p
)
2635 struct spoolss_AddPort r
;
2636 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
2638 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s",
2639 dcerpc_server_name(p
));
2641 r
.in
.monitor_name
= "foo";
2643 torture_comment(tctx
, "Testing AddPort\n");
2645 status
= dcerpc_spoolss_AddPort_r(b
, tctx
, &r
);
2647 torture_assert_ntstatus_ok(tctx
, status
, "AddPort failed");
2649 /* win2k3 returns WERR_NOT_SUPPORTED */
2653 if (!W_ERROR_IS_OK(r
.out
.result
)) {
2654 printf("AddPort failed - %s\n", win_errstr(r
.out
.result
));
2663 static bool test_GetJob_args(struct torture_context
*tctx
,
2664 struct dcerpc_binding_handle
*b
,
2665 struct policy_handle
*handle
,
2668 union spoolss_JobInfo
*info_p
)
2671 struct spoolss_GetJob r
;
2672 union spoolss_JobInfo info
;
2675 r
.in
.handle
= handle
;
2676 r
.in
.job_id
= job_id
;
2680 r
.out
.needed
= &needed
;
2683 torture_comment(tctx
, "Testing GetJob(%d), level %d\n", job_id
, r
.in
.level
);
2685 status
= dcerpc_spoolss_GetJob_r(b
, tctx
, &r
);
2686 torture_assert_ntstatus_ok(tctx
, status
, "GetJob failed");
2688 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
, "Unexpected return code");
2691 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2692 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2693 data_blob_clear(&blob
);
2694 r
.in
.buffer
= &blob
;
2695 r
.in
.offered
= needed
;
2697 status
= dcerpc_spoolss_GetJob_r(b
, tctx
, &r
);
2698 torture_assert_ntstatus_ok(tctx
, status
, "GetJob failed");
2699 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetJob failed");
2700 torture_assert(tctx
, r
.out
.info
, "No job info returned");
2702 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
2706 *info_p
= *r
.out
.info
;
2712 static bool test_GetJob(struct torture_context
*tctx
,
2713 struct dcerpc_binding_handle
*b
,
2714 struct policy_handle
*handle
,
2717 uint32_t levels
[] = {0, 1, 2 /* 3, 4 */};
2720 for (i
=0; i
< ARRAY_SIZE(levels
); i
++) {
2721 torture_assert(tctx
,
2722 test_GetJob_args(tctx
, b
, handle
, job_id
, levels
[i
], NULL
),
2729 static bool test_SetJob(struct torture_context
*tctx
,
2730 struct dcerpc_binding_handle
*b
,
2731 struct policy_handle
*handle
, uint32_t job_id
,
2732 enum spoolss_JobControl command
)
2735 struct spoolss_SetJob r
;
2737 r
.in
.handle
= handle
;
2738 r
.in
.job_id
= job_id
;
2740 r
.in
.command
= command
;
2743 case SPOOLSS_JOB_CONTROL_PAUSE
:
2744 torture_comment(tctx
, "Testing SetJob(%d) SPOOLSS_JOB_CONTROL_PAUSE\n", job_id
);
2746 case SPOOLSS_JOB_CONTROL_RESUME
:
2747 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id
);
2749 case SPOOLSS_JOB_CONTROL_CANCEL
:
2750 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id
);
2752 case SPOOLSS_JOB_CONTROL_RESTART
:
2753 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id
);
2755 case SPOOLSS_JOB_CONTROL_DELETE
:
2756 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id
);
2758 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER
:
2759 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id
);
2761 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED
:
2762 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id
);
2764 case SPOOLSS_JOB_CONTROL_RETAIN
:
2765 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id
);
2767 case SPOOLSS_JOB_CONTROL_RELEASE
:
2768 torture_comment(tctx
, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id
);
2771 torture_comment(tctx
, "Testing SetJob(%d)\n", job_id
);
2775 status
= dcerpc_spoolss_SetJob_r(b
, tctx
, &r
);
2776 torture_assert_ntstatus_ok(tctx
, status
, "SetJob failed");
2777 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetJob failed");
2782 static bool test_AddJob(struct torture_context
*tctx
,
2783 struct dcerpc_binding_handle
*b
,
2784 struct policy_handle
*handle
)
2787 struct spoolss_AddJob r
;
2791 r
.in
.handle
= handle
;
2793 r
.out
.needed
= &needed
;
2794 r
.in
.buffer
= r
.out
.buffer
= NULL
;
2796 torture_comment(tctx
, "Testing AddJob\n");
2798 status
= dcerpc_spoolss_AddJob_r(b
, tctx
, &r
);
2799 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
, "AddJob failed");
2803 status
= dcerpc_spoolss_AddJob_r(b
, tctx
, &r
);
2804 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
, "AddJob failed");
2810 static bool test_EnumJobs_args(struct torture_context
*tctx
,
2811 struct dcerpc_binding_handle
*b
,
2812 struct policy_handle
*handle
,
2815 union spoolss_JobInfo
**info_p
)
2818 struct spoolss_EnumJobs r
;
2821 union spoolss_JobInfo
*info
;
2823 r
.in
.handle
= handle
;
2825 r
.in
.numjobs
= 0xffffffff;
2829 r
.out
.needed
= &needed
;
2830 r
.out
.count
= &count
;
2833 torture_comment(tctx
, "Testing EnumJobs level %d\n", level
);
2835 status
= dcerpc_spoolss_EnumJobs_r(b
, tctx
, &r
);
2837 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
2839 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2840 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2841 data_blob_clear(&blob
);
2842 r
.in
.buffer
= &blob
;
2843 r
.in
.offered
= needed
;
2845 status
= dcerpc_spoolss_EnumJobs_r(b
, tctx
, &r
);
2847 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
2848 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumJobs failed");
2849 torture_assert(tctx
, info
, "No jobs returned");
2851 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs
, *r
.out
.info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
2854 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumJobs failed");
2867 static bool test_DoPrintTest_add_one_job(struct torture_context
*tctx
,
2868 struct dcerpc_binding_handle
*b
,
2869 struct policy_handle
*handle
,
2873 struct spoolss_StartDocPrinter s
;
2874 struct spoolss_DocumentInfo1 info1
;
2875 struct spoolss_StartPagePrinter sp
;
2876 struct spoolss_WritePrinter w
;
2877 struct spoolss_EndPagePrinter ep
;
2878 struct spoolss_EndDocPrinter e
;
2880 uint32_t num_written
;
2882 torture_comment(tctx
, "Testing StartDocPrinter\n");
2884 s
.in
.handle
= handle
;
2886 s
.in
.info
.info1
= &info1
;
2887 s
.out
.job_id
= job_id
;
2888 info1
.document_name
= "TorturePrintJob";
2889 info1
.output_file
= NULL
;
2890 info1
.datatype
= "RAW";
2892 status
= dcerpc_spoolss_StartDocPrinter_r(b
, tctx
, &s
);
2893 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_StartDocPrinter failed");
2894 torture_assert_werr_ok(tctx
, s
.out
.result
, "StartDocPrinter failed");
2896 for (i
=1; i
< 4; i
++) {
2897 torture_comment(tctx
, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i
, *job_id
);
2899 sp
.in
.handle
= handle
;
2901 status
= dcerpc_spoolss_StartPagePrinter_r(b
, tctx
, &sp
);
2902 torture_assert_ntstatus_ok(tctx
, status
,
2903 "dcerpc_spoolss_StartPagePrinter failed");
2904 torture_assert_werr_ok(tctx
, sp
.out
.result
, "StartPagePrinter failed");
2906 torture_comment(tctx
, "Testing WritePrinter: Page[%d], JobId[%d]\n", i
, *job_id
);
2908 w
.in
.handle
= handle
;
2909 w
.in
.data
= data_blob_string_const(talloc_asprintf(tctx
,"TortureTestPage: %d\nData\n",i
));
2910 w
.out
.num_written
= &num_written
;
2912 status
= dcerpc_spoolss_WritePrinter_r(b
, tctx
, &w
);
2913 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_WritePrinter failed");
2914 torture_assert_werr_ok(tctx
, w
.out
.result
, "WritePrinter failed");
2916 torture_comment(tctx
, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i
, *job_id
);
2918 ep
.in
.handle
= handle
;
2920 status
= dcerpc_spoolss_EndPagePrinter_r(b
, tctx
, &ep
);
2921 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndPagePrinter failed");
2922 torture_assert_werr_ok(tctx
, ep
.out
.result
, "EndPagePrinter failed");
2925 torture_comment(tctx
, "Testing EndDocPrinter: JobId[%d]\n", *job_id
);
2927 e
.in
.handle
= handle
;
2929 status
= dcerpc_spoolss_EndDocPrinter_r(b
, tctx
, &e
);
2930 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndDocPrinter failed");
2931 torture_assert_werr_ok(tctx
, e
.out
.result
, "EndDocPrinter failed");
2936 static bool test_DoPrintTest_check_jobs(struct torture_context
*tctx
,
2937 struct dcerpc_binding_handle
*b
,
2938 struct policy_handle
*handle
,
2943 union spoolss_JobInfo
*info
= NULL
;
2946 torture_assert(tctx
,
2947 test_AddJob(tctx
, b
, handle
),
2950 torture_assert(tctx
,
2951 test_EnumJobs_args(tctx
, b
, handle
, 1, &count
, &info
),
2952 "EnumJobs level 1 failed");
2954 torture_assert_int_equal(tctx
, count
, num_jobs
, "unexpected number of jobs in queue");
2956 for (i
=0; i
< num_jobs
; i
++) {
2957 union spoolss_JobInfo ginfo
;
2959 torture_assert_int_equal(tctx
, info
[i
].info1
.job_id
, job_ids
[i
], "job id mismatch");
2961 torture_assert(tctx
,
2962 test_GetJob_args(tctx
, b
, handle
, info
[i
].info1
.job_id
, 1, &ginfo
),
2963 "failed to call test_GetJob");
2965 torture_assert_int_equal(tctx
, ginfo
.info1
.job_id
, info
[i
].info1
.job_id
, "job id mismatch");
2968 for (i
=0; i
< num_jobs
; i
++) {
2969 torture_assert(tctx
,
2970 test_SetJob(tctx
, b
, handle
, info
[i
].info1
.job_id
, SPOOLSS_JOB_CONTROL_PAUSE
),
2971 "failed to pause printjob");
2972 torture_assert(tctx
,
2973 test_SetJob(tctx
, b
, handle
, info
[i
].info1
.job_id
, SPOOLSS_JOB_CONTROL_RESUME
),
2974 "failed to resume printjob");
2980 static bool test_DoPrintTest(struct torture_context
*tctx
,
2981 struct dcerpc_binding_handle
*b
,
2982 struct policy_handle
*handle
)
2985 uint32_t num_jobs
= 8;
2989 job_ids
= talloc_zero_array(tctx
, uint32_t, num_jobs
);
2991 for (i
=0; i
< num_jobs
; i
++) {
2992 ret
&= test_DoPrintTest_add_one_job(tctx
, b
, handle
, &job_ids
[i
]);
2995 ret
&= test_DoPrintTest_check_jobs(tctx
, b
, handle
, num_jobs
, job_ids
);
2997 for (i
=0; i
< num_jobs
; i
++) {
2998 ret
&= test_SetJob(tctx
, b
, handle
, job_ids
[i
], SPOOLSS_JOB_CONTROL_DELETE
);
3004 static bool test_PausePrinter(struct torture_context
*tctx
,
3005 struct dcerpc_binding_handle
*b
,
3006 struct policy_handle
*handle
)
3009 struct spoolss_SetPrinter r
;
3010 struct spoolss_SetPrinterInfoCtr info_ctr
;
3011 struct spoolss_DevmodeContainer devmode_ctr
;
3012 struct sec_desc_buf secdesc_ctr
;
3015 info_ctr
.info
.info0
= NULL
;
3017 ZERO_STRUCT(devmode_ctr
);
3018 ZERO_STRUCT(secdesc_ctr
);
3020 r
.in
.handle
= handle
;
3021 r
.in
.info_ctr
= &info_ctr
;
3022 r
.in
.devmode_ctr
= &devmode_ctr
;
3023 r
.in
.secdesc_ctr
= &secdesc_ctr
;
3024 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
3026 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3028 status
= dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
);
3030 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
3032 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
3037 static bool test_ResumePrinter(struct torture_context
*tctx
,
3038 struct dcerpc_binding_handle
*b
,
3039 struct policy_handle
*handle
)
3042 struct spoolss_SetPrinter r
;
3043 struct spoolss_SetPrinterInfoCtr info_ctr
;
3044 struct spoolss_DevmodeContainer devmode_ctr
;
3045 struct sec_desc_buf secdesc_ctr
;
3048 info_ctr
.info
.info0
= NULL
;
3050 ZERO_STRUCT(devmode_ctr
);
3051 ZERO_STRUCT(secdesc_ctr
);
3053 r
.in
.handle
= handle
;
3054 r
.in
.info_ctr
= &info_ctr
;
3055 r
.in
.devmode_ctr
= &devmode_ctr
;
3056 r
.in
.secdesc_ctr
= &secdesc_ctr
;
3057 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
3059 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3061 status
= dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
);
3063 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
3065 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
3070 static bool test_GetPrinterData(struct torture_context
*tctx
,
3071 struct dcerpc_binding_handle
*b
,
3072 struct policy_handle
*handle
,
3073 const char *value_name
,
3074 enum winreg_Type
*type_p
,
3079 struct spoolss_GetPrinterData r
;
3081 enum winreg_Type type
;
3082 union spoolss_PrinterData data
;
3084 r
.in
.handle
= handle
;
3085 r
.in
.value_name
= value_name
;
3087 r
.out
.needed
= &needed
;
3089 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
3091 torture_comment(tctx
, "Testing GetPrinterData(%s)\n", r
.in
.value_name
);
3093 status
= dcerpc_spoolss_GetPrinterData_r(b
, tctx
, &r
);
3094 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
3096 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
3097 r
.in
.offered
= needed
;
3098 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
3099 status
= dcerpc_spoolss_GetPrinterData_r(b
, tctx
, &r
);
3100 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
3103 torture_assert_werr_ok(tctx
, r
.out
.result
,
3104 talloc_asprintf(tctx
, "GetPrinterData(%s) failed", r
.in
.value_name
));
3106 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData
, &data
, type
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 1);
3113 *data_p
= r
.out
.data
;
3123 static bool test_GetPrinterDataEx(struct torture_context
*tctx
,
3124 struct dcerpc_pipe
*p
,
3125 struct policy_handle
*handle
,
3126 const char *key_name
,
3127 const char *value_name
,
3128 enum winreg_Type
*type_p
,
3133 struct spoolss_GetPrinterDataEx r
;
3134 enum winreg_Type type
;
3136 union spoolss_PrinterData data
;
3137 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
3139 r
.in
.handle
= handle
;
3140 r
.in
.key_name
= key_name
;
3141 r
.in
.value_name
= value_name
;
3144 r
.out
.needed
= &needed
;
3145 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
3147 torture_comment(tctx
, "Testing GetPrinterDataEx(%s - %s)\n",
3148 r
.in
.key_name
, r
.in
.value_name
);
3150 status
= dcerpc_spoolss_GetPrinterDataEx_r(b
, tctx
, &r
);
3151 if (!NT_STATUS_IS_OK(status
)) {
3152 if (NT_STATUS_EQUAL(status
,NT_STATUS_NET_WRITE_FAULT
) &&
3153 p
->last_fault_code
== DCERPC_FAULT_OP_RNG_ERROR
) {
3154 torture_skip(tctx
, "GetPrinterDataEx not supported by server\n");
3156 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
3159 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
3160 r
.in
.offered
= needed
;
3161 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
3162 status
= dcerpc_spoolss_GetPrinterDataEx_r(b
, tctx
, &r
);
3163 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
3166 torture_assert_werr_ok(tctx
, r
.out
.result
,
3167 talloc_asprintf(tctx
, "GetPrinterDataEx(%s - %s) failed", r
.in
.key_name
, r
.in
.value_name
));
3169 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData
, &data
, type
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 1);
3176 *data_p
= r
.out
.data
;
3186 static bool test_GetPrinterData_list(struct torture_context
*tctx
,
3187 struct dcerpc_pipe
*p
,
3188 struct policy_handle
*handle
,
3189 const char **architecture
)
3191 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
3192 const char *list
[] = {
3196 /* "NetPopup", not on w2k8 */
3197 /* "NetPopupToComputer", not on w2k8 */
3200 "DefaultSpoolDirectory",
3204 /* "OSVersionEx", not on s3 */
3209 for (i
=0; i
< ARRAY_SIZE(list
); i
++) {
3210 enum winreg_Type type
, type_ex
;
3211 uint8_t *data
, *data_ex
;
3212 uint32_t needed
, needed_ex
;
3214 torture_assert(tctx
, test_GetPrinterData(tctx
, b
, handle
, list
[i
], &type
, &data
, &needed
),
3215 talloc_asprintf(tctx
, "GetPrinterData failed on %s\n", list
[i
]));
3216 torture_assert(tctx
, test_GetPrinterDataEx(tctx
, p
, handle
, "random_string", list
[i
], &type_ex
, &data_ex
, &needed_ex
),
3217 talloc_asprintf(tctx
, "GetPrinterDataEx failed on %s\n", list
[i
]));
3218 torture_assert_int_equal(tctx
, type
, type_ex
, "type mismatch");
3219 torture_assert_int_equal(tctx
, needed
, needed_ex
, "needed mismatch");
3220 torture_assert_mem_equal(tctx
, data
, data_ex
, needed
, "data mismatch");
3222 if (strequal(list
[i
], "Architecture")) {
3224 DATA_BLOB blob
= data_blob_const(data
, needed
);
3225 *architecture
= reg_val_data_string(tctx
, lp_iconv_convenience(tctx
->lp_ctx
), REG_SZ
, blob
);
3233 static bool test_EnumPrinterData(struct torture_context
*tctx
,
3234 struct dcerpc_pipe
*p
,
3235 struct policy_handle
*handle
,
3236 uint32_t enum_index
,
3237 uint32_t value_offered
,
3238 uint32_t data_offered
,
3239 enum winreg_Type
*type_p
,
3240 uint32_t *value_needed_p
,
3241 uint32_t *data_needed_p
,
3242 const char **value_name_p
,
3246 struct spoolss_EnumPrinterData r
;
3247 uint32_t data_needed
;
3248 uint32_t value_needed
;
3249 enum winreg_Type type
;
3250 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
3252 r
.in
.handle
= handle
;
3253 r
.in
.enum_index
= enum_index
;
3254 r
.in
.value_offered
= value_offered
;
3255 r
.in
.data_offered
= data_offered
;
3256 r
.out
.data_needed
= &data_needed
;
3257 r
.out
.value_needed
= &value_needed
;
3259 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.data_offered
);
3260 r
.out
.value_name
= talloc_zero_array(tctx
, const char, r
.in
.value_offered
);
3262 torture_comment(tctx
, "Testing EnumPrinterData(%d)\n", enum_index
);
3264 torture_assert_ntstatus_ok(tctx
,
3265 dcerpc_spoolss_EnumPrinterData_r(b
, tctx
, &r
),
3266 "EnumPrinterData failed");
3271 if (value_needed_p
) {
3272 *value_needed_p
= value_needed
;
3274 if (data_needed_p
) {
3275 *data_needed_p
= data_needed
;
3278 *value_name_p
= r
.out
.value_name
;
3281 *data_p
= r
.out
.data
;
3284 *result_p
= r
.out
.result
;
3291 static bool test_EnumPrinterData_all(struct torture_context
*tctx
,
3292 struct dcerpc_pipe
*p
,
3293 struct policy_handle
*handle
)
3295 uint32_t enum_index
= 0;
3296 enum winreg_Type type
;
3297 uint32_t value_needed
;
3298 uint32_t data_needed
;
3300 const char *value_name
;
3303 torture_comment(tctx
, "Testing EnumPrinterData\n");
3306 torture_assert(tctx
,
3307 test_EnumPrinterData(tctx
, p
, handle
, enum_index
, 0, 0,
3308 &type
, &value_needed
, &data_needed
,
3309 &value_name
, &data
, &result
),
3310 "EnumPrinterData failed");
3312 if (W_ERROR_EQUAL(result
, WERR_NO_MORE_ITEMS
)) {
3316 torture_assert(tctx
,
3317 test_EnumPrinterData(tctx
, p
, handle
, enum_index
, value_needed
, data_needed
,
3318 &type
, &value_needed
, &data_needed
,
3319 &value_name
, &data
, &result
),
3320 "EnumPrinterData failed");
3322 if (W_ERROR_EQUAL(result
, WERR_NO_MORE_ITEMS
)) {
3328 } while (W_ERROR_IS_OK(result
));
3330 torture_comment(tctx
, "EnumPrinterData test succeeded\n");
3335 static bool test_EnumPrinterDataEx(struct torture_context
*tctx
,
3336 struct dcerpc_binding_handle
*b
,
3337 struct policy_handle
*handle
,
3338 const char *key_name
,
3340 struct spoolss_PrinterEnumValues
**info_p
)
3342 struct spoolss_EnumPrinterDataEx r
;
3343 struct spoolss_PrinterEnumValues
*info
;
3347 r
.in
.handle
= handle
;
3348 r
.in
.key_name
= key_name
;
3350 r
.out
.needed
= &needed
;
3351 r
.out
.count
= &count
;
3354 torture_comment(tctx
, "Testing EnumPrinterDataEx(%s)\n", key_name
);
3356 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterDataEx_r(b
, tctx
, &r
),
3357 "EnumPrinterDataEx failed");
3358 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
3359 r
.in
.offered
= needed
;
3360 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterDataEx_r(b
, tctx
, &r
),
3361 "EnumPrinterDataEx failed");
3364 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDataEx failed");
3366 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx
, info
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 1);
3378 static bool test_SetPrinterData(struct torture_context
*tctx
,
3379 struct dcerpc_binding_handle
*b
,
3380 struct policy_handle
*handle
,
3381 const char *value_name
,
3382 enum winreg_Type type
,
3385 static bool test_DeletePrinterData(struct torture_context
*tctx
,
3386 struct dcerpc_binding_handle
*b
,
3387 struct policy_handle
*handle
,
3388 const char *value_name
);
3390 static bool test_EnumPrinterData_consistency(struct torture_context
*tctx
,
3391 struct dcerpc_pipe
*p
,
3392 struct policy_handle
*handle
)
3395 struct spoolss_PrinterEnumValues
*info
;
3397 uint32_t value_needed
, data_needed
;
3398 uint32_t value_offered
, data_offered
;
3400 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
3402 enum winreg_Type type
;
3405 torture_comment(tctx
, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3407 torture_assert(tctx
,
3408 reg_string_to_val(tctx
, lp_iconv_convenience(tctx
->lp_ctx
),
3409 "REG_SZ", "torture_data1", &type
, &blob
), "");
3411 torture_assert(tctx
,
3412 test_SetPrinterData(tctx
, b
, handle
, "torture_value1", type
, blob
.data
, blob
.length
),
3413 "SetPrinterData failed");
3415 blob
= data_blob_string_const("torture_data2");
3417 torture_assert(tctx
,
3418 test_SetPrinterData(tctx
, b
, handle
, "torture_value2", REG_BINARY
, blob
.data
, blob
.length
),
3419 "SetPrinterData failed");
3421 blob
= data_blob_talloc(tctx
, NULL
, 4);
3422 SIVAL(blob
.data
, 0, 0x11223344);
3424 torture_assert(tctx
,
3425 test_SetPrinterData(tctx
, b
, handle
, "torture_value3", type
, blob
.data
, blob
.length
),
3426 "SetPrinterData failed");
3428 torture_assert(tctx
,
3429 test_EnumPrinterDataEx(tctx
, b
, handle
, "PrinterDriverData", &count
, &info
),
3430 "failed to call EnumPrinterDataEx");
3432 /* get the max sizes for value and data */
3434 torture_assert(tctx
,
3435 test_EnumPrinterData(tctx
, p
, handle
, 0, 0, 0,
3436 NULL
, &value_needed
, &data_needed
,
3437 NULL
, NULL
, &result
),
3438 "EnumPrinterData failed");
3439 torture_assert_werr_ok(tctx
, result
, "unexpected result");
3441 /* check if the reply from the EnumPrinterData really matches max values */
3443 for (i
=0; i
< count
; i
++) {
3444 if (info
[i
].value_name_len
> value_needed
) {
3446 talloc_asprintf(tctx
,
3447 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3448 info
[i
].value_name_len
, value_needed
));
3450 if (info
[i
].data_length
> data_needed
) {
3452 talloc_asprintf(tctx
,
3453 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3454 info
[i
].data_length
, data_needed
));
3458 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3459 * sort or not sort the replies by value name, we should be able to do
3460 * the following entry comparison */
3462 data_offered
= data_needed
;
3463 value_offered
= value_needed
;
3465 for (i
=0; i
< count
; i
++) {
3467 const char *value_name
;
3470 torture_assert(tctx
,
3471 test_EnumPrinterData(tctx
, p
, handle
, i
, value_offered
, data_offered
,
3472 &type
, &value_needed
, &data_needed
,
3473 &value_name
, &data
, &result
),
3474 "EnumPrinterData failed");
3476 if (i
-1 == count
) {
3477 torture_assert_werr_equal(tctx
, result
, WERR_NO_MORE_ITEMS
,
3478 "unexpected result");
3481 torture_assert_werr_ok(tctx
, result
, "unexpected result");
3484 torture_assert_int_equal(tctx
, type
, info
[i
].type
, "type mismatch");
3485 torture_assert_int_equal(tctx
, value_needed
, info
[i
].value_name_len
, "value name length mismatch");
3486 torture_assert_str_equal(tctx
, value_name
, info
[i
].value_name
, "value name mismatch");
3487 torture_assert_int_equal(tctx
, data_needed
, info
[i
].data_length
, "data length mismatch");
3488 torture_assert_mem_equal(tctx
, data
, info
[i
].data
->data
, info
[i
].data_length
, "data mismatch");
3491 torture_assert(tctx
,
3492 test_DeletePrinterData(tctx
, b
, handle
, "torture_value1"),
3493 "DeletePrinterData failed");
3494 torture_assert(tctx
,
3495 test_DeletePrinterData(tctx
, b
, handle
, "torture_value2"),
3496 "DeletePrinterData failed");
3497 torture_assert(tctx
,
3498 test_DeletePrinterData(tctx
, b
, handle
, "torture_value3"),
3499 "DeletePrinterData failed");
3501 torture_comment(tctx
, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
3506 static bool test_DeletePrinterData(struct torture_context
*tctx
,
3507 struct dcerpc_binding_handle
*b
,
3508 struct policy_handle
*handle
,
3509 const char *value_name
)
3512 struct spoolss_DeletePrinterData r
;
3514 r
.in
.handle
= handle
;
3515 r
.in
.value_name
= value_name
;
3517 torture_comment(tctx
, "Testing DeletePrinterData(%s)\n",
3520 status
= dcerpc_spoolss_DeletePrinterData_r(b
, tctx
, &r
);
3522 torture_assert_ntstatus_ok(tctx
, status
, "DeletePrinterData failed");
3523 torture_assert_werr_ok(tctx
, r
.out
.result
, "DeletePrinterData failed");
3528 static bool test_DeletePrinterDataEx(struct torture_context
*tctx
,
3529 struct dcerpc_binding_handle
*b
,
3530 struct policy_handle
*handle
,
3531 const char *key_name
,
3532 const char *value_name
)
3534 struct spoolss_DeletePrinterDataEx r
;
3536 r
.in
.handle
= handle
;
3537 r
.in
.key_name
= key_name
;
3538 r
.in
.value_name
= value_name
;
3540 torture_comment(tctx
, "Testing DeletePrinterDataEx(%s - %s)\n",
3541 r
.in
.key_name
, r
.in
.value_name
);
3543 torture_assert_ntstatus_ok(tctx
,
3544 dcerpc_spoolss_DeletePrinterDataEx_r(b
, tctx
, &r
),
3545 "DeletePrinterDataEx failed");
3546 torture_assert_werr_ok(tctx
, r
.out
.result
,
3547 "DeletePrinterDataEx failed");
3552 static bool test_DeletePrinterKey(struct torture_context
*tctx
,
3553 struct dcerpc_binding_handle
*b
,
3554 struct policy_handle
*handle
,
3555 const char *key_name
)
3557 struct spoolss_DeletePrinterKey r
;
3559 r
.in
.handle
= handle
;
3560 r
.in
.key_name
= key_name
;
3562 torture_comment(tctx
, "Testing DeletePrinterKey(%s)\n", r
.in
.key_name
);
3564 if (strequal(key_name
, "") && !torture_setting_bool(tctx
, "dangerous", false)) {
3565 torture_skip(tctx
, "not wiping out printer registry - enable dangerous tests to use\n");
3569 torture_assert_ntstatus_ok(tctx
,
3570 dcerpc_spoolss_DeletePrinterKey_r(b
, tctx
, &r
),
3571 "DeletePrinterKey failed");
3572 torture_assert_werr_ok(tctx
, r
.out
.result
,
3573 "DeletePrinterKey failed");
3578 static bool test_winreg_OpenHKLM(struct torture_context
*tctx
,
3579 struct dcerpc_binding_handle
*b
,
3580 struct policy_handle
*handle
)
3582 struct winreg_OpenHKLM r
;
3584 r
.in
.system_name
= NULL
;
3585 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
3586 r
.out
.handle
= handle
;
3588 torture_comment(tctx
, "Testing winreg_OpenHKLM\n");
3590 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_OpenHKLM_r(b
, tctx
, &r
), "OpenHKLM failed");
3591 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenHKLM failed");
3596 static void init_winreg_String(struct winreg_String
*name
, const char *s
)
3600 name
->name_len
= 2 * (strlen_m(s
) + 1);
3601 name
->name_size
= name
->name_len
;
3604 name
->name_size
= 0;
3608 static bool test_winreg_OpenKey(struct torture_context
*tctx
,
3609 struct dcerpc_binding_handle
*b
,
3610 struct policy_handle
*hive_handle
,
3611 const char *keyname
,
3612 struct policy_handle
*key_handle
)
3614 struct winreg_OpenKey r
;
3616 r
.in
.parent_handle
= hive_handle
;
3617 init_winreg_String(&r
.in
.keyname
, keyname
);
3618 r
.in
.options
= REG_KEYTYPE_NON_VOLATILE
;
3619 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
3620 r
.out
.handle
= key_handle
;
3622 torture_comment(tctx
, "Testing winreg_OpenKey(%s)\n", keyname
);
3624 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_OpenKey_r(b
, tctx
, &r
), "OpenKey failed");
3625 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenKey failed");
3630 static bool test_winreg_CloseKey(struct torture_context
*tctx
,
3631 struct dcerpc_binding_handle
*b
,
3632 struct policy_handle
*handle
)
3634 struct winreg_CloseKey r
;
3636 r
.in
.handle
= handle
;
3637 r
.out
.handle
= handle
;
3639 torture_comment(tctx
, "Testing winreg_CloseKey\n");
3641 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_CloseKey_r(b
, tctx
, &r
), "CloseKey failed");
3642 torture_assert_werr_ok(tctx
, r
.out
.result
, "CloseKey failed");
3647 bool test_winreg_QueryValue(struct torture_context
*tctx
,
3648 struct dcerpc_binding_handle
*b
,
3649 struct policy_handle
*handle
,
3650 const char *value_name
,
3651 enum winreg_Type
*type_p
,
3652 uint32_t *data_size_p
,
3653 uint32_t *data_length_p
,
3656 struct winreg_QueryValue r
;
3657 enum winreg_Type type
= REG_NONE
;
3658 uint32_t data_size
= 0;
3659 uint32_t data_length
= 0;
3660 struct winreg_String valuename
;
3661 uint8_t *data
= NULL
;
3663 init_winreg_String(&valuename
, value_name
);
3665 data
= talloc_zero_array(tctx
, uint8_t, 0);
3667 r
.in
.handle
= handle
;
3668 r
.in
.value_name
= &valuename
;
3670 r
.in
.data_size
= &data_size
;
3671 r
.in
.data_length
= &data_length
;
3675 r
.out
.data_size
= &data_size
;
3676 r
.out
.data_length
= &data_length
;
3678 torture_comment(tctx
, "Testing winreg_QueryValue(%s)\n", value_name
);
3680 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_QueryValue_r(b
, tctx
, &r
), "QueryValue failed");
3681 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
3682 *r
.in
.data_size
= *r
.out
.data_size
;
3683 data
= talloc_zero_array(tctx
, uint8_t, *r
.in
.data_size
);
3686 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_QueryValue_r(b
, tctx
, &r
), "QueryValue failed");
3688 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryValue failed");
3691 *type_p
= *r
.out
.type
;
3694 *data_size_p
= *r
.out
.data_size
;
3696 if (data_length_p
) {
3697 *data_length_p
= *r
.out
.data_length
;
3700 *data_p
= r
.out
.data
;
3706 static bool test_winreg_query_printerdata(struct torture_context
*tctx
,
3707 struct dcerpc_binding_handle
*b
,
3708 struct policy_handle
*handle
,
3709 const char *printer_name
,
3710 const char *key_name
,
3711 const char *value_name
,
3712 enum winreg_Type
*w_type
,
3717 const char *printer_key
;
3718 struct policy_handle key_handle
;
3720 printer_key
= talloc_asprintf(tctx
, "%s\\%s\\%s",
3721 TOP_LEVEL_PRINT_PRINTERS_KEY
, printer_name
, key_name
);
3723 torture_assert(tctx
,
3724 test_winreg_OpenKey(tctx
, b
, handle
, printer_key
, &key_handle
), "");
3726 torture_assert(tctx
,
3727 test_winreg_QueryValue(tctx
, b
, &key_handle
, value_name
, w_type
, w_size
, w_length
, w_data
), "");
3729 torture_assert(tctx
,
3730 test_winreg_CloseKey(tctx
, b
, &key_handle
), "");
3735 static bool test_GetForm_winreg(struct torture_context
*tctx
,
3736 struct dcerpc_binding_handle
*b
,
3737 struct policy_handle
*handle
,
3738 const char *key_name
,
3739 const char *form_name
,
3740 enum winreg_Type
*w_type
,
3745 struct policy_handle key_handle
;
3747 torture_assert(tctx
,
3748 test_winreg_OpenKey(tctx
, b
, handle
, key_name
, &key_handle
), "");
3750 torture_assert(tctx
,
3751 test_winreg_QueryValue(tctx
, b
, &key_handle
, form_name
, w_type
, w_size
, w_length
, w_data
), "");
3753 torture_assert(tctx
,
3754 test_winreg_CloseKey(tctx
, b
, &key_handle
), "");
3759 static bool test_SetPrinterData(struct torture_context
*tctx
,
3760 struct dcerpc_binding_handle
*b
,
3761 struct policy_handle
*handle
,
3762 const char *value_name
,
3763 enum winreg_Type type
,
3767 struct spoolss_SetPrinterData r
;
3769 r
.in
.handle
= handle
;
3770 r
.in
.value_name
= value_name
;
3773 r
.in
.offered
= offered
;
3775 torture_comment(tctx
, "Testing SetPrinterData(%s)\n",
3778 torture_assert_ntstatus_ok(tctx
,
3779 dcerpc_spoolss_SetPrinterData_r(b
, tctx
, &r
),
3780 "SetPrinterData failed");
3781 torture_assert_werr_ok(tctx
, r
.out
.result
,
3782 "SetPrinterData failed");
3787 static bool test_SetPrinterData_matrix(struct torture_context
*tctx
,
3788 struct dcerpc_binding_handle
*b
,
3789 struct policy_handle
*handle
,
3790 const char *printer_name
,
3791 struct dcerpc_binding_handle
*winreg_handle
,
3792 struct policy_handle
*hive_handle
)
3794 const char *values
[] = {
3798 /* FIXME: not working with s3 atm. */
3804 /* FIXME: not working with s3 atm. */
3811 for (i
=0; i
< ARRAY_SIZE(values
); i
++) {
3813 enum winreg_Type type
;
3818 torture_assert(tctx
,
3819 reg_string_to_val(tctx
, lp_iconv_convenience(tctx
->lp_ctx
),
3820 "REG_SZ", "dog", &type
, &blob
), "");
3822 torture_assert(tctx
,
3823 test_SetPrinterData(tctx
, b
, handle
, values
[i
], REG_SZ
, blob
.data
, blob
.length
),
3824 "SetPrinterData failed");
3826 torture_assert(tctx
,
3827 test_GetPrinterData(tctx
, b
, handle
, values
[i
], &type
, &data
, &needed
),
3828 "GetPrinterData failed");
3830 torture_assert_int_equal(tctx
, type
, REG_SZ
, "type mismatch");
3831 torture_assert_int_equal(tctx
, needed
, blob
.length
, "size mismatch");
3832 torture_assert_mem_equal(tctx
, data
, blob
.data
, blob
.length
, "buffer mismatch");
3834 if (winreg_handle
&& hive_handle
) {
3836 enum winreg_Type w_type
;
3841 torture_assert(tctx
,
3842 test_winreg_query_printerdata(tctx
, winreg_handle
, hive_handle
,
3843 printer_name
, "PrinterDriverData", values
[i
],
3844 &w_type
, &w_size
, &w_length
, &w_data
), "");
3846 torture_assert_int_equal(tctx
, w_type
, REG_SZ
, "winreg type mismatch");
3847 torture_assert_int_equal(tctx
, w_size
, blob
.length
, "winreg size mismatch");
3848 torture_assert_int_equal(tctx
, w_length
, blob
.length
, "winreg length mismatch");
3849 torture_assert_mem_equal(tctx
, w_data
, blob
.data
, blob
.length
, "winreg buffer mismatch");
3852 torture_assert(tctx
,
3853 test_DeletePrinterData(tctx
, b
, handle
, values
[i
]),
3854 "DeletePrinterData failed");
3861 static bool test_EnumPrinterKey(struct torture_context
*tctx
,
3862 struct dcerpc_binding_handle
*b
,
3863 struct policy_handle
*handle
,
3864 const char *key_name
,
3865 const char ***array
);
3867 static bool test_SetPrinterDataEx(struct torture_context
*tctx
,
3868 struct dcerpc_binding_handle
*b
,
3869 struct policy_handle
*handle
,
3870 const char *key_name
,
3871 const char *value_name
,
3872 enum winreg_Type type
,
3877 struct spoolss_SetPrinterDataEx r
;
3879 r
.in
.handle
= handle
;
3880 r
.in
.key_name
= key_name
;
3881 r
.in
.value_name
= value_name
;
3884 r
.in
.offered
= offered
;
3886 torture_comment(tctx
, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
3887 r
.in
.key_name
, r
.in
.value_name
, str_regtype(r
.in
.type
), r
.in
.offered
);
3889 status
= dcerpc_spoolss_SetPrinterDataEx_r(b
, tctx
, &r
);
3891 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinterDataEx failed");
3892 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinterDataEx failed");
3897 static bool test_SetPrinterDataEx_matrix(struct torture_context
*tctx
,
3898 struct dcerpc_pipe
*p
,
3899 struct policy_handle
*handle
,
3900 const char *printername
,
3901 struct dcerpc_binding_handle
*winreg_handle
,
3902 struct policy_handle
*hive_handle
)
3904 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
3905 const char *value_name
= "dog";
3906 const char *keys
[] = {
3910 /* FIXME: not working with s3 atm. */
3911 "torturedataex_with_subkey\\subkey",
3912 "torturedataex_with_subkey\\subkey:0",
3913 "torturedataex_with_subkey\\subkey:1",
3914 "torturedataex_with_subkey\\subkey\\subsubkey",
3915 "torturedataex_with_subkey\\subkey\\subsubkey:0",
3916 "torturedataex_with_subkey\\subkey\\subsubkey:1",
3920 /* FIXME: not working with s3 atm. */
3927 enum winreg_Type types
[] = {
3933 const char *str
= "abcdefghijklmnopqrstuvwxzy";
3937 for (i
=0; i
< ARRAY_SIZE(keys
); i
++) {
3938 for (t
=0; t
< ARRAY_SIZE(types
); t
++) {
3939 for (s
=0; s
< strlen(str
); s
++) {
3943 enum winreg_Type type
;
3944 const char *string
= talloc_strndup(tctx
, str
, s
);
3945 DATA_BLOB blob
= data_blob_string_const(string
);
3946 const char **subkeys
;
3949 uint32_t needed
, offered
= 0;
3951 struct spoolss_PrinterEnumValues
*einfo
;
3953 if (types
[t
] == REG_DWORD
) {
3957 if (torture_setting_bool(tctx
, "samba3", false)) {
3958 if ((types
[t
] == REG_MULTI_SZ
) && s
== 0) {
3959 torture_warning(tctx
, "samba3 does not handle 4 byte emtpy REG_MULTI_SZ buffers");
3967 offered
= blob
.length
;
3970 data
= data_blob_talloc(tctx
, NULL
, 4);
3971 SIVAL(data
.data
, 0, 0x12345678);
3975 torture_assert(tctx
,
3976 reg_string_to_val(tctx
, lp_iconv_convenience(tctx
->lp_ctx
),
3977 "REG_SZ", string
, &type
, &data
), "");
3978 offered
= data
.length
;
3979 /*strlen_m_term(data.string)*2;*/
3982 torture_assert(tctx
,
3983 reg_string_to_val(tctx
, lp_iconv_convenience(tctx
->lp_ctx
),
3984 "REG_SZ", string
, &type
, &data
), "");
3985 torture_assert(tctx
, data_blob_realloc(tctx
, &data
, data
.length
+ 2), "");
3986 memset(&data
.data
[data
.length
- 2], '\0', 2);
3987 offered
= data
.length
;
3990 torture_fail(tctx
, talloc_asprintf(tctx
, "type %d untested\n", types
[t
]));
3993 torture_assert(tctx
,
3994 test_SetPrinterDataEx(tctx
, b
, handle
, keys
[i
], value_name
, types
[t
], data
.data
, offered
),
3995 "failed to call SetPrinterDataEx");
3997 torture_assert(tctx
,
3998 test_GetPrinterDataEx(tctx
, p
, handle
, keys
[i
], value_name
, &type
, &data_out
, &needed
),
3999 "failed to call GetPrinterDataEx");
4001 torture_assert(tctx
,
4002 test_EnumPrinterDataEx(tctx
, b
, handle
, keys
[i
], &ecount
, &einfo
),
4003 "failed to call EnumPrinterDataEx");
4005 torture_assert_int_equal(tctx
, types
[t
], type
, "type mismatch");
4006 torture_assert_int_equal(tctx
, needed
, offered
, "size mismatch");
4007 torture_assert_mem_equal(tctx
, data_out
, data
.data
, offered
, "buffer mismatch");
4009 torture_assert_int_equal(tctx
, ecount
, 1, "unexpected enum count");
4010 torture_assert_str_equal(tctx
, einfo
[0].value_name
, value_name
, "value_name mismatch");
4011 torture_assert_int_equal(tctx
, einfo
[0].value_name_len
, strlen_m_term(value_name
)*2, "unexpected value_name_len");
4012 torture_assert_int_equal(tctx
, einfo
[0].type
, types
[t
], "type mismatch");
4013 torture_assert_int_equal(tctx
, einfo
[0].data_length
, offered
, "size mismatch");
4014 if (einfo
[0].data_length
> 0) {
4015 torture_assert_mem_equal(tctx
, einfo
[0].data
->data
, data
.data
, offered
, "buffer mismatch");
4018 if (winreg_handle
&& hive_handle
) {
4019 enum winreg_Type w_type
;
4024 torture_assert(tctx
,
4025 test_winreg_query_printerdata(tctx
, winreg_handle
, hive_handle
,
4026 printername
, keys
[i
], value_name
,
4027 &w_type
, &w_size
, &w_length
, &w_data
), "");
4029 torture_assert_int_equal(tctx
, w_type
, types
[t
], "winreg type mismatch");
4030 torture_assert_int_equal(tctx
, w_size
, offered
, "winreg size mismatch");
4031 torture_assert_int_equal(tctx
, w_length
, offered
, "winreg length mismatch");
4032 torture_assert_mem_equal(tctx
, w_data
, data
.data
, offered
, "winreg buffer mismatch");
4035 key
= talloc_strdup(tctx
, keys
[i
]);
4037 if (!test_DeletePrinterDataEx(tctx
, b
, handle
, keys
[i
], value_name
)) {
4041 c
= strchr(key
, '\\');
4045 /* we have subkeys */
4049 if (!test_EnumPrinterKey(tctx
, b
, handle
, key
, &subkeys
)) {
4053 for (k
=0; subkeys
&& subkeys
[k
]; k
++) {
4055 const char *current_key
= talloc_asprintf(tctx
, "%s\\%s", key
, subkeys
[k
]);
4057 if (!test_DeletePrinterKey(tctx
, b
, handle
, current_key
)) {
4062 if (!test_DeletePrinterKey(tctx
, b
, handle
, key
)) {
4067 if (!test_DeletePrinterKey(tctx
, b
, handle
, key
)) {
4078 static bool test_PrinterData_winreg(struct torture_context
*tctx
,
4079 struct dcerpc_pipe
*p
,
4080 struct policy_handle
*handle
,
4081 const char *printer_name
)
4083 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4084 struct dcerpc_pipe
*p2
;
4086 struct policy_handle hive_handle
;
4087 struct dcerpc_binding_handle
*b2
;
4089 torture_assert_ntstatus_ok(tctx
,
4090 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
4091 "could not open winreg pipe");
4092 b2
= p2
->binding_handle
;
4094 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
4096 ret
&= test_SetPrinterData_matrix(tctx
, b
, handle
, printer_name
, b2
, &hive_handle
);
4097 ret
&= test_SetPrinterDataEx_matrix(tctx
, p
, handle
, printer_name
, b2
, &hive_handle
);
4099 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
4106 static bool test_Forms_winreg(struct torture_context
*tctx
,
4107 struct dcerpc_binding_handle
*b
,
4108 struct policy_handle
*handle
,
4110 const char *printer_name
)
4112 struct dcerpc_pipe
*p2
;
4114 struct policy_handle hive_handle
;
4115 struct dcerpc_binding_handle
*b2
;
4117 torture_assert_ntstatus_ok(tctx
,
4118 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
4119 "could not open winreg pipe");
4120 b2
= p2
->binding_handle
;
4122 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
4124 ret
= test_Forms(tctx
, b
, handle
, print_server
, printer_name
, b2
, &hive_handle
);
4126 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
4133 static bool test_GetChangeID_PrinterData(struct torture_context
*tctx
,
4134 struct dcerpc_binding_handle
*b
,
4135 struct policy_handle
*handle
,
4136 uint32_t *change_id
)
4138 enum winreg_Type type
;
4142 torture_assert(tctx
,
4143 test_GetPrinterData(tctx
, b
, handle
, "ChangeID", &type
, &data
, &needed
),
4144 "failed to call GetPrinterData");
4146 torture_assert(tctx
, type
== REG_DWORD
, "unexpected type");
4147 torture_assert_int_equal(tctx
, needed
, 4, "unexpected size");
4149 *change_id
= IVAL(data
, 0);
4154 static bool test_GetChangeID_PrinterDataEx(struct torture_context
*tctx
,
4155 struct dcerpc_pipe
*p
,
4156 struct policy_handle
*handle
,
4157 uint32_t *change_id
)
4159 enum winreg_Type type
;
4163 torture_assert(tctx
,
4164 test_GetPrinterDataEx(tctx
, p
, handle
, "PrinterDriverData", "ChangeID", &type
, &data
, &needed
),
4165 "failed to call GetPrinterData");
4167 torture_assert(tctx
, type
== REG_DWORD
, "unexpected type");
4168 torture_assert_int_equal(tctx
, needed
, 4, "unexpected size");
4170 *change_id
= IVAL(data
, 0);
4175 static bool test_GetChangeID_PrinterInfo(struct torture_context
*tctx
,
4176 struct dcerpc_binding_handle
*b
,
4177 struct policy_handle
*handle
,
4178 uint32_t *change_id
)
4180 union spoolss_PrinterInfo info
;
4182 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 0, &info
),
4183 "failed to query Printer level 0");
4185 *change_id
= info
.info0
.change_id
;
4190 static bool test_ChangeID(struct torture_context
*tctx
,
4191 struct dcerpc_pipe
*p
,
4192 struct policy_handle
*handle
)
4194 uint32_t change_id
, change_id_ex
, change_id_info
;
4195 uint32_t change_id2
, change_id_ex2
, change_id_info2
;
4196 union spoolss_PrinterInfo info
;
4197 const char *comment
;
4198 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4200 torture_comment(tctx
, "Testing ChangeID: id change test #1\n");
4202 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id
),
4203 "failed to query for ChangeID");
4204 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex
),
4205 "failed to query for ChangeID");
4206 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info
),
4207 "failed to query for ChangeID");
4209 torture_assert_int_equal(tctx
, change_id
, change_id_ex
,
4210 "change_ids should all be equal");
4211 torture_assert_int_equal(tctx
, change_id_ex
, change_id_info
,
4212 "change_ids should all be equal");
4215 torture_comment(tctx
, "Testing ChangeID: id change test #2\n");
4217 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id
),
4218 "failed to query for ChangeID");
4219 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
4220 "failed to query Printer level 2");
4221 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex
),
4222 "failed to query for ChangeID");
4223 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info
),
4224 "failed to query for ChangeID");
4225 torture_assert_int_equal(tctx
, change_id
, change_id_ex
,
4226 "change_id should not have changed");
4227 torture_assert_int_equal(tctx
, change_id_ex
, change_id_info
,
4228 "change_id should not have changed");
4231 torture_comment(tctx
, "Testing ChangeID: id change test #3\n");
4233 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id
),
4234 "failed to query for ChangeID");
4235 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex
),
4236 "failed to query for ChangeID");
4237 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info
),
4238 "failed to query for ChangeID");
4239 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
4240 "failed to query Printer level 2");
4241 comment
= talloc_strdup(tctx
, info
.info2
.comment
);
4244 struct spoolss_SetPrinterInfoCtr info_ctr
;
4245 struct spoolss_DevmodeContainer devmode_ctr
;
4246 struct sec_desc_buf secdesc_ctr
;
4247 union spoolss_SetPrinterInfo sinfo
;
4249 ZERO_STRUCT(info_ctr
);
4250 ZERO_STRUCT(devmode_ctr
);
4251 ZERO_STRUCT(secdesc_ctr
);
4254 torture_assert(tctx
, PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
4255 sinfo
.info2
->comment
= "torture_comment";
4258 info_ctr
.info
= sinfo
;
4260 torture_assert(tctx
, test_SetPrinter(tctx
, b
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0),
4261 "failed to call SetPrinter");
4263 sinfo
.info2
->comment
= comment
;
4265 torture_assert(tctx
, test_SetPrinter(tctx
, b
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0),
4266 "failed to call SetPrinter");
4270 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id2
),
4271 "failed to query for ChangeID");
4272 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex2
),
4273 "failed to query for ChangeID");
4274 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info2
),
4275 "failed to query for ChangeID");
4277 torture_assert_int_equal(tctx
, change_id2
, change_id_ex2
,
4278 "change_ids should all be equal");
4279 torture_assert_int_equal(tctx
, change_id_ex2
, change_id_info2
,
4280 "change_ids should all be equal");
4282 torture_assert(tctx
, (change_id
< change_id2
),
4283 talloc_asprintf(tctx
, "change_id %d needs to be larger than change_id %d",
4284 change_id2
, change_id
));
4285 torture_assert(tctx
, (change_id_ex
< change_id_ex2
),
4286 talloc_asprintf(tctx
, "change_id %d needs to be larger than change_id %d",
4287 change_id_ex2
, change_id_ex
));
4288 torture_assert(tctx
, (change_id_info
< change_id_info2
),
4289 talloc_asprintf(tctx
, "change_id %d needs to be larger than change_id %d",
4290 change_id_info2
, change_id_info
));
4292 torture_comment(tctx
, "ChangeID tests succeeded\n\n");
4297 static bool test_SecondaryClosePrinter(struct torture_context
*tctx
,
4298 struct dcerpc_pipe
*p
,
4299 struct policy_handle
*handle
)
4302 struct dcerpc_binding
*b
;
4303 struct dcerpc_pipe
*p2
;
4304 struct spoolss_ClosePrinter cp
;
4306 /* only makes sense on SMB */
4307 if (p
->conn
->transport
.transport
!= NCACN_NP
) {
4311 torture_comment(tctx
, "testing close on secondary pipe\n");
4313 status
= dcerpc_parse_binding(tctx
, p
->conn
->binding_string
, &b
);
4314 torture_assert_ntstatus_ok(tctx
, status
, "Failed to parse dcerpc binding");
4316 status
= dcerpc_secondary_connection(p
, &p2
, b
);
4317 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create secondary connection");
4319 status
= dcerpc_bind_auth_none(p2
, &ndr_table_spoolss
);
4320 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create bind on secondary connection");
4322 cp
.in
.handle
= handle
;
4323 cp
.out
.handle
= handle
;
4325 status
= dcerpc_spoolss_ClosePrinter_r(p2
->binding_handle
, tctx
, &cp
);
4326 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_NET_WRITE_FAULT
,
4327 "ERROR: Allowed close on secondary connection");
4329 torture_assert_int_equal(tctx
, p2
->last_fault_code
, DCERPC_FAULT_CONTEXT_MISMATCH
,
4330 "Unexpected fault code");
4337 static bool test_OpenPrinter_badname(struct torture_context
*tctx
,
4338 struct dcerpc_binding_handle
*b
, const char *name
)
4341 struct spoolss_OpenPrinter op
;
4342 struct spoolss_OpenPrinterEx opEx
;
4343 struct policy_handle handle
;
4346 op
.in
.printername
= name
;
4347 op
.in
.datatype
= NULL
;
4348 op
.in
.devmode_ctr
.devmode
= NULL
;
4349 op
.in
.access_mask
= 0;
4350 op
.out
.handle
= &handle
;
4352 torture_comment(tctx
, "Testing OpenPrinter(%s) with bad name\n", op
.in
.printername
);
4354 status
= dcerpc_spoolss_OpenPrinter_r(b
, tctx
, &op
);
4355 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
4356 torture_assert_werr_equal(tctx
, op
.out
.result
, WERR_INVALID_PRINTER_NAME
,
4357 "unexpected result");
4359 if (W_ERROR_IS_OK(op
.out
.result
)) {
4360 ret
&=test_ClosePrinter(tctx
, b
, &handle
);
4363 opEx
.in
.printername
= name
;
4364 opEx
.in
.datatype
= NULL
;
4365 opEx
.in
.devmode_ctr
.devmode
= NULL
;
4366 opEx
.in
.access_mask
= 0;
4368 opEx
.in
.userlevel
.level1
= NULL
;
4369 opEx
.out
.handle
= &handle
;
4371 torture_comment(tctx
, "Testing OpenPrinterEx(%s) with bad name\n", opEx
.in
.printername
);
4373 status
= dcerpc_spoolss_OpenPrinterEx_r(b
, tctx
, &opEx
);
4374 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinterEx failed");
4375 torture_assert_werr_equal(tctx
, opEx
.out
.result
, WERR_INVALID_PARAM
,
4376 "unexpected result");
4378 if (W_ERROR_IS_OK(opEx
.out
.result
)) {
4379 ret
&=test_ClosePrinter(tctx
, b
, &handle
);
4385 static bool test_OpenPrinter(struct torture_context
*tctx
,
4386 struct dcerpc_pipe
*p
,
4388 const char *environment
)
4391 struct spoolss_OpenPrinter r
;
4392 struct policy_handle handle
;
4394 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4396 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s\\%s", dcerpc_server_name(p
), name
);
4397 r
.in
.datatype
= NULL
;
4398 r
.in
.devmode_ctr
.devmode
= NULL
;
4399 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4400 r
.out
.handle
= &handle
;
4402 torture_comment(tctx
, "Testing OpenPrinter(%s)\n", r
.in
.printername
);
4404 status
= dcerpc_spoolss_OpenPrinter_r(b
, tctx
, &r
);
4406 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
4408 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenPrinter failed");
4410 if (!test_GetPrinter(tctx
, b
, &handle
, environment
)) {
4414 if (!torture_setting_bool(tctx
, "samba3", false)) {
4415 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
4420 if (!test_ClosePrinter(tctx
, b
, &handle
)) {
4427 static bool call_OpenPrinterEx(struct torture_context
*tctx
,
4428 struct dcerpc_pipe
*p
,
4430 struct spoolss_DeviceMode
*devmode
,
4431 struct policy_handle
*handle
)
4433 struct spoolss_OpenPrinterEx r
;
4434 struct spoolss_UserLevel1 userlevel1
;
4436 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4438 if (name
&& name
[0]) {
4439 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s\\%s",
4440 dcerpc_server_name(p
), name
);
4442 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s",
4443 dcerpc_server_name(p
));
4446 r
.in
.datatype
= NULL
;
4447 r
.in
.devmode_ctr
.devmode
= devmode
;
4448 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4450 r
.in
.userlevel
.level1
= &userlevel1
;
4451 r
.out
.handle
= handle
;
4453 userlevel1
.size
= 1234;
4454 userlevel1
.client
= "hello";
4455 userlevel1
.user
= "spottyfoot!";
4456 userlevel1
.build
= 1;
4457 userlevel1
.major
= 2;
4458 userlevel1
.minor
= 3;
4459 userlevel1
.processor
= 4;
4461 torture_comment(tctx
, "Testing OpenPrinterEx(%s)\n", r
.in
.printername
);
4463 status
= dcerpc_spoolss_OpenPrinterEx_r(b
, tctx
, &r
);
4465 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinterEx failed");
4467 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenPrinterEx failed");
4472 static bool test_printer_rename(struct torture_context
*tctx
,
4473 struct dcerpc_pipe
*p
,
4474 struct policy_handle
*handle
,
4478 union spoolss_PrinterInfo info
;
4479 union spoolss_SetPrinterInfo sinfo
;
4480 struct spoolss_SetPrinterInfoCtr info_ctr
;
4481 struct spoolss_DevmodeContainer devmode_ctr
;
4482 struct sec_desc_buf secdesc_ctr
;
4483 const char *printer_name
;
4484 const char *printer_name_orig
;
4485 const char *printer_name_new
= "SAMBA smbtorture Test Printer (Copy 2)";
4486 struct policy_handle new_handle
;
4488 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4490 ZERO_STRUCT(devmode_ctr
);
4491 ZERO_STRUCT(secdesc_ctr
);
4493 torture_comment(tctx
, "Testing Printer rename operations\n");
4495 torture_assert(tctx
,
4496 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
4497 "failed to call GetPrinter level 2");
4499 printer_name_orig
= talloc_strdup(tctx
, info
.info2
.printername
);
4501 q
= strrchr(info
.info2
.printername
, '\\');
4503 torture_warning(tctx
,
4504 "server returns printername %s incl. servername although we did not set servername", info
.info2
.printername
);
4507 torture_assert(tctx
,
4508 PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
4510 sinfo
.info2
->printername
= printer_name_new
;
4513 info_ctr
.info
= sinfo
;
4515 torture_assert(tctx
,
4516 test_SetPrinter(tctx
, b
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0),
4517 "failed to call SetPrinter level 2");
4519 torture_assert(tctx
,
4520 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
4521 "failed to call GetPrinter level 2");
4523 printer_name
= talloc_strdup(tctx
, info
.info2
.printername
);
4525 q
= strrchr(info
.info2
.printername
, '\\');
4527 torture_warning(tctx
,
4528 "server returns printername %s incl. servername although we did not set servername", info
.info2
.printername
);
4533 torture_assert_str_equal(tctx
, printer_name
, printer_name_new
,
4534 "new printer name was not set");
4536 /* samba currently cannot fully rename printers */
4537 if (!torture_setting_bool(tctx
, "samba3", false)) {
4538 torture_assert(tctx
,
4539 test_OpenPrinter_badname(tctx
, b
, printer_name_orig
),
4540 "still can open printer with oldname after rename");
4542 torture_warning(tctx
, "*not* checking for open with oldname after rename for samba3");
4545 torture_assert(tctx
,
4546 call_OpenPrinterEx(tctx
, p
, printer_name_new
, NULL
, &new_handle
),
4547 "failed to open printer with new name");
4549 torture_assert(tctx
,
4550 test_GetPrinter_level(tctx
, b
, &new_handle
, 2, &info
),
4551 "failed to call GetPrinter level 2");
4553 /* FIXME: we openend with servername! */
4554 printer_name
= talloc_asprintf(tctx
, "\\\\%s\\%s",
4555 dcerpc_server_name(p
), printer_name_new
);
4557 torture_assert_str_equal(tctx
, info
.info2
.printername
, printer_name
,
4558 "new printer name was not set");
4560 torture_assert(tctx
,
4561 test_ClosePrinter(tctx
, b
, &new_handle
),
4562 "failed to close printer");
4564 torture_comment(tctx
, "Printer rename operations test succeeded\n\n");
4570 static bool test_OpenPrinterEx(struct torture_context
*tctx
,
4571 struct dcerpc_pipe
*p
,
4573 const char *environment
)
4575 struct policy_handle handle
;
4577 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4579 if (!call_OpenPrinterEx(tctx
, p
, name
, NULL
, &handle
)) {
4583 if (!test_PrinterInfo_SD(tctx
, b
, &handle
)) {
4587 if (!test_GetPrinter(tctx
, b
, &handle
, environment
)) {
4591 if (!test_EnumForms_all(tctx
, b
, &handle
, false)) {
4595 if (!test_Forms(tctx
, b
, &handle
, false, name
, NULL
, NULL
)) {
4599 if (!test_Forms_winreg(tctx
, b
, &handle
, false, name
)) {
4603 if (!test_EnumPrinterData_all(tctx
, p
, &handle
)) {
4607 if (!test_EnumPrinterDataEx(tctx
, b
, &handle
, "PrinterDriverData", NULL
, NULL
)) {
4611 if (!test_EnumPrinterData_consistency(tctx
, p
, &handle
)) {
4615 if (!test_printer_keys(tctx
, b
, &handle
)) {
4619 if (!test_PausePrinter(tctx
, b
, &handle
)) {
4623 if (!test_DoPrintTest(tctx
, b
, &handle
)) {
4627 if (!test_ResumePrinter(tctx
, b
, &handle
)) {
4631 if (!test_SetPrinterData_matrix(tctx
, b
, &handle
, name
, NULL
, NULL
)) {
4635 if (!test_SetPrinterDataEx_matrix(tctx
, p
, &handle
, name
, NULL
, NULL
)) {
4639 if (!torture_setting_bool(tctx
, "samba3", false)) {
4640 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
4645 if (!test_ClosePrinter(tctx
, b
, &handle
)) {
4652 static bool test_EnumPrinters_old(struct torture_context
*tctx
,
4653 struct dcerpc_pipe
*p
,
4654 const char *environment
)
4656 struct spoolss_EnumPrinters r
;
4658 uint16_t levels
[] = {1, 2, 4, 5};
4661 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4663 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
4664 union spoolss_PrinterInfo
*info
;
4669 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
4671 r
.in
.level
= levels
[i
];
4674 r
.out
.needed
= &needed
;
4675 r
.out
.count
= &count
;
4678 torture_comment(tctx
, "Testing EnumPrinters level %u\n", r
.in
.level
);
4680 status
= dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &r
);
4681 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
4683 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
4684 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
4685 data_blob_clear(&blob
);
4686 r
.in
.buffer
= &blob
;
4687 r
.in
.offered
= needed
;
4688 status
= dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &r
);
4691 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
4693 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
4695 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
4698 torture_comment(tctx
, "No printers returned\n");
4702 for (j
=0;j
<count
;j
++) {
4703 if (r
.in
.level
== 1) {
4704 char *unc
= talloc_strdup(tctx
, info
[j
].info1
.name
);
4707 if (unc
[0] == '\\' && unc
[1] == '\\') {
4710 slash
= strchr(unc
, '\\');
4715 if (!test_OpenPrinter(tctx
, p
, name
, environment
)) {
4718 if (!test_OpenPrinterEx(tctx
, p
, name
, environment
)) {
4728 static bool test_GetPrinterDriver(struct torture_context
*tctx
,
4729 struct dcerpc_binding_handle
*b
,
4730 struct policy_handle
*handle
,
4731 const char *driver_name
)
4733 struct spoolss_GetPrinterDriver r
;
4736 r
.in
.handle
= handle
;
4737 r
.in
.architecture
= "W32X86";
4741 r
.out
.needed
= &needed
;
4743 torture_comment(tctx
, "Testing GetPrinterDriver level %d\n", r
.in
.level
);
4745 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver_r(b
, tctx
, &r
),
4746 "failed to call GetPrinterDriver");
4747 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
4748 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
4749 data_blob_clear(&blob
);
4750 r
.in
.buffer
= &blob
;
4751 r
.in
.offered
= needed
;
4752 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver_r(b
, tctx
, &r
),
4753 "failed to call GetPrinterDriver");
4756 torture_assert_werr_ok(tctx
, r
.out
.result
,
4757 "failed to call GetPrinterDriver");
4759 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
4764 static bool test_GetPrinterDriver2(struct torture_context
*tctx
,
4765 struct dcerpc_binding_handle
*b
,
4766 struct policy_handle
*handle
,
4767 const char *driver_name
,
4768 const char *architecture
)
4770 struct spoolss_GetPrinterDriver2 r
;
4771 uint16_t levels
[] = {1, 2, 3, 4, 5, 6, 8, 101 };
4773 uint32_t server_major_version
;
4774 uint32_t server_minor_version
;
4777 r
.in
.handle
= handle
;
4778 r
.in
.architecture
= architecture
;
4779 r
.in
.client_major_version
= 3;
4780 r
.in
.client_minor_version
= 0;
4781 r
.out
.needed
= &needed
;
4782 r
.out
.server_major_version
= &server_major_version
;
4783 r
.out
.server_minor_version
= &server_minor_version
;
4785 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
4789 r
.in
.level
= levels
[i
];
4791 torture_comment(tctx
, "Testing GetPrinterDriver2(%s) level %d\n",
4792 driver_name
, r
.in
.level
);
4794 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver2_r(b
, tctx
, &r
),
4795 "failed to call GetPrinterDriver2");
4796 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
4797 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
4798 data_blob_clear(&blob
);
4799 r
.in
.buffer
= &blob
;
4800 r
.in
.offered
= needed
;
4801 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver2_r(b
, tctx
, &r
),
4802 "failed to call GetPrinterDriver2");
4805 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INVALID_LEVEL
)) {
4806 switch (r
.in
.level
) {
4815 torture_assert_werr_ok(tctx
, r
.out
.result
,
4816 "failed to call GetPrinterDriver2");
4818 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
4824 static bool test_EnumPrinterDrivers_old(struct torture_context
*tctx
,
4825 struct dcerpc_pipe
*p
,
4826 const char *environment
)
4828 struct spoolss_EnumPrinterDrivers r
;
4830 uint16_t levels
[] = {1, 2, 3, 4, 5, 6};
4832 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4834 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
4838 union spoolss_DriverInfo
*info
;
4840 r
.in
.server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
4841 r
.in
.environment
= environment
;
4842 r
.in
.level
= levels
[i
];
4845 r
.out
.needed
= &needed
;
4846 r
.out
.count
= &count
;
4849 torture_comment(tctx
, "Testing EnumPrinterDrivers level %u\n", r
.in
.level
);
4851 status
= dcerpc_spoolss_EnumPrinterDrivers_r(b
, tctx
, &r
);
4853 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterDrivers failed");
4855 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
4856 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
4857 data_blob_clear(&blob
);
4858 r
.in
.buffer
= &blob
;
4859 r
.in
.offered
= needed
;
4860 status
= dcerpc_spoolss_EnumPrinterDrivers_r(b
, tctx
, &r
);
4863 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterDrivers failed");
4865 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDrivers failed");
4868 torture_comment(tctx
, "No printer drivers returned\n");
4872 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
4878 static bool test_DeletePrinter(struct torture_context
*tctx
,
4879 struct dcerpc_binding_handle
*b
,
4880 struct policy_handle
*handle
)
4882 struct spoolss_DeletePrinter r
;
4884 torture_comment(tctx
, "Testing DeletePrinter\n");
4886 r
.in
.handle
= handle
;
4888 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_DeletePrinter_r(b
, tctx
, &r
),
4889 "failed to delete printer");
4890 torture_assert_werr_ok(tctx
, r
.out
.result
,
4891 "failed to delete printer");
4896 static bool test_EnumPrinters_findname(struct torture_context
*tctx
,
4897 struct dcerpc_binding_handle
*b
,
4903 struct spoolss_EnumPrinters e
;
4905 union spoolss_PrinterInfo
*info
;
4916 e
.out
.count
= &count
;
4918 e
.out
.needed
= &needed
;
4920 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &e
),
4921 "failed to enum printers");
4923 if (W_ERROR_EQUAL(e
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
4924 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
4925 data_blob_clear(&blob
);
4926 e
.in
.buffer
= &blob
;
4927 e
.in
.offered
= needed
;
4929 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &e
),
4930 "failed to enum printers");
4933 torture_assert_werr_ok(tctx
, e
.out
.result
,
4934 "failed to enum printers");
4936 for (i
=0; i
< count
; i
++) {
4938 const char *current
= NULL
;
4943 current
= info
[i
].info1
.name
;
4947 if (strequal(current
, name
)) {
4952 q
= strrchr(current
, '\\');
4955 torture_warning(tctx
,
4956 "server returns printername %s incl. servername although we did not set servername", current
);
4959 if (strequal(q
, name
)) {
4969 static bool test_AddPrinter_wellknown(struct torture_context
*tctx
,
4970 struct dcerpc_pipe
*p
,
4971 const char *printername
,
4975 struct spoolss_AddPrinter r
;
4976 struct spoolss_AddPrinterEx rex
;
4977 struct spoolss_SetPrinterInfoCtr info_ctr
;
4978 struct spoolss_SetPrinterInfo1 info1
;
4979 struct spoolss_DevmodeContainer devmode_ctr
;
4980 struct sec_desc_buf secdesc_ctr
;
4981 struct spoolss_UserLevelCtr userlevel_ctr
;
4982 struct policy_handle handle
;
4984 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4986 ZERO_STRUCT(devmode_ctr
);
4987 ZERO_STRUCT(secdesc_ctr
);
4988 ZERO_STRUCT(userlevel_ctr
);
4991 torture_comment(tctx
, "Testing AddPrinter%s level 1\n", ex
? "Ex":"");
4993 /* try to add printer to wellknown printer list (level 1) */
4995 userlevel_ctr
.level
= 1;
4997 info_ctr
.info
.info1
= &info1
;
5000 rex
.in
.server
= NULL
;
5001 rex
.in
.info_ctr
= &info_ctr
;
5002 rex
.in
.devmode_ctr
= &devmode_ctr
;
5003 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
5004 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
5005 rex
.out
.handle
= &handle
;
5008 r
.in
.info_ctr
= &info_ctr
;
5009 r
.in
.devmode_ctr
= &devmode_ctr
;
5010 r
.in
.secdesc_ctr
= &secdesc_ctr
;
5011 r
.out
.handle
= &handle
;
5013 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
5014 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
5015 "failed to add printer");
5016 result
= ex
? rex
.out
.result
: r
.out
.result
;
5017 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
5018 "unexpected result code");
5020 info1
.name
= printername
;
5021 info1
.flags
= PRINTER_ATTRIBUTE_SHARED
;
5023 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
5024 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
5025 "failed to add printer");
5026 result
= ex
? rex
.out
.result
: r
.out
.result
;
5027 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
5028 "unexpected result code");
5030 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
5031 better do a real check to see the printer is really there */
5033 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, b
,
5034 PRINTER_ENUM_NETWORK
, 1,
5037 "failed to enum printers");
5039 torture_assert(tctx
, found
, "failed to find newly added printer");
5043 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
5044 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
5045 "failed to add printer");
5046 result
= ex
? rex
.out
.result
: r
.out
.result
;
5047 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
5048 "unexpected result code");
5050 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
5051 better do a real check to see the printer has really been removed
5052 from the well known printer list */
5056 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, b
,
5057 PRINTER_ENUM_NETWORK
, 1,
5060 "failed to enum printers");
5062 torture_assert(tctx
, !found
, "printer still in well known printer list");
5067 static bool test_AddPrinter_normal(struct torture_context
*tctx
,
5068 struct dcerpc_pipe
*p
,
5069 struct policy_handle
*handle_p
,
5070 const char *printername
,
5071 const char *drivername
,
5072 const char *portname
,
5076 struct spoolss_AddPrinter r
;
5077 struct spoolss_AddPrinterEx rex
;
5078 struct spoolss_SetPrinterInfoCtr info_ctr
;
5079 struct spoolss_SetPrinterInfo2 info2
;
5080 struct spoolss_DevmodeContainer devmode_ctr
;
5081 struct sec_desc_buf secdesc_ctr
;
5082 struct spoolss_UserLevelCtr userlevel_ctr
;
5083 struct policy_handle handle
;
5085 bool existing_printer_deleted
= false;
5086 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5088 ZERO_STRUCT(devmode_ctr
);
5089 ZERO_STRUCT(secdesc_ctr
);
5090 ZERO_STRUCT(userlevel_ctr
);
5092 torture_comment(tctx
, "Testing AddPrinter%s level 2\n", ex
? "Ex":"");
5094 userlevel_ctr
.level
= 1;
5096 rex
.in
.server
= NULL
;
5097 rex
.in
.info_ctr
= &info_ctr
;
5098 rex
.in
.devmode_ctr
= &devmode_ctr
;
5099 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
5100 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
5101 rex
.out
.handle
= &handle
;
5104 r
.in
.info_ctr
= &info_ctr
;
5105 r
.in
.devmode_ctr
= &devmode_ctr
;
5106 r
.in
.secdesc_ctr
= &secdesc_ctr
;
5107 r
.out
.handle
= &handle
;
5111 /* try to add printer to printer list (level 2) */
5115 info_ctr
.info
.info2
= &info2
;
5118 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
5119 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
5120 "failed to add printer");
5121 result
= ex
? rex
.out
.result
: r
.out
.result
;
5122 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
5123 "unexpected result code");
5125 info2
.printername
= printername
;
5127 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
5128 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
5129 "failed to add printer");
5130 result
= ex
? rex
.out
.result
: r
.out
.result
;
5132 if (W_ERROR_EQUAL(result
, WERR_PRINTER_ALREADY_EXISTS
)) {
5133 struct policy_handle printer_handle
;
5135 if (existing_printer_deleted
) {
5136 torture_fail(tctx
, "already deleted printer still existing?");
5139 torture_assert(tctx
, call_OpenPrinterEx(tctx
, p
, printername
, NULL
, &printer_handle
),
5140 "failed to open printer handle");
5142 torture_assert(tctx
, test_DeletePrinter(tctx
, b
, &printer_handle
),
5143 "failed to delete printer");
5145 torture_assert(tctx
, test_ClosePrinter(tctx
, b
, &printer_handle
),
5146 "failed to close server handle");
5148 existing_printer_deleted
= true;
5153 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PORT
,
5154 "unexpected result code");
5156 info2
.portname
= portname
;
5158 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
5159 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
5160 "failed to add printer");
5161 result
= ex
? rex
.out
.result
: r
.out
.result
;
5162 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTER_DRIVER
,
5163 "unexpected result code");
5165 info2
.drivername
= drivername
;
5167 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
5168 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
5169 "failed to add printer");
5170 result
= ex
? rex
.out
.result
: r
.out
.result
;
5172 /* w2k8r2 allows to add printer w/o defining printprocessor */
5174 if (!W_ERROR_IS_OK(result
)) {
5175 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTPROCESSOR
,
5176 "unexpected result code");
5178 info2
.printprocessor
= "winprint";
5180 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
5181 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
5182 "failed to add printer");
5183 result
= ex
? rex
.out
.result
: r
.out
.result
;
5184 torture_assert_werr_ok(tctx
, result
,
5185 "failed to add printer");
5190 /* we are paranoid, really check if the printer is there now */
5192 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, b
,
5193 PRINTER_ENUM_LOCAL
, 1,
5196 "failed to enum printers");
5197 torture_assert(tctx
, found
, "failed to find newly added printer");
5199 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
5200 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
5201 "failed to add printer");
5202 result
= ex
? rex
.out
.result
: r
.out
.result
;
5203 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
5204 "unexpected result code");
5209 static bool test_AddPrinterEx(struct torture_context
*tctx
,
5210 struct dcerpc_pipe
*p
,
5211 struct policy_handle
*handle_p
,
5212 const char *printername
,
5213 const char *drivername
,
5214 const char *portname
)
5218 if (!torture_setting_bool(tctx
, "samba3", false)) {
5219 if (!test_AddPrinter_wellknown(tctx
, p
, TORTURE_WELLKNOWN_PRINTER_EX
, true)) {
5220 torture_comment(tctx
, "failed to add printer to well known list\n");
5225 if (!test_AddPrinter_normal(tctx
, p
, handle_p
,
5226 printername
, drivername
, portname
,
5228 torture_comment(tctx
, "failed to add printer to printer list\n");
5235 static bool test_AddPrinter(struct torture_context
*tctx
,
5236 struct dcerpc_pipe
*p
,
5237 struct policy_handle
*handle_p
,
5238 const char *printername
,
5239 const char *drivername
,
5240 const char *portname
)
5244 if (!torture_setting_bool(tctx
, "samba3", false)) {
5245 if (!test_AddPrinter_wellknown(tctx
, p
, TORTURE_WELLKNOWN_PRINTER
, false)) {
5246 torture_comment(tctx
, "failed to add printer to well known list\n");
5251 if (!test_AddPrinter_normal(tctx
, p
, handle_p
,
5252 printername
, drivername
, portname
,
5254 torture_comment(tctx
, "failed to add printer to printer list\n");
5261 static bool test_printer_info(struct torture_context
*tctx
,
5262 struct dcerpc_binding_handle
*b
,
5263 struct policy_handle
*handle
)
5267 if (torture_setting_bool(tctx
, "samba3", false)) {
5268 torture_skip(tctx
, "skipping printer info cross tests against samba 3");
5271 if (!test_PrinterInfo(tctx
, b
, handle
)) {
5275 if (!test_SetPrinter_errors(tctx
, b
, handle
)) {
5282 static bool test_EnumPrinterKey(struct torture_context
*tctx
,
5283 struct dcerpc_binding_handle
*b
,
5284 struct policy_handle
*handle
,
5285 const char *key_name
,
5286 const char ***array
)
5288 struct spoolss_EnumPrinterKey r
;
5289 uint32_t needed
= 0;
5290 union spoolss_KeyNames key_buffer
;
5291 int32_t offered
[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
5295 r
.in
.handle
= handle
;
5296 r
.in
.key_name
= key_name
;
5297 r
.out
.key_buffer
= &key_buffer
;
5298 r
.out
.needed
= &needed
;
5299 r
.out
._ndr_size
= &_ndr_size
;
5301 for (i
=0; i
< ARRAY_SIZE(offered
); i
++) {
5303 if (offered
[i
] < 0 && needed
) {
5307 r
.in
.offered
= needed
+ offered
[i
];
5309 r
.in
.offered
= offered
[i
];
5312 ZERO_STRUCT(key_buffer
);
5314 torture_comment(tctx
, "Testing EnumPrinterKey(%s) with %d offered\n", r
.in
.key_name
, r
.in
.offered
);
5316 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterKey_r(b
, tctx
, &r
),
5317 "failed to call EnumPrinterKey");
5318 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
5320 torture_assert(tctx
, (_ndr_size
== r
.in
.offered
/2),
5321 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
5322 _ndr_size
, r
.in
.offered
/2));
5324 r
.in
.offered
= needed
;
5325 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterKey_r(b
, tctx
, &r
),
5326 "failed to call EnumPrinterKey");
5329 if (offered
[i
] > 0) {
5330 torture_assert_werr_ok(tctx
, r
.out
.result
,
5331 "failed to call EnumPrinterKey");
5334 torture_assert(tctx
, (_ndr_size
== r
.in
.offered
/2),
5335 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
5336 _ndr_size
, r
.in
.offered
/2));
5338 torture_assert(tctx
, (*r
.out
.needed
<= r
.in
.offered
),
5339 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r
.out
.needed
, r
.in
.offered
));
5341 torture_assert(tctx
, (*r
.out
.needed
<= _ndr_size
* 2),
5342 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r
.out
.needed
, _ndr_size
));
5344 if (key_buffer
.string_array
) {
5345 uint32_t calc_needed
= 0;
5347 for (s
=0; key_buffer
.string_array
[s
]; s
++) {
5348 calc_needed
+= strlen_m_term(key_buffer
.string_array
[s
])*2;
5350 if (!key_buffer
.string_array
[0]) {
5355 torture_assert_int_equal(tctx
, *r
.out
.needed
, calc_needed
,
5356 "EnumPrinterKey unexpected size");
5361 *array
= key_buffer
.string_array
;
5367 bool test_printer_keys(struct torture_context
*tctx
,
5368 struct dcerpc_binding_handle
*b
,
5369 struct policy_handle
*handle
)
5371 const char **key_array
= NULL
;
5374 torture_comment(tctx
, "Testing Printer Keys\n");
5376 torture_assert(tctx
, test_EnumPrinterKey(tctx
, b
, handle
, "", &key_array
),
5377 "failed to call test_EnumPrinterKey");
5379 for (i
=0; key_array
&& key_array
[i
]; i
++) {
5380 torture_assert(tctx
, test_EnumPrinterKey(tctx
, b
, handle
, key_array
[i
], NULL
),
5381 "failed to call test_EnumPrinterKey");
5383 for (i
=0; key_array
&& key_array
[i
]; i
++) {
5384 torture_assert(tctx
, test_EnumPrinterDataEx(tctx
, b
, handle
, key_array
[i
], NULL
, NULL
),
5385 "failed to call test_EnumPrinterDataEx");
5388 torture_comment(tctx
, "Printer Keys test succeeded\n\n");
5393 static bool test_one_printer(struct torture_context
*tctx
,
5394 struct dcerpc_pipe
*p
,
5395 struct policy_handle
*handle
,
5399 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5401 if (!test_PausePrinter(tctx
, b
, handle
)) {
5405 if (!test_DoPrintTest(tctx
, b
, handle
)) {
5409 if (!test_ResumePrinter(tctx
, b
, handle
)) {
5413 if (!test_printer_info(tctx
, b
, handle
)) {
5417 if (!test_PrinterInfo_SD(tctx
, b
, handle
)) {
5421 if (!test_PrinterInfo_DevMode(tctx
, p
, handle
, name
)) {
5425 if (!test_ChangeID(tctx
, p
, handle
)) {
5429 if (!test_printer_keys(tctx
, b
, handle
)) {
5433 if (!test_EnumPrinterData_consistency(tctx
, p
, handle
)) {
5437 if (!test_SetPrinterDataEx_matrix(tctx
, p
, handle
, name
, NULL
, NULL
)) {
5441 if (!test_PrinterData_winreg(tctx
, p
, handle
, name
)) {
5445 if (!test_printer_rename(tctx
, p
, handle
, name
)) {
5452 static bool test_printer(struct torture_context
*tctx
,
5453 struct dcerpc_pipe
*p
)
5456 struct policy_handle handle
[2];
5458 const char *drivername
= "Microsoft XPS Document Writer";
5459 const char *portname
= "LPT1:";
5460 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5462 /* test printer created via AddPrinter */
5464 if (!test_AddPrinter(tctx
, p
, &handle
[0], TORTURE_PRINTER
, drivername
, portname
)) {
5468 if (!test_one_printer(tctx
, p
, &handle
[0], TORTURE_PRINTER
)) {
5472 if (!test_DeletePrinter(tctx
, b
, &handle
[0])) {
5476 if (!test_EnumPrinters_findname(tctx
, b
, PRINTER_ENUM_LOCAL
, 1,
5477 TORTURE_PRINTER
, &found
)) {
5481 torture_assert(tctx
, !found
, "deleted printer still there");
5483 /* test printer created via AddPrinterEx */
5485 if (!test_AddPrinterEx(tctx
, p
, &handle
[1], TORTURE_PRINTER_EX
, drivername
, portname
)) {
5489 if (!test_one_printer(tctx
, p
, &handle
[1], TORTURE_PRINTER_EX
)) {
5493 if (!test_DeletePrinter(tctx
, b
, &handle
[1])) {
5497 if (!test_EnumPrinters_findname(tctx
, b
, PRINTER_ENUM_LOCAL
, 1,
5498 TORTURE_PRINTER_EX
, &found
)) {
5502 torture_assert(tctx
, !found
, "deleted printer still there");
5507 static bool test_architecture_buffer(struct torture_context
*tctx
,
5508 struct dcerpc_pipe
*p
)
5510 struct spoolss_OpenPrinterEx r
;
5511 struct spoolss_UserLevel1 u1
;
5512 struct policy_handle handle
;
5513 uint32_t architectures
[] = {
5514 PROCESSOR_ARCHITECTURE_INTEL
,
5515 PROCESSOR_ARCHITECTURE_IA64
,
5516 PROCESSOR_ARCHITECTURE_AMD64
5520 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5522 for (i
=0; i
< ARRAY_SIZE(architectures
); i
++) {
5524 torture_comment(tctx
, "Testing OpenPrinterEx with architecture %d\n", architectures
[i
]);
5532 u1
.processor
= architectures
[i
];
5534 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
5535 r
.in
.datatype
= NULL
;
5536 r
.in
.devmode_ctr
.devmode
= NULL
;
5537 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
5539 r
.in
.userlevel
.level1
= &u1
;
5540 r
.out
.handle
= &handle
;
5542 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_OpenPrinterEx_r(b
, tctx
, &r
), "");
5543 torture_assert_werr_ok(tctx
, r
.out
.result
, "");
5546 struct spoolss_EnumPrinters e
;
5548 union spoolss_PrinterInfo
*info
;
5550 e
.in
.flags
= PRINTER_ENUM_LOCAL
;
5555 e
.out
.count
= &count
;
5557 e
.out
.needed
= &needed
[i
];
5559 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &e
), "");
5561 torture_comment(tctx
, "needed was %d\n", needed
[i
]);
5565 torture_assert(tctx
, test_ClosePrinter(tctx
, b
, &handle
), "");
5568 for (i
=1; i
< ARRAY_SIZE(architectures
); i
++) {
5569 if (needed
[i
-1] != needed
[i
]) {
5571 talloc_asprintf(tctx
, "needed size %d for architecture %d != needed size %d for architecture %d\n",
5572 needed
[i
-1], architectures
[i
-1], needed
[i
], architectures
[i
]));
5579 bool torture_rpc_spoolss(struct torture_context
*torture
)
5582 struct dcerpc_pipe
*p
;
5583 struct dcerpc_binding_handle
*b
;
5585 struct test_spoolss_context
*ctx
;
5586 const char *environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
5588 status
= torture_rpc_connection(torture
, &p
, &ndr_table_spoolss
);
5589 if (!NT_STATUS_IS_OK(status
)) {
5592 b
= p
->binding_handle
;
5594 ctx
= talloc_zero(torture
, struct test_spoolss_context
);
5596 ret
&= test_OpenPrinter_server(torture
, p
, &ctx
->server_handle
);
5597 ret
&= test_GetPrinterData_list(torture
, p
, &ctx
->server_handle
, &environment
);
5598 ret
&= test_EnumForms_all(torture
, b
, &ctx
->server_handle
, true);
5599 ret
&= test_Forms(torture
, b
, &ctx
->server_handle
, true, NULL
, NULL
, NULL
);
5600 ret
&= test_Forms_winreg(torture
, b
, &ctx
->server_handle
, true, NULL
);
5601 ret
&= test_EnumPorts(torture
, b
, ctx
);
5602 ret
&= test_GetPrinterDriverDirectory(torture
, p
, environment
);
5603 ret
&= test_GetPrintProcessorDirectory(torture
, p
, environment
);
5604 ret
&= test_EnumPrinterDrivers(torture
, p
, ctx
, environment
);
5605 ret
&= test_EnumPrinterDrivers(torture
, p
, ctx
, SPOOLSS_ARCHITECTURE_ALL
);
5606 ret
&= test_EnumMonitors(torture
, b
, ctx
);
5607 ret
&= test_EnumPrintProcessors(torture
, b
, ctx
, environment
);
5608 ret
&= test_EnumPrintProcDataTypes(torture
, b
);
5609 ret
&= test_EnumPrinters(torture
, b
, ctx
);
5610 ret
&= test_OpenPrinter_badname(torture
, b
, "__INVALID_PRINTER__");
5611 ret
&= test_OpenPrinter_badname(torture
, b
, "\\\\__INVALID_HOST__");
5612 ret
&= test_OpenPrinter_badname(torture
, b
, "");
5613 ret
&= test_OpenPrinter_badname(torture
, b
, "\\\\\\");
5614 ret
&= test_OpenPrinter_badname(torture
, b
, "\\\\\\__INVALID_PRINTER__");
5615 ret
&= test_OpenPrinter_badname(torture
, b
, talloc_asprintf(torture
, "\\\\%s\\", dcerpc_server_name(p
)));
5616 ret
&= test_OpenPrinter_badname(torture
, b
,
5617 talloc_asprintf(torture
, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p
)));
5620 ret
&= test_AddPort(torture
, p
);
5621 ret
&= test_EnumPorts_old(torture
, p
);
5622 ret
&= test_EnumPrinters_old(torture
, p
, environment
);
5623 ret
&= test_EnumPrinterDrivers_old(torture
, p
, environment
);
5624 ret
&= test_architecture_buffer(torture
, p
);
5629 struct torture_suite
*torture_rpc_spoolss_printer(TALLOC_CTX
*mem_ctx
)
5631 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "SPOOLSS-PRINTER");
5633 struct torture_rpc_tcase
*tcase
= torture_suite_add_rpc_iface_tcase(suite
,
5634 "printer", &ndr_table_spoolss
);
5636 torture_rpc_tcase_add_test(tcase
, "printer", test_printer
);