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_PRINTER_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"
43 struct test_spoolss_context
{
44 /* print server handle */
45 struct policy_handle server_handle
;
48 uint32_t port_count
[3];
49 union spoolss_PortInfo
*ports
[3];
51 /* for EnumPrinterDrivers */
52 uint32_t driver_count
[8];
53 union spoolss_DriverInfo
*drivers
[8];
55 /* for EnumMonitors */
56 uint32_t monitor_count
[3];
57 union spoolss_MonitorInfo
*monitors
[3];
59 /* for EnumPrintProcessors */
60 uint32_t print_processor_count
[2];
61 union spoolss_PrintProcessorInfo
*print_processors
[2];
63 /* for EnumPrinters */
64 uint32_t printer_count
[6];
65 union spoolss_PrinterInfo
*printers
[6];
68 #define COMPARE_STRING(tctx, c,r,e) \
69 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
71 /* not every compiler supports __typeof__() */
73 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
74 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
75 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
77 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
78 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
82 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
85 #define COMPARE_UINT32(tctx, c, r, e) do {\
86 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
87 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
90 #define COMPARE_UINT64(tctx, c, r, e) do {\
91 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
92 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
96 #define COMPARE_NTTIME(tctx, c, r, e) do {\
97 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
98 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
101 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
103 if (!c.e && !r.e) { \
107 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
110 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
112 for (__i=0;c.e[__i] != NULL; __i++) { \
113 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
117 #define CHECK_ALIGN(size, n) do {\
119 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
120 size, n, size + n - (size % n));\
124 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
126 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, ic, needed, align) do { \
127 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
128 uint32_t size = ndr_size_##fn##_info(tctx, ic, level, count, info);\
129 uint32_t round_size = DO_ROUND(size, align);\
130 if (round_size != needed) {\
131 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
132 CHECK_ALIGN(size, align);\
137 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, ic, needed, align) do { \
138 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
139 uint32_t size = ndr_size_##fn##_info(tctx, ic, count, info);\
140 uint32_t round_size = DO_ROUND(size, align);\
141 if (round_size != needed) {\
142 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
143 CHECK_ALIGN(size, align);\
148 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, ic, needed, align) do { \
149 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
150 uint32_t size = ndr_size_##fn(info, level, ic, 0);\
151 uint32_t round_size = DO_ROUND(size, align);\
152 if (round_size != needed) {\
153 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
154 CHECK_ALIGN(size, align);\
159 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context
*tctx
,
160 const union spoolss_PrinterInfo
*i
,
162 union spoolss_SetPrinterInfo
*s
)
166 s
->info0
= talloc(tctx
, struct spoolss_SetPrinterInfo0
);
169 s
->info2
= talloc(tctx
, struct spoolss_SetPrinterInfo2
);
170 s
->info2
->servername
= i
->info2
.servername
;
171 s
->info2
->printername
= i
->info2
.printername
;
172 s
->info2
->sharename
= i
->info2
.sharename
;
173 s
->info2
->portname
= i
->info2
.portname
;
174 s
->info2
->drivername
= i
->info2
.drivername
;
175 s
->info2
->comment
= i
->info2
.comment
;
176 s
->info2
->location
= i
->info2
.location
;
177 s
->info2
->devmode_ptr
= 0;
178 s
->info2
->sepfile
= i
->info2
.sepfile
;
179 s
->info2
->printprocessor
= i
->info2
.printprocessor
;
180 s
->info2
->datatype
= i
->info2
.datatype
;
181 s
->info2
->parameters
= i
->info2
.parameters
;
182 s
->info2
->secdesc_ptr
= 0;
183 s
->info2
->attributes
= i
->info2
.attributes
;
184 s
->info2
->priority
= i
->info2
.priority
;
185 s
->info2
->defaultpriority
= i
->info2
.defaultpriority
;
186 s
->info2
->starttime
= i
->info2
.starttime
;
187 s
->info2
->untiltime
= i
->info2
.untiltime
;
188 s
->info2
->status
= i
->info2
.status
;
189 s
->info2
->cjobs
= i
->info2
.cjobs
;
190 s
->info2
->averageppm
= i
->info2
.averageppm
;
206 static bool test_OpenPrinter_server(struct torture_context
*tctx
,
207 struct dcerpc_pipe
*p
,
208 struct policy_handle
*server_handle
)
211 struct spoolss_OpenPrinter op
;
212 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
214 op
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
215 op
.in
.datatype
= NULL
;
216 op
.in
.devmode_ctr
.devmode
= NULL
;
217 op
.in
.access_mask
= 0;
218 op
.out
.handle
= server_handle
;
220 torture_comment(tctx
, "Testing OpenPrinter(%s)\n", op
.in
.printername
);
222 status
= dcerpc_spoolss_OpenPrinter_r(b
, tctx
, &op
);
223 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_OpenPrinter failed");
224 torture_assert_werr_ok(tctx
, op
.out
.result
, "dcerpc_spoolss_OpenPrinter failed");
229 static bool test_EnumPorts(struct torture_context
*tctx
,
230 struct dcerpc_binding_handle
*b
,
231 struct test_spoolss_context
*ctx
)
234 struct spoolss_EnumPorts r
;
235 uint16_t levels
[] = { 1, 2 };
238 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
239 int level
= levels
[i
];
243 union spoolss_PortInfo
*info
;
245 r
.in
.servername
= "";
249 r
.out
.needed
= &needed
;
250 r
.out
.count
= &count
;
253 torture_comment(tctx
, "Testing EnumPorts level %u\n", r
.in
.level
);
255 status
= dcerpc_spoolss_EnumPorts_r(b
, ctx
, &r
);
256 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPorts failed");
257 if (W_ERROR_IS_OK(r
.out
.result
)) {
258 /* TODO: do some more checks here */
261 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
262 "EnumPorts unexpected return code");
264 blob
= data_blob_talloc(ctx
, NULL
, needed
);
265 data_blob_clear(&blob
);
267 r
.in
.offered
= needed
;
269 status
= dcerpc_spoolss_EnumPorts_r(b
, ctx
, &r
);
270 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPorts failed");
272 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
274 torture_assert(tctx
, info
, "EnumPorts returned no info");
276 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
278 ctx
->port_count
[level
] = count
;
279 ctx
->ports
[level
] = info
;
282 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
283 int level
= levels
[i
];
284 int old_level
= levels
[i
-1];
285 torture_assert_int_equal(tctx
, ctx
->port_count
[level
], ctx
->port_count
[old_level
],
286 "EnumPorts invalid value");
288 /* if the array sizes are not the same we would maybe segfault in the following code */
290 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
291 int level
= levels
[i
];
292 for (j
=0;j
<ctx
->port_count
[level
];j
++) {
293 union spoolss_PortInfo
*cur
= &ctx
->ports
[level
][j
];
294 union spoolss_PortInfo
*ref
= &ctx
->ports
[2][j
];
297 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, port_name
);
300 /* level 2 is our reference, and it makes no sense to compare it to itself */
309 static bool test_GetPrintProcessorDirectory(struct torture_context
*tctx
,
310 struct dcerpc_pipe
*p
,
311 struct test_spoolss_context
*ctx
,
312 const char *environment
)
315 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
316 struct spoolss_GetPrintProcessorDirectory r
;
331 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
334 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
340 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
341 int level
= levels
[i
].level
;
344 r
.in
.server
= levels
[i
].server
;
345 r
.in
.environment
= environment
;
349 r
.out
.needed
= &needed
;
351 torture_comment(tctx
, "Testing GetPrintProcessorDirectory level %u\n", r
.in
.level
);
353 status
= dcerpc_spoolss_GetPrintProcessorDirectory_r(b
, ctx
, &r
);
354 torture_assert_ntstatus_ok(tctx
, status
,
355 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
356 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
357 "GetPrintProcessorDirectory unexpected return code");
359 blob
= data_blob_talloc(ctx
, NULL
, needed
);
360 data_blob_clear(&blob
);
362 r
.in
.offered
= needed
;
364 status
= dcerpc_spoolss_GetPrintProcessorDirectory_r(b
, ctx
, &r
);
365 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
367 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrintProcessorDirectory failed");
369 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 2);
376 static bool test_GetPrinterDriverDirectory(struct torture_context
*tctx
,
377 struct dcerpc_pipe
*p
,
378 struct test_spoolss_context
*ctx
,
379 const char *environment
)
382 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
383 struct spoolss_GetPrinterDriverDirectory r
;
398 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
401 .server
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
))
407 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
408 int level
= levels
[i
].level
;
411 r
.in
.server
= levels
[i
].server
;
412 r
.in
.environment
= environment
;
416 r
.out
.needed
= &needed
;
418 torture_comment(tctx
, "Testing GetPrinterDriverDirectory level %u\n", r
.in
.level
);
420 status
= dcerpc_spoolss_GetPrinterDriverDirectory_r(b
, ctx
, &r
);
421 torture_assert_ntstatus_ok(tctx
, status
,
422 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
423 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
424 "GetPrinterDriverDirectory unexpected return code");
426 blob
= data_blob_talloc(ctx
, NULL
, needed
);
427 data_blob_clear(&blob
);
429 r
.in
.offered
= needed
;
431 status
= dcerpc_spoolss_GetPrinterDriverDirectory_r(b
, ctx
, &r
);
432 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
434 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetPrinterDriverDirectory failed");
436 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 2);
442 static bool test_EnumPrinterDrivers(struct torture_context
*tctx
,
443 struct dcerpc_pipe
*p
,
444 struct test_spoolss_context
*ctx
,
445 const char *architecture
)
448 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
449 struct spoolss_EnumPrinterDrivers r
;
450 uint16_t levels
[] = { 1, 2, 3, 4, 5, 6, 8 };
453 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
454 int level
= levels
[i
];
458 union spoolss_DriverInfo
*info
;
460 /* FIXME: gd, come back and fix "" as server, and handle
461 * priority of returned error codes in torture test and samba 3
464 r
.in
.server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
465 r
.in
.environment
= architecture
;
469 r
.out
.needed
= &needed
;
470 r
.out
.count
= &count
;
473 torture_comment(tctx
, "Testing EnumPrinterDrivers level %u (%s)\n", r
.in
.level
, r
.in
.environment
);
475 status
= dcerpc_spoolss_EnumPrinterDrivers_r(b
, ctx
, &r
);
476 torture_assert_ntstatus_ok(tctx
, status
,
477 "dcerpc_spoolss_EnumPrinterDrivers failed");
478 if (W_ERROR_IS_OK(r
.out
.result
)) {
479 /* TODO: do some more checks here */
482 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
483 blob
= data_blob_talloc(ctx
, NULL
, needed
);
484 data_blob_clear(&blob
);
486 r
.in
.offered
= needed
;
488 status
= dcerpc_spoolss_EnumPrinterDrivers_r(b
, ctx
, &r
);
489 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrinterDrivers failed");
492 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDrivers failed");
494 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
496 ctx
->driver_count
[level
] = count
;
497 ctx
->drivers
[level
] = info
;
500 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
501 int level
= levels
[i
];
502 int old_level
= levels
[i
-1];
504 torture_assert_int_equal(tctx
, ctx
->driver_count
[level
], ctx
->driver_count
[old_level
],
505 "EnumPrinterDrivers invalid value");
508 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
509 int level
= levels
[i
];
511 for (j
=0;j
<ctx
->driver_count
[level
];j
++) {
512 union spoolss_DriverInfo
*cur
= &ctx
->drivers
[level
][j
];
513 union spoolss_DriverInfo
*ref
= &ctx
->drivers
[8][j
];
517 COMPARE_STRING(tctx
, cur
->info1
, ref
->info8
, driver_name
);
520 COMPARE_UINT32(tctx
, cur
->info2
, ref
->info8
, version
);
521 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, driver_name
);
522 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, architecture
);
523 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, driver_path
);
524 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, data_file
);
525 COMPARE_STRING(tctx
, cur
->info2
, ref
->info8
, config_file
);
528 COMPARE_UINT32(tctx
, cur
->info3
, ref
->info8
, version
);
529 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, driver_name
);
530 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, architecture
);
531 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, driver_path
);
532 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, data_file
);
533 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, config_file
);
534 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, help_file
);
535 COMPARE_STRING_ARRAY(tctx
, cur
->info3
, ref
->info8
, dependent_files
);
536 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, monitor_name
);
537 COMPARE_STRING(tctx
, cur
->info3
, ref
->info8
, default_datatype
);
540 COMPARE_UINT32(tctx
, cur
->info4
, ref
->info8
, version
);
541 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, driver_name
);
542 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, architecture
);
543 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, driver_path
);
544 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, data_file
);
545 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, config_file
);
546 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, help_file
);
547 COMPARE_STRING_ARRAY(tctx
, cur
->info4
, ref
->info8
, dependent_files
);
548 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, monitor_name
);
549 COMPARE_STRING(tctx
, cur
->info4
, ref
->info8
, default_datatype
);
550 COMPARE_STRING_ARRAY(tctx
, cur
->info4
, ref
->info8
, previous_names
);
553 COMPARE_UINT32(tctx
, cur
->info5
, ref
->info8
, version
);
554 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, driver_name
);
555 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, architecture
);
556 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, driver_path
);
557 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, data_file
);
558 COMPARE_STRING(tctx
, cur
->info5
, ref
->info8
, config_file
);
559 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
560 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
561 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
564 COMPARE_UINT32(tctx
, cur
->info6
, ref
->info8
, version
);
565 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, driver_name
);
566 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, architecture
);
567 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, driver_path
);
568 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, data_file
);
569 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, config_file
);
570 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, help_file
);
571 COMPARE_STRING_ARRAY(tctx
, cur
->info6
, ref
->info8
, dependent_files
);
572 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, monitor_name
);
573 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, default_datatype
);
574 COMPARE_STRING_ARRAY(tctx
, cur
->info6
, ref
->info8
, previous_names
);
575 COMPARE_NTTIME(tctx
, cur
->info6
, ref
->info8
, driver_date
);
576 COMPARE_UINT64(tctx
, cur
->info6
, ref
->info8
, driver_version
);
577 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, manufacturer_name
);
578 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, manufacturer_url
);
579 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, hardware_id
);
580 COMPARE_STRING(tctx
, cur
->info6
, ref
->info8
, provider
);
583 /* level 8 is our reference, and it makes no sense to compare it to itself */
592 static bool test_EnumMonitors(struct torture_context
*tctx
,
593 struct dcerpc_binding_handle
*b
,
594 struct test_spoolss_context
*ctx
)
597 struct spoolss_EnumMonitors r
;
598 uint16_t levels
[] = { 1, 2 };
601 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
602 int level
= levels
[i
];
606 union spoolss_MonitorInfo
*info
;
608 r
.in
.servername
= "";
612 r
.out
.needed
= &needed
;
613 r
.out
.count
= &count
;
616 torture_comment(tctx
, "Testing EnumMonitors level %u\n", r
.in
.level
);
618 status
= dcerpc_spoolss_EnumMonitors_r(b
, ctx
, &r
);
619 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumMonitors failed");
620 if (W_ERROR_IS_OK(r
.out
.result
)) {
621 /* TODO: do some more checks here */
624 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
625 "EnumMonitors failed");
627 blob
= data_blob_talloc(ctx
, NULL
, needed
);
628 data_blob_clear(&blob
);
630 r
.in
.offered
= needed
;
632 status
= dcerpc_spoolss_EnumMonitors_r(b
, ctx
, &r
);
633 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumMonitors failed");
635 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumMonitors failed");
637 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
639 ctx
->monitor_count
[level
] = count
;
640 ctx
->monitors
[level
] = info
;
643 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
644 int level
= levels
[i
];
645 int old_level
= levels
[i
-1];
646 torture_assert_int_equal(tctx
, ctx
->monitor_count
[level
], ctx
->monitor_count
[old_level
],
647 "EnumMonitors invalid value");
650 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
651 int level
= levels
[i
];
652 for (j
=0;j
<ctx
->monitor_count
[level
];j
++) {
653 union spoolss_MonitorInfo
*cur
= &ctx
->monitors
[level
][j
];
654 union spoolss_MonitorInfo
*ref
= &ctx
->monitors
[2][j
];
657 COMPARE_STRING(tctx
, cur
->info1
, ref
->info2
, monitor_name
);
660 /* level 2 is our reference, and it makes no sense to compare it to itself */
669 static bool test_EnumPrintProcessors(struct torture_context
*tctx
,
670 struct dcerpc_binding_handle
*b
,
671 struct test_spoolss_context
*ctx
,
672 const char *environment
)
675 struct spoolss_EnumPrintProcessors r
;
676 uint16_t levels
[] = { 1 };
679 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
680 int level
= levels
[i
];
684 union spoolss_PrintProcessorInfo
*info
;
686 r
.in
.servername
= "";
687 r
.in
.environment
= environment
;
691 r
.out
.needed
= &needed
;
692 r
.out
.count
= &count
;
695 torture_comment(tctx
, "Testing EnumPrintProcessors level %u\n", r
.in
.level
);
697 status
= dcerpc_spoolss_EnumPrintProcessors_r(b
, ctx
, &r
);
698 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcessors failed");
699 if (W_ERROR_IS_OK(r
.out
.result
)) {
700 /* TODO: do some more checks here */
703 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INSUFFICIENT_BUFFER
,
704 "EnumPrintProcessors unexpected return code");
706 blob
= data_blob_talloc(ctx
, NULL
, needed
);
707 data_blob_clear(&blob
);
709 r
.in
.offered
= needed
;
711 status
= dcerpc_spoolss_EnumPrintProcessors_r(b
, ctx
, &r
);
712 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EnumPrintProcessors failed");
714 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrintProcessors failed");
716 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
718 ctx
->print_processor_count
[level
] = count
;
719 ctx
->print_processors
[level
] = info
;
722 for (i
=1;i
<ARRAY_SIZE(levels
);i
++) {
723 int level
= levels
[i
];
724 int old_level
= levels
[i
-1];
725 torture_assert_int_equal(tctx
, ctx
->print_processor_count
[level
], ctx
->print_processor_count
[old_level
],
726 "EnumPrintProcessors failed");
729 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
730 int level
= levels
[i
];
731 for (j
=0;j
<ctx
->print_processor_count
[level
];j
++) {
733 union spoolss_PrintProcessorInfo
*cur
= &ctx
->print_processors
[level
][j
];
734 union spoolss_PrintProcessorInfo
*ref
= &ctx
->print_processors
[1][j
];
738 /* level 1 is our reference, and it makes no sense to compare it to itself */
747 static bool test_EnumPrintProcDataTypes(struct torture_context
*tctx
,
748 struct dcerpc_binding_handle
*b
,
749 struct test_spoolss_context
*ctx
)
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
, ctx
, &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(ctx
, NULL
, needed
);
784 data_blob_clear(&blob
);
786 r
.in
.offered
= needed
;
788 status
= dcerpc_spoolss_EnumPrintProcDataTypes_r(b
, ctx
, &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(struct torture_context
*tctx
,
2215 struct dcerpc_binding_handle
*b
,
2216 struct policy_handle
*handle
,
2217 const char *form_name
,
2221 struct spoolss_GetForm r
;
2224 r
.in
.handle
= handle
;
2225 r
.in
.form_name
= form_name
;
2229 r
.out
.needed
= &needed
;
2231 torture_comment(tctx
, "Testing GetForm level %d\n", r
.in
.level
);
2233 status
= dcerpc_spoolss_GetForm_r(b
, tctx
, &r
);
2234 torture_assert_ntstatus_ok(tctx
, status
, "GetForm failed");
2236 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2237 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2238 data_blob_clear(&blob
);
2239 r
.in
.buffer
= &blob
;
2240 r
.in
.offered
= needed
;
2241 status
= dcerpc_spoolss_GetForm_r(b
, tctx
, &r
);
2242 torture_assert_ntstatus_ok(tctx
, status
, "GetForm failed");
2244 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetForm failed");
2246 torture_assert(tctx
, r
.out
.info
, "No form info returned");
2249 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetForm failed");
2251 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
2256 static bool test_EnumForms(struct torture_context
*tctx
,
2257 struct dcerpc_binding_handle
*b
,
2258 struct policy_handle
*handle
, bool print_server
)
2261 struct spoolss_EnumForms r
;
2265 uint32_t levels
[] = { 1, 2 };
2268 for (i
=0; i
<ARRAY_SIZE(levels
); i
++) {
2270 union spoolss_FormInfo
*info
;
2272 r
.in
.handle
= handle
;
2273 r
.in
.level
= levels
[i
];
2276 r
.out
.needed
= &needed
;
2277 r
.out
.count
= &count
;
2280 torture_comment(tctx
, "Testing EnumForms level %d\n", levels
[i
]);
2282 status
= dcerpc_spoolss_EnumForms_r(b
, tctx
, &r
);
2283 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
2285 if ((r
.in
.level
== 2) && (W_ERROR_EQUAL(r
.out
.result
, WERR_UNKNOWN_LEVEL
))) {
2289 if (print_server
&& W_ERROR_EQUAL(r
.out
.result
, WERR_BADFID
))
2290 torture_fail(tctx
, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2292 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2294 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2295 data_blob_clear(&blob
);
2296 r
.in
.buffer
= &blob
;
2297 r
.in
.offered
= needed
;
2299 status
= dcerpc_spoolss_EnumForms_r(b
, tctx
, &r
);
2301 torture_assert(tctx
, info
, "No forms returned");
2303 for (j
= 0; j
< count
; j
++) {
2305 ret
&= test_GetForm(tctx
, b
, handle
, info
[j
].info1
.form_name
, levels
[i
]);
2309 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
2311 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumForms failed");
2313 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
2319 static bool test_DeleteForm(struct torture_context
*tctx
,
2320 struct dcerpc_binding_handle
*b
,
2321 struct policy_handle
*handle
,
2322 const char *form_name
)
2325 struct spoolss_DeleteForm r
;
2327 r
.in
.handle
= handle
;
2328 r
.in
.form_name
= form_name
;
2330 status
= dcerpc_spoolss_DeleteForm_r(b
, tctx
, &r
);
2332 torture_assert_ntstatus_ok(tctx
, status
, "DeleteForm failed");
2334 torture_assert_werr_ok(tctx
, r
.out
.result
, "DeleteForm failed");
2339 static bool test_AddForm(struct torture_context
*tctx
,
2340 struct dcerpc_binding_handle
*b
,
2341 struct policy_handle
*handle
, bool print_server
)
2343 struct spoolss_AddForm r
;
2344 struct spoolss_AddFormInfo1 addform
;
2345 const char *form_name
= "testform3";
2349 r
.in
.handle
= handle
;
2351 r
.in
.info
.info1
= &addform
;
2352 addform
.flags
= SPOOLSS_FORM_USER
;
2353 addform
.form_name
= form_name
;
2354 addform
.size
.width
= 50;
2355 addform
.size
.height
= 25;
2356 addform
.area
.left
= 5;
2357 addform
.area
.top
= 10;
2358 addform
.area
.right
= 45;
2359 addform
.area
.bottom
= 15;
2361 status
= dcerpc_spoolss_AddForm_r(b
, tctx
, &r
);
2363 torture_assert_ntstatus_ok(tctx
, status
, "AddForm failed");
2365 torture_assert_werr_ok(tctx
, r
.out
.result
, "AddForm failed");
2367 if (!print_server
) ret
&= test_GetForm(tctx
, b
, handle
, form_name
, 1);
2370 struct spoolss_SetForm sf
;
2371 struct spoolss_AddFormInfo1 setform
;
2373 sf
.in
.handle
= handle
;
2374 sf
.in
.form_name
= form_name
;
2376 sf
.in
.info
.info1
= &setform
;
2377 setform
.flags
= addform
.flags
;
2378 setform
.form_name
= addform
.form_name
;
2379 setform
.size
= addform
.size
;
2380 setform
.area
= addform
.area
;
2382 setform
.size
.width
= 1234;
2384 status
= dcerpc_spoolss_SetForm_r(b
, tctx
, &sf
);
2386 torture_assert_ntstatus_ok(tctx
, status
, "SetForm failed");
2388 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetForm failed");
2391 if (!print_server
) ret
&= test_GetForm(tctx
, b
, handle
, form_name
, 1);
2394 struct spoolss_EnumForms e
;
2395 union spoolss_FormInfo
*info
;
2400 e
.in
.handle
= handle
;
2404 e
.out
.needed
= &needed
;
2405 e
.out
.count
= &count
;
2408 torture_comment(tctx
, "Testing EnumForms level 1\n");
2410 status
= dcerpc_spoolss_EnumForms_r(b
, tctx
, &e
);
2411 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
2413 if (print_server
&& W_ERROR_EQUAL(e
.out
.result
, WERR_BADFID
))
2414 torture_fail(tctx
, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2416 if (W_ERROR_EQUAL(e
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2418 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2419 data_blob_clear(&blob
);
2420 e
.in
.buffer
= &blob
;
2421 e
.in
.offered
= needed
;
2423 status
= dcerpc_spoolss_EnumForms_r(b
, tctx
, &e
);
2425 torture_assert(tctx
, info
, "No forms returned");
2427 for (j
= 0; j
< count
; j
++) {
2428 if (strequal(form_name
, info
[j
].info1
.form_name
)) {
2434 torture_assert(tctx
, found
, "Newly added form not found in enum call");
2437 if (!test_DeleteForm(tctx
, b
, handle
, form_name
)) {
2444 static bool test_EnumPorts_old(struct torture_context
*tctx
,
2445 struct dcerpc_pipe
*p
)
2448 struct spoolss_EnumPorts r
;
2451 union spoolss_PortInfo
*info
;
2452 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
2454 r
.in
.servername
= talloc_asprintf(tctx
, "\\\\%s",
2455 dcerpc_server_name(p
));
2459 r
.out
.needed
= &needed
;
2460 r
.out
.count
= &count
;
2463 torture_comment(tctx
, "Testing EnumPorts\n");
2465 status
= dcerpc_spoolss_EnumPorts_r(b
, tctx
, &r
);
2467 torture_assert_ntstatus_ok(tctx
, status
, "EnumPorts failed");
2469 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2470 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2471 data_blob_clear(&blob
);
2472 r
.in
.buffer
= &blob
;
2473 r
.in
.offered
= needed
;
2475 status
= dcerpc_spoolss_EnumPorts_r(b
, tctx
, &r
);
2476 torture_assert_ntstatus_ok(tctx
, status
, "EnumPorts failed");
2477 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
2479 torture_assert(tctx
, info
, "No ports returned");
2482 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPorts failed");
2484 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts
, info
, 2, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
2489 static bool test_AddPort(struct torture_context
*tctx
,
2490 struct dcerpc_pipe
*p
)
2493 struct spoolss_AddPort r
;
2494 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
2496 r
.in
.server_name
= talloc_asprintf(tctx
, "\\\\%s",
2497 dcerpc_server_name(p
));
2499 r
.in
.monitor_name
= "foo";
2501 torture_comment(tctx
, "Testing AddPort\n");
2503 status
= dcerpc_spoolss_AddPort_r(b
, tctx
, &r
);
2505 torture_assert_ntstatus_ok(tctx
, status
, "AddPort failed");
2507 /* win2k3 returns WERR_NOT_SUPPORTED */
2511 if (!W_ERROR_IS_OK(r
.out
.result
)) {
2512 printf("AddPort failed - %s\n", win_errstr(r
.out
.result
));
2521 static bool test_GetJob(struct torture_context
*tctx
,
2522 struct dcerpc_binding_handle
*b
,
2523 struct policy_handle
*handle
, uint32_t job_id
)
2526 struct spoolss_GetJob r
;
2527 union spoolss_JobInfo info
;
2529 uint32_t levels
[] = {1, 2 /* 3, 4 */};
2532 r
.in
.handle
= handle
;
2533 r
.in
.job_id
= job_id
;
2537 r
.out
.needed
= &needed
;
2540 torture_comment(tctx
, "Testing GetJob level %d\n", r
.in
.level
);
2542 status
= dcerpc_spoolss_GetJob_r(b
, tctx
, &r
);
2543 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
, "Unexpected return code");
2545 for (i
= 0; i
< ARRAY_SIZE(levels
); i
++) {
2547 torture_comment(tctx
, "Testing GetJob level %d\n", r
.in
.level
);
2551 r
.in
.level
= levels
[i
];
2555 status
= dcerpc_spoolss_GetJob_r(b
, tctx
, &r
);
2556 torture_assert_ntstatus_ok(tctx
, status
, "GetJob failed");
2558 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2559 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2560 data_blob_clear(&blob
);
2561 r
.in
.buffer
= &blob
;
2562 r
.in
.offered
= needed
;
2564 status
= dcerpc_spoolss_GetJob_r(b
, tctx
, &r
);
2565 torture_assert_ntstatus_ok(tctx
, status
, "GetJob failed");
2568 torture_assert(tctx
, r
.out
.info
, "No job info returned");
2569 torture_assert_werr_ok(tctx
, r
.out
.result
, "GetJob failed");
2571 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
2577 static bool test_SetJob(struct torture_context
*tctx
,
2578 struct dcerpc_binding_handle
*b
,
2579 struct policy_handle
*handle
, uint32_t job_id
,
2580 enum spoolss_JobControl command
)
2583 struct spoolss_SetJob r
;
2585 r
.in
.handle
= handle
;
2586 r
.in
.job_id
= job_id
;
2588 r
.in
.command
= command
;
2591 case SPOOLSS_JOB_CONTROL_PAUSE
:
2592 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
2594 case SPOOLSS_JOB_CONTROL_RESUME
:
2595 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
2597 case SPOOLSS_JOB_CONTROL_CANCEL
:
2598 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
2600 case SPOOLSS_JOB_CONTROL_RESTART
:
2601 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
2603 case SPOOLSS_JOB_CONTROL_DELETE
:
2604 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
2606 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER
:
2607 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
2609 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED
:
2610 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
2612 case SPOOLSS_JOB_CONTROL_RETAIN
:
2613 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
2615 case SPOOLSS_JOB_CONTROL_RELEASE
:
2616 torture_comment(tctx
, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
2619 torture_comment(tctx
, "Testing SetJob\n");
2623 status
= dcerpc_spoolss_SetJob_r(b
, tctx
, &r
);
2624 torture_assert_ntstatus_ok(tctx
, status
, "SetJob failed");
2625 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetJob failed");
2630 static bool test_AddJob(struct torture_context
*tctx
,
2631 struct dcerpc_binding_handle
*b
,
2632 struct policy_handle
*handle
)
2635 struct spoolss_AddJob r
;
2639 r
.in
.handle
= handle
;
2641 r
.out
.needed
= &needed
;
2642 r
.in
.buffer
= r
.out
.buffer
= NULL
;
2644 torture_comment(tctx
, "Testing AddJob\n");
2646 status
= dcerpc_spoolss_AddJob_r(b
, tctx
, &r
);
2647 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_UNKNOWN_LEVEL
, "AddJob failed");
2651 status
= dcerpc_spoolss_AddJob_r(b
, tctx
, &r
);
2652 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
, "AddJob failed");
2658 static bool test_EnumJobs(struct torture_context
*tctx
,
2659 struct dcerpc_binding_handle
*b
,
2660 struct policy_handle
*handle
)
2663 struct spoolss_EnumJobs r
;
2666 union spoolss_JobInfo
*info
;
2668 r
.in
.handle
= handle
;
2670 r
.in
.numjobs
= 0xffffffff;
2674 r
.out
.needed
= &needed
;
2675 r
.out
.count
= &count
;
2678 torture_comment(tctx
, "Testing EnumJobs\n");
2680 status
= dcerpc_spoolss_EnumJobs_r(b
, tctx
, &r
);
2682 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
2684 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
2686 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
2687 data_blob_clear(&blob
);
2688 r
.in
.buffer
= &blob
;
2689 r
.in
.offered
= needed
;
2691 status
= dcerpc_spoolss_EnumJobs_r(b
, tctx
, &r
);
2693 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
2694 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumJobs failed");
2695 torture_assert(tctx
, info
, "No jobs returned");
2697 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs
, *r
.out
.info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
2699 for (j
= 0; j
< count
; j
++) {
2701 torture_assert(tctx
, test_GetJob(tctx
, b
, handle
, info
[j
].info1
.job_id
),
2702 "failed to call test_GetJob");
2705 if (!torture_setting_bool(tctx
, "samba3", false)) {
2706 test_SetJob(tctx
, b
, handle
, info
[j
].info1
.job_id
, SPOOLSS_JOB_CONTROL_PAUSE
);
2707 test_SetJob(tctx
, b
, handle
, info
[j
].info1
.job_id
, SPOOLSS_JOB_CONTROL_RESUME
);
2712 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumJobs failed");
2718 static bool test_DoPrintTest(struct torture_context
*tctx
,
2719 struct dcerpc_binding_handle
*b
,
2720 struct policy_handle
*handle
)
2724 struct spoolss_StartDocPrinter s
;
2725 struct spoolss_DocumentInfo1 info1
;
2726 struct spoolss_StartPagePrinter sp
;
2727 struct spoolss_WritePrinter w
;
2728 struct spoolss_EndPagePrinter ep
;
2729 struct spoolss_EndDocPrinter e
;
2732 uint32_t num_written
;
2734 torture_comment(tctx
, "Testing StartDocPrinter\n");
2736 s
.in
.handle
= handle
;
2738 s
.in
.info
.info1
= &info1
;
2739 s
.out
.job_id
= &job_id
;
2740 info1
.document_name
= "TorturePrintJob";
2741 info1
.output_file
= NULL
;
2742 info1
.datatype
= "RAW";
2744 status
= dcerpc_spoolss_StartDocPrinter_r(b
, tctx
, &s
);
2745 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_StartDocPrinter failed");
2746 torture_assert_werr_ok(tctx
, s
.out
.result
, "StartDocPrinter failed");
2748 for (i
=1; i
< 4; i
++) {
2749 torture_comment(tctx
, "Testing StartPagePrinter: Page[%d]\n", i
);
2751 sp
.in
.handle
= handle
;
2753 status
= dcerpc_spoolss_StartPagePrinter_r(b
, tctx
, &sp
);
2754 torture_assert_ntstatus_ok(tctx
, status
,
2755 "dcerpc_spoolss_StartPagePrinter failed");
2756 torture_assert_werr_ok(tctx
, sp
.out
.result
, "StartPagePrinter failed");
2758 torture_comment(tctx
, "Testing WritePrinter: Page[%d]\n", i
);
2760 w
.in
.handle
= handle
;
2761 w
.in
.data
= data_blob_string_const(talloc_asprintf(tctx
,"TortureTestPage: %d\nData\n",i
));
2762 w
.out
.num_written
= &num_written
;
2764 status
= dcerpc_spoolss_WritePrinter_r(b
, tctx
, &w
);
2765 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_WritePrinter failed");
2766 torture_assert_werr_ok(tctx
, w
.out
.result
, "WritePrinter failed");
2768 torture_comment(tctx
, "Testing EndPagePrinter: Page[%d]\n", i
);
2770 ep
.in
.handle
= handle
;
2772 status
= dcerpc_spoolss_EndPagePrinter_r(b
, tctx
, &ep
);
2773 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndPagePrinter failed");
2774 torture_assert_werr_ok(tctx
, ep
.out
.result
, "EndPagePrinter failed");
2777 torture_comment(tctx
, "Testing EndDocPrinter\n");
2779 e
.in
.handle
= handle
;
2781 status
= dcerpc_spoolss_EndDocPrinter_r(b
, tctx
, &e
);
2782 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_spoolss_EndDocPrinter failed");
2783 torture_assert_werr_ok(tctx
, e
.out
.result
, "EndDocPrinter failed");
2785 ret
&= test_AddJob(tctx
, b
, handle
);
2786 ret
&= test_EnumJobs(tctx
, b
, handle
);
2788 ret
&= test_SetJob(tctx
, b
, handle
, job_id
, SPOOLSS_JOB_CONTROL_DELETE
);
2793 static bool test_PausePrinter(struct torture_context
*tctx
,
2794 struct dcerpc_binding_handle
*b
,
2795 struct policy_handle
*handle
)
2798 struct spoolss_SetPrinter r
;
2799 struct spoolss_SetPrinterInfoCtr info_ctr
;
2800 struct spoolss_DevmodeContainer devmode_ctr
;
2801 struct sec_desc_buf secdesc_ctr
;
2804 info_ctr
.info
.info0
= NULL
;
2806 ZERO_STRUCT(devmode_ctr
);
2807 ZERO_STRUCT(secdesc_ctr
);
2809 r
.in
.handle
= handle
;
2810 r
.in
.info_ctr
= &info_ctr
;
2811 r
.in
.devmode_ctr
= &devmode_ctr
;
2812 r
.in
.secdesc_ctr
= &secdesc_ctr
;
2813 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_PAUSE
;
2815 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
2817 status
= dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
);
2819 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
2821 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
2826 static bool test_ResumePrinter(struct torture_context
*tctx
,
2827 struct dcerpc_binding_handle
*b
,
2828 struct policy_handle
*handle
)
2831 struct spoolss_SetPrinter r
;
2832 struct spoolss_SetPrinterInfoCtr info_ctr
;
2833 struct spoolss_DevmodeContainer devmode_ctr
;
2834 struct sec_desc_buf secdesc_ctr
;
2837 info_ctr
.info
.info0
= NULL
;
2839 ZERO_STRUCT(devmode_ctr
);
2840 ZERO_STRUCT(secdesc_ctr
);
2842 r
.in
.handle
= handle
;
2843 r
.in
.info_ctr
= &info_ctr
;
2844 r
.in
.devmode_ctr
= &devmode_ctr
;
2845 r
.in
.secdesc_ctr
= &secdesc_ctr
;
2846 r
.in
.command
= SPOOLSS_PRINTER_CONTROL_RESUME
;
2848 torture_comment(tctx
, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2850 status
= dcerpc_spoolss_SetPrinter_r(b
, tctx
, &r
);
2852 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinter failed");
2854 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinter failed");
2859 static bool test_GetPrinterData(struct torture_context
*tctx
,
2860 struct dcerpc_binding_handle
*b
,
2861 struct policy_handle
*handle
,
2862 const char *value_name
,
2863 enum winreg_Type
*type_p
,
2868 struct spoolss_GetPrinterData r
;
2870 enum winreg_Type type
;
2871 union spoolss_PrinterData data
;
2873 r
.in
.handle
= handle
;
2874 r
.in
.value_name
= value_name
;
2876 r
.out
.needed
= &needed
;
2878 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
2880 torture_comment(tctx
, "Testing GetPrinterData(%s)\n", r
.in
.value_name
);
2882 status
= dcerpc_spoolss_GetPrinterData_r(b
, tctx
, &r
);
2883 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
2885 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
2886 r
.in
.offered
= needed
;
2887 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
2888 status
= dcerpc_spoolss_GetPrinterData_r(b
, tctx
, &r
);
2889 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed");
2892 torture_assert_werr_ok(tctx
, r
.out
.result
,
2893 talloc_asprintf(tctx
, "GetPrinterData(%s) failed", r
.in
.value_name
));
2895 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData
, &data
, type
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 1);
2902 *data_p
= r
.out
.data
;
2912 static bool test_GetPrinterDataEx(struct torture_context
*tctx
,
2913 struct dcerpc_pipe
*p
,
2914 struct policy_handle
*handle
,
2915 const char *key_name
,
2916 const char *value_name
,
2917 enum winreg_Type
*type_p
,
2922 struct spoolss_GetPrinterDataEx r
;
2923 enum winreg_Type type
;
2925 union spoolss_PrinterData data
;
2926 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
2928 r
.in
.handle
= handle
;
2929 r
.in
.key_name
= key_name
;
2930 r
.in
.value_name
= value_name
;
2933 r
.out
.needed
= &needed
;
2934 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
2936 torture_comment(tctx
, "Testing GetPrinterDataEx(%s - %s)\n",
2937 r
.in
.key_name
, r
.in
.value_name
);
2939 status
= dcerpc_spoolss_GetPrinterDataEx_r(b
, tctx
, &r
);
2940 if (!NT_STATUS_IS_OK(status
)) {
2941 if (NT_STATUS_EQUAL(status
,NT_STATUS_NET_WRITE_FAULT
) &&
2942 p
->last_fault_code
== DCERPC_FAULT_OP_RNG_ERROR
) {
2943 torture_skip(tctx
, "GetPrinterDataEx not supported by server\n");
2945 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
2948 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
2949 r
.in
.offered
= needed
;
2950 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.offered
);
2951 status
= dcerpc_spoolss_GetPrinterDataEx_r(b
, tctx
, &r
);
2952 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDataEx failed");
2955 torture_assert_werr_ok(tctx
, r
.out
.result
,
2956 talloc_asprintf(tctx
, "GetPrinterDataEx(%s - %s) failed", r
.in
.key_name
, r
.in
.value_name
));
2958 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData
, &data
, type
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 1);
2965 *data_p
= r
.out
.data
;
2975 static bool test_GetPrinterData_list(struct torture_context
*tctx
,
2976 struct dcerpc_pipe
*p
,
2977 struct policy_handle
*handle
,
2978 const char **architecture
)
2980 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
2981 const char *list
[] = {
2985 /* "NetPopup", not on w2k8 */
2986 /* "NetPopupToComputer", not on w2k8 */
2989 "DefaultSpoolDirectory",
2993 /* "OSVersionEx", not on s3 */
2998 for (i
=0; i
< ARRAY_SIZE(list
); i
++) {
2999 enum winreg_Type type
, type_ex
;
3000 uint8_t *data
, *data_ex
;
3001 uint32_t needed
, needed_ex
;
3003 torture_assert(tctx
, test_GetPrinterData(tctx
, b
, handle
, list
[i
], &type
, &data
, &needed
),
3004 talloc_asprintf(tctx
, "GetPrinterData failed on %s\n", list
[i
]));
3005 torture_assert(tctx
, test_GetPrinterDataEx(tctx
, p
, handle
, "random_string", list
[i
], &type_ex
, &data_ex
, &needed_ex
),
3006 talloc_asprintf(tctx
, "GetPrinterDataEx failed on %s\n", list
[i
]));
3007 torture_assert_int_equal(tctx
, type
, type_ex
, "type mismatch");
3008 torture_assert_int_equal(tctx
, needed
, needed_ex
, "needed mismatch");
3009 torture_assert_mem_equal(tctx
, data
, data_ex
, needed
, "data mismatch");
3011 if (strequal(list
[i
], "Architecture")) {
3013 DATA_BLOB blob
= data_blob_const(data
, needed
);
3014 *architecture
= reg_val_data_string(tctx
, lp_iconv_convenience(tctx
->lp_ctx
), REG_SZ
, blob
);
3022 static bool test_EnumPrinterData(struct torture_context
*tctx
,
3023 struct dcerpc_pipe
*p
,
3024 struct policy_handle
*handle
,
3025 uint32_t enum_index
,
3026 uint32_t value_offered
,
3027 uint32_t data_offered
,
3028 enum winreg_Type
*type_p
,
3029 uint32_t *value_needed_p
,
3030 uint32_t *data_needed_p
,
3031 const char **value_name_p
,
3035 struct spoolss_EnumPrinterData r
;
3036 uint32_t data_needed
;
3037 uint32_t value_needed
;
3038 enum winreg_Type type
;
3039 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
3041 r
.in
.handle
= handle
;
3042 r
.in
.enum_index
= enum_index
;
3043 r
.in
.value_offered
= value_offered
;
3044 r
.in
.data_offered
= data_offered
;
3045 r
.out
.data_needed
= &data_needed
;
3046 r
.out
.value_needed
= &value_needed
;
3048 r
.out
.data
= talloc_zero_array(tctx
, uint8_t, r
.in
.data_offered
);
3049 r
.out
.value_name
= talloc_zero_array(tctx
, const char, r
.in
.value_offered
);
3051 torture_comment(tctx
, "Testing EnumPrinterData(%d)\n", enum_index
);
3053 torture_assert_ntstatus_ok(tctx
,
3054 dcerpc_spoolss_EnumPrinterData_r(b
, tctx
, &r
),
3055 "EnumPrinterData failed");
3060 if (value_needed_p
) {
3061 *value_needed_p
= value_needed
;
3063 if (data_needed_p
) {
3064 *data_needed_p
= data_needed
;
3067 *value_name_p
= r
.out
.value_name
;
3070 *data_p
= r
.out
.data
;
3073 *result_p
= r
.out
.result
;
3080 static bool test_EnumPrinterData_all(struct torture_context
*tctx
,
3081 struct dcerpc_pipe
*p
,
3082 struct policy_handle
*handle
)
3084 uint32_t enum_index
= 0;
3085 enum winreg_Type type
;
3086 uint32_t value_needed
;
3087 uint32_t data_needed
;
3089 const char *value_name
;
3092 torture_comment(tctx
, "Testing EnumPrinterData\n");
3095 torture_assert(tctx
,
3096 test_EnumPrinterData(tctx
, p
, handle
, enum_index
, 0, 0,
3097 &type
, &value_needed
, &data_needed
,
3098 &value_name
, &data
, &result
),
3099 "EnumPrinterData failed");
3101 if (W_ERROR_EQUAL(result
, WERR_NO_MORE_ITEMS
)) {
3105 torture_assert(tctx
,
3106 test_EnumPrinterData(tctx
, p
, handle
, enum_index
, value_needed
, data_needed
,
3107 &type
, &value_needed
, &data_needed
,
3108 &value_name
, &data
, &result
),
3109 "EnumPrinterData failed");
3111 if (W_ERROR_EQUAL(result
, WERR_NO_MORE_ITEMS
)) {
3117 } while (W_ERROR_IS_OK(result
));
3119 torture_comment(tctx
, "EnumPrinterData test succeeded\n");
3124 static bool test_EnumPrinterDataEx(struct torture_context
*tctx
,
3125 struct dcerpc_binding_handle
*b
,
3126 struct policy_handle
*handle
,
3127 const char *key_name
,
3129 struct spoolss_PrinterEnumValues
**info_p
)
3131 struct spoolss_EnumPrinterDataEx r
;
3132 struct spoolss_PrinterEnumValues
*info
;
3136 r
.in
.handle
= handle
;
3137 r
.in
.key_name
= key_name
;
3139 r
.out
.needed
= &needed
;
3140 r
.out
.count
= &count
;
3143 torture_comment(tctx
, "Testing EnumPrinterDataEx(%s)\n", key_name
);
3145 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterDataEx_r(b
, tctx
, &r
),
3146 "EnumPrinterDataEx failed");
3147 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
3148 r
.in
.offered
= needed
;
3149 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterDataEx_r(b
, tctx
, &r
),
3150 "EnumPrinterDataEx failed");
3153 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDataEx failed");
3155 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx
, info
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 1);
3167 static bool test_SetPrinterData(struct torture_context
*tctx
,
3168 struct dcerpc_binding_handle
*b
,
3169 struct policy_handle
*handle
,
3170 const char *value_name
,
3171 enum winreg_Type type
,
3174 static bool test_DeletePrinterData(struct torture_context
*tctx
,
3175 struct dcerpc_binding_handle
*b
,
3176 struct policy_handle
*handle
,
3177 const char *value_name
);
3179 static bool test_EnumPrinterData_consistency(struct torture_context
*tctx
,
3180 struct dcerpc_pipe
*p
,
3181 struct policy_handle
*handle
)
3184 struct spoolss_PrinterEnumValues
*info
;
3186 uint32_t value_needed
, data_needed
;
3187 uint32_t value_offered
, data_offered
;
3189 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
3191 enum winreg_Type type
;
3194 torture_comment(tctx
, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3196 torture_assert(tctx
,
3197 reg_string_to_val(tctx
, lp_iconv_convenience(tctx
->lp_ctx
),
3198 "REG_SZ", "torture_data1", &type
, &blob
), "");
3200 torture_assert(tctx
,
3201 test_SetPrinterData(tctx
, b
, handle
, "torture_value1", type
, blob
.data
, blob
.length
),
3202 "SetPrinterData failed");
3204 blob
= data_blob_string_const("torture_data2");
3206 torture_assert(tctx
,
3207 test_SetPrinterData(tctx
, b
, handle
, "torture_value2", REG_BINARY
, blob
.data
, blob
.length
),
3208 "SetPrinterData failed");
3210 blob
= data_blob_talloc(tctx
, NULL
, 4);
3211 SIVAL(blob
.data
, 0, 0x11223344);
3213 torture_assert(tctx
,
3214 test_SetPrinterData(tctx
, b
, handle
, "torture_value3", type
, blob
.data
, blob
.length
),
3215 "SetPrinterData failed");
3217 torture_assert(tctx
,
3218 test_EnumPrinterDataEx(tctx
, b
, handle
, "PrinterDriverData", &count
, &info
),
3219 "failed to call EnumPrinterDataEx");
3221 /* get the max sizes for value and data */
3223 torture_assert(tctx
,
3224 test_EnumPrinterData(tctx
, p
, handle
, 0, 0, 0,
3225 NULL
, &value_needed
, &data_needed
,
3226 NULL
, NULL
, &result
),
3227 "EnumPrinterData failed");
3228 torture_assert_werr_ok(tctx
, result
, "unexpected result");
3230 /* check if the reply from the EnumPrinterData really matches max values */
3232 for (i
=0; i
< count
; i
++) {
3233 if (info
[i
].value_name_len
> value_needed
) {
3235 talloc_asprintf(tctx
,
3236 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3237 info
[i
].value_name_len
, value_needed
));
3239 if (info
[i
].data_length
> data_needed
) {
3241 talloc_asprintf(tctx
,
3242 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3243 info
[i
].data_length
, data_needed
));
3247 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3248 * sort or not sort the replies by value name, we should be able to do
3249 * the following entry comparison */
3251 data_offered
= data_needed
;
3252 value_offered
= value_needed
;
3254 for (i
=0; i
< count
; i
++) {
3256 const char *value_name
;
3259 torture_assert(tctx
,
3260 test_EnumPrinterData(tctx
, p
, handle
, i
, value_offered
, data_offered
,
3261 &type
, &value_needed
, &data_needed
,
3262 &value_name
, &data
, &result
),
3263 "EnumPrinterData failed");
3265 if (i
-1 == count
) {
3266 torture_assert_werr_equal(tctx
, result
, WERR_NO_MORE_ITEMS
,
3267 "unexpected result");
3270 torture_assert_werr_ok(tctx
, result
, "unexpected result");
3273 torture_assert_int_equal(tctx
, type
, info
[i
].type
, "type mismatch");
3274 torture_assert_int_equal(tctx
, value_needed
, info
[i
].value_name_len
, "value name length mismatch");
3275 torture_assert_str_equal(tctx
, value_name
, info
[i
].value_name
, "value name mismatch");
3276 torture_assert_int_equal(tctx
, data_needed
, info
[i
].data_length
, "data length mismatch");
3277 torture_assert_mem_equal(tctx
, data
, info
[i
].data
->data
, info
[i
].data_length
, "data mismatch");
3280 torture_assert(tctx
,
3281 test_DeletePrinterData(tctx
, b
, handle
, "torture_value1"),
3282 "DeletePrinterData failed");
3283 torture_assert(tctx
,
3284 test_DeletePrinterData(tctx
, b
, handle
, "torture_value2"),
3285 "DeletePrinterData failed");
3286 torture_assert(tctx
,
3287 test_DeletePrinterData(tctx
, b
, handle
, "torture_value3"),
3288 "DeletePrinterData failed");
3290 torture_comment(tctx
, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
3295 static bool test_DeletePrinterData(struct torture_context
*tctx
,
3296 struct dcerpc_binding_handle
*b
,
3297 struct policy_handle
*handle
,
3298 const char *value_name
)
3301 struct spoolss_DeletePrinterData r
;
3303 r
.in
.handle
= handle
;
3304 r
.in
.value_name
= value_name
;
3306 torture_comment(tctx
, "Testing DeletePrinterData(%s)\n",
3309 status
= dcerpc_spoolss_DeletePrinterData_r(b
, tctx
, &r
);
3311 torture_assert_ntstatus_ok(tctx
, status
, "DeletePrinterData failed");
3312 torture_assert_werr_ok(tctx
, r
.out
.result
, "DeletePrinterData failed");
3317 static bool test_DeletePrinterDataEx(struct torture_context
*tctx
,
3318 struct dcerpc_binding_handle
*b
,
3319 struct policy_handle
*handle
,
3320 const char *key_name
,
3321 const char *value_name
)
3323 struct spoolss_DeletePrinterDataEx r
;
3325 r
.in
.handle
= handle
;
3326 r
.in
.key_name
= key_name
;
3327 r
.in
.value_name
= value_name
;
3329 torture_comment(tctx
, "Testing DeletePrinterDataEx(%s - %s)\n",
3330 r
.in
.key_name
, r
.in
.value_name
);
3332 torture_assert_ntstatus_ok(tctx
,
3333 dcerpc_spoolss_DeletePrinterDataEx_r(b
, tctx
, &r
),
3334 "DeletePrinterDataEx failed");
3335 torture_assert_werr_ok(tctx
, r
.out
.result
,
3336 "DeletePrinterDataEx failed");
3341 static bool test_DeletePrinterKey(struct torture_context
*tctx
,
3342 struct dcerpc_binding_handle
*b
,
3343 struct policy_handle
*handle
,
3344 const char *key_name
)
3346 struct spoolss_DeletePrinterKey r
;
3348 r
.in
.handle
= handle
;
3349 r
.in
.key_name
= key_name
;
3351 torture_comment(tctx
, "Testing DeletePrinterKey(%s)\n", r
.in
.key_name
);
3353 if (strequal(key_name
, "") && !torture_setting_bool(tctx
, "dangerous", false)) {
3354 torture_skip(tctx
, "not wiping out printer registry - enable dangerous tests to use\n");
3358 torture_assert_ntstatus_ok(tctx
,
3359 dcerpc_spoolss_DeletePrinterKey_r(b
, tctx
, &r
),
3360 "DeletePrinterKey failed");
3361 torture_assert_werr_ok(tctx
, r
.out
.result
,
3362 "DeletePrinterKey failed");
3367 static bool test_winreg_OpenHKLM(struct torture_context
*tctx
,
3368 struct dcerpc_binding_handle
*b
,
3369 struct policy_handle
*handle
)
3371 struct winreg_OpenHKLM r
;
3373 r
.in
.system_name
= NULL
;
3374 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
3375 r
.out
.handle
= handle
;
3377 torture_comment(tctx
, "Testing winreg_OpenHKLM\n");
3379 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_OpenHKLM_r(b
, tctx
, &r
), "OpenHKLM failed");
3380 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenHKLM failed");
3385 static void init_winreg_String(struct winreg_String
*name
, const char *s
)
3389 name
->name_len
= 2 * (strlen_m(s
) + 1);
3390 name
->name_size
= name
->name_len
;
3393 name
->name_size
= 0;
3397 static bool test_winreg_OpenKey(struct torture_context
*tctx
,
3398 struct dcerpc_binding_handle
*b
,
3399 struct policy_handle
*hive_handle
,
3400 const char *keyname
,
3401 struct policy_handle
*key_handle
)
3403 struct winreg_OpenKey r
;
3405 r
.in
.parent_handle
= hive_handle
;
3406 init_winreg_String(&r
.in
.keyname
, keyname
);
3407 r
.in
.options
= REG_KEYTYPE_NON_VOLATILE
;
3408 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
3409 r
.out
.handle
= key_handle
;
3411 torture_comment(tctx
, "Testing winreg_OpenKey(%s)\n", keyname
);
3413 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_OpenKey_r(b
, tctx
, &r
), "OpenKey failed");
3414 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenKey failed");
3419 static bool test_winreg_CloseKey(struct torture_context
*tctx
,
3420 struct dcerpc_binding_handle
*b
,
3421 struct policy_handle
*handle
)
3423 struct winreg_CloseKey r
;
3425 r
.in
.handle
= handle
;
3426 r
.out
.handle
= handle
;
3428 torture_comment(tctx
, "Testing winreg_CloseKey\n");
3430 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_CloseKey_r(b
, tctx
, &r
), "CloseKey failed");
3431 torture_assert_werr_ok(tctx
, r
.out
.result
, "CloseKey failed");
3436 bool test_winreg_QueryValue(struct torture_context
*tctx
,
3437 struct dcerpc_binding_handle
*b
,
3438 struct policy_handle
*handle
,
3439 const char *value_name
,
3440 enum winreg_Type
*type_p
,
3441 uint32_t *data_size_p
,
3442 uint32_t *data_length_p
,
3445 struct winreg_QueryValue r
;
3446 enum winreg_Type type
= REG_NONE
;
3447 uint32_t data_size
= 0;
3448 uint32_t data_length
= 0;
3449 struct winreg_String valuename
;
3450 uint8_t *data
= NULL
;
3452 init_winreg_String(&valuename
, value_name
);
3454 data
= talloc_zero_array(tctx
, uint8_t, 0);
3456 r
.in
.handle
= handle
;
3457 r
.in
.value_name
= &valuename
;
3459 r
.in
.data_size
= &data_size
;
3460 r
.in
.data_length
= &data_length
;
3464 r
.out
.data_size
= &data_size
;
3465 r
.out
.data_length
= &data_length
;
3467 torture_comment(tctx
, "Testing winreg_QueryValue(%s)\n", value_name
);
3469 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_QueryValue_r(b
, tctx
, &r
), "QueryValue failed");
3470 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
3471 *r
.in
.data_size
= *r
.out
.data_size
;
3472 data
= talloc_zero_array(tctx
, uint8_t, *r
.in
.data_size
);
3475 torture_assert_ntstatus_ok(tctx
, dcerpc_winreg_QueryValue_r(b
, tctx
, &r
), "QueryValue failed");
3477 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryValue failed");
3480 *type_p
= *r
.out
.type
;
3483 *data_size_p
= *r
.out
.data_size
;
3485 if (data_length_p
) {
3486 *data_length_p
= *r
.out
.data_length
;
3489 *data_p
= r
.out
.data
;
3495 static bool test_winreg_query_printerdata(struct torture_context
*tctx
,
3496 struct dcerpc_binding_handle
*b
,
3497 struct policy_handle
*handle
,
3498 const char *printer_name
,
3499 const char *key_name
,
3500 const char *value_name
,
3501 enum winreg_Type
*w_type
,
3506 const char *printer_key
;
3507 struct policy_handle key_handle
;
3509 printer_key
= talloc_asprintf(tctx
, "%s\\%s\\%s",
3510 TOP_LEVEL_PRINTER_KEY
, printer_name
, key_name
);
3512 torture_assert(tctx
,
3513 test_winreg_OpenKey(tctx
, b
, handle
, printer_key
, &key_handle
), "");
3515 torture_assert(tctx
,
3516 test_winreg_QueryValue(tctx
, b
, &key_handle
, value_name
, w_type
, w_size
, w_length
, w_data
), "");
3518 torture_assert(tctx
,
3519 test_winreg_CloseKey(tctx
, b
, &key_handle
), "");
3524 static bool test_SetPrinterData(struct torture_context
*tctx
,
3525 struct dcerpc_binding_handle
*b
,
3526 struct policy_handle
*handle
,
3527 const char *value_name
,
3528 enum winreg_Type type
,
3532 struct spoolss_SetPrinterData r
;
3534 r
.in
.handle
= handle
;
3535 r
.in
.value_name
= value_name
;
3538 r
.in
.offered
= offered
;
3540 torture_comment(tctx
, "Testing SetPrinterData(%s)\n",
3543 torture_assert_ntstatus_ok(tctx
,
3544 dcerpc_spoolss_SetPrinterData_r(b
, tctx
, &r
),
3545 "SetPrinterData failed");
3546 torture_assert_werr_ok(tctx
, r
.out
.result
,
3547 "SetPrinterData failed");
3552 static bool test_SetPrinterData_matrix(struct torture_context
*tctx
,
3553 struct dcerpc_binding_handle
*b
,
3554 struct policy_handle
*handle
,
3555 const char *printer_name
,
3556 struct dcerpc_binding_handle
*winreg_handle
,
3557 struct policy_handle
*hive_handle
)
3559 const char *values
[] = {
3563 /* FIXME: not working with s3 atm. */
3569 /* FIXME: not working with s3 atm. */
3576 for (i
=0; i
< ARRAY_SIZE(values
); i
++) {
3578 enum winreg_Type type
;
3583 torture_assert(tctx
,
3584 reg_string_to_val(tctx
, lp_iconv_convenience(tctx
->lp_ctx
),
3585 "REG_SZ", "dog", &type
, &blob
), "");
3587 torture_assert(tctx
,
3588 test_SetPrinterData(tctx
, b
, handle
, values
[i
], REG_SZ
, blob
.data
, blob
.length
),
3589 "SetPrinterData failed");
3591 torture_assert(tctx
,
3592 test_GetPrinterData(tctx
, b
, handle
, values
[i
], &type
, &data
, &needed
),
3593 "GetPrinterData failed");
3595 torture_assert_int_equal(tctx
, type
, REG_SZ
, "type mismatch");
3596 torture_assert_int_equal(tctx
, needed
, blob
.length
, "size mismatch");
3597 torture_assert_mem_equal(tctx
, data
, blob
.data
, blob
.length
, "buffer mismatch");
3599 if (winreg_handle
&& hive_handle
) {
3601 enum winreg_Type w_type
;
3606 torture_assert(tctx
,
3607 test_winreg_query_printerdata(tctx
, winreg_handle
, hive_handle
,
3608 printer_name
, "PrinterDriverData", values
[i
],
3609 &w_type
, &w_size
, &w_length
, &w_data
), "");
3611 torture_assert_int_equal(tctx
, w_type
, REG_SZ
, "winreg type mismatch");
3612 torture_assert_int_equal(tctx
, w_size
, blob
.length
, "winreg size mismatch");
3613 torture_assert_int_equal(tctx
, w_length
, blob
.length
, "winreg length mismatch");
3614 torture_assert_mem_equal(tctx
, w_data
, blob
.data
, blob
.length
, "winreg buffer mismatch");
3617 torture_assert(tctx
,
3618 test_DeletePrinterData(tctx
, b
, handle
, values
[i
]),
3619 "DeletePrinterData failed");
3626 static bool test_EnumPrinterKey(struct torture_context
*tctx
,
3627 struct dcerpc_binding_handle
*b
,
3628 struct policy_handle
*handle
,
3629 const char *key_name
,
3630 const char ***array
);
3632 static bool test_SetPrinterDataEx(struct torture_context
*tctx
,
3633 struct dcerpc_binding_handle
*b
,
3634 struct policy_handle
*handle
,
3635 const char *key_name
,
3636 const char *value_name
,
3637 enum winreg_Type type
,
3642 struct spoolss_SetPrinterDataEx r
;
3644 r
.in
.handle
= handle
;
3645 r
.in
.key_name
= key_name
;
3646 r
.in
.value_name
= value_name
;
3649 r
.in
.offered
= offered
;
3651 torture_comment(tctx
, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
3652 r
.in
.key_name
, r
.in
.value_name
, str_regtype(r
.in
.type
), r
.in
.offered
);
3654 status
= dcerpc_spoolss_SetPrinterDataEx_r(b
, tctx
, &r
);
3656 torture_assert_ntstatus_ok(tctx
, status
, "SetPrinterDataEx failed");
3657 torture_assert_werr_ok(tctx
, r
.out
.result
, "SetPrinterDataEx failed");
3662 static bool test_SetPrinterDataEx_matrix(struct torture_context
*tctx
,
3663 struct dcerpc_pipe
*p
,
3664 struct policy_handle
*handle
,
3665 const char *printername
,
3666 struct dcerpc_binding_handle
*winreg_handle
,
3667 struct policy_handle
*hive_handle
)
3669 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
3670 const char *value_name
= "dog";
3671 const char *keys
[] = {
3675 /* FIXME: not working with s3 atm. */
3676 "torturedataex_with_subkey\\subkey",
3677 "torturedataex_with_subkey\\subkey:0",
3678 "torturedataex_with_subkey\\subkey:1",
3679 "torturedataex_with_subkey\\subkey\\subsubkey",
3680 "torturedataex_with_subkey\\subkey\\subsubkey:0",
3681 "torturedataex_with_subkey\\subkey\\subsubkey:1",
3685 /* FIXME: not working with s3 atm. */
3692 enum winreg_Type types
[] = {
3698 const char *str
= "abcdefghijklmnopqrstuvwxzy";
3702 for (i
=0; i
< ARRAY_SIZE(keys
); i
++) {
3703 for (t
=0; t
< ARRAY_SIZE(types
); t
++) {
3704 for (s
=0; s
< strlen(str
); s
++) {
3708 enum winreg_Type type
;
3709 const char *string
= talloc_strndup(tctx
, str
, s
);
3710 DATA_BLOB blob
= data_blob_string_const(string
);
3711 const char **subkeys
;
3714 uint32_t needed
, offered
= 0;
3716 struct spoolss_PrinterEnumValues
*einfo
;
3718 if (types
[t
] == REG_DWORD
) {
3722 if (torture_setting_bool(tctx
, "samba3", false)) {
3723 if ((types
[t
] == REG_MULTI_SZ
) && s
== 0) {
3724 torture_warning(tctx
, "samba3 does not handle 4 byte emtpy REG_MULTI_SZ buffers");
3732 offered
= blob
.length
;
3735 data
= data_blob_talloc(tctx
, NULL
, 4);
3736 SIVAL(data
.data
, 0, 0x12345678);
3740 torture_assert(tctx
,
3741 reg_string_to_val(tctx
, lp_iconv_convenience(tctx
->lp_ctx
),
3742 "REG_SZ", string
, &type
, &data
), "");
3743 offered
= data
.length
;
3744 /*strlen_m_term(data.string)*2;*/
3747 torture_assert(tctx
,
3748 reg_string_to_val(tctx
, lp_iconv_convenience(tctx
->lp_ctx
),
3749 "REG_SZ", string
, &type
, &data
), "");
3750 torture_assert(tctx
, data_blob_realloc(tctx
, &data
, data
.length
+ 2), "");
3751 memset(&data
.data
[data
.length
- 2], '\0', 2);
3752 offered
= data
.length
;
3755 torture_fail(tctx
, talloc_asprintf(tctx
, "type %d untested\n", types
[t
]));
3758 torture_assert(tctx
,
3759 test_SetPrinterDataEx(tctx
, b
, handle
, keys
[i
], value_name
, types
[t
], data
.data
, offered
),
3760 "failed to call SetPrinterDataEx");
3762 torture_assert(tctx
,
3763 test_GetPrinterDataEx(tctx
, p
, handle
, keys
[i
], value_name
, &type
, &data_out
, &needed
),
3764 "failed to call GetPrinterDataEx");
3766 torture_assert(tctx
,
3767 test_EnumPrinterDataEx(tctx
, b
, handle
, keys
[i
], &ecount
, &einfo
),
3768 "failed to call EnumPrinterDataEx");
3770 torture_assert_int_equal(tctx
, types
[t
], type
, "type mismatch");
3771 torture_assert_int_equal(tctx
, needed
, offered
, "size mismatch");
3772 torture_assert_mem_equal(tctx
, data_out
, data
.data
, offered
, "buffer mismatch");
3774 torture_assert_int_equal(tctx
, ecount
, 1, "unexpected enum count");
3775 torture_assert_str_equal(tctx
, einfo
[0].value_name
, value_name
, "value_name mismatch");
3776 torture_assert_int_equal(tctx
, einfo
[0].value_name_len
, strlen_m_term(value_name
)*2, "unexpected value_name_len");
3777 torture_assert_int_equal(tctx
, einfo
[0].type
, types
[t
], "type mismatch");
3778 torture_assert_int_equal(tctx
, einfo
[0].data_length
, offered
, "size mismatch");
3779 if (einfo
[0].data_length
> 0) {
3780 torture_assert_mem_equal(tctx
, einfo
[0].data
->data
, data
.data
, offered
, "buffer mismatch");
3783 if (winreg_handle
&& hive_handle
) {
3784 enum winreg_Type w_type
;
3789 torture_assert(tctx
,
3790 test_winreg_query_printerdata(tctx
, winreg_handle
, hive_handle
,
3791 printername
, keys
[i
], value_name
,
3792 &w_type
, &w_size
, &w_length
, &w_data
), "");
3794 torture_assert_int_equal(tctx
, w_type
, types
[t
], "winreg type mismatch");
3795 torture_assert_int_equal(tctx
, w_size
, offered
, "winreg size mismatch");
3796 torture_assert_int_equal(tctx
, w_length
, offered
, "winreg length mismatch");
3797 torture_assert_mem_equal(tctx
, w_data
, data
.data
, offered
, "winreg buffer mismatch");
3800 key
= talloc_strdup(tctx
, keys
[i
]);
3802 if (!test_DeletePrinterDataEx(tctx
, b
, handle
, keys
[i
], value_name
)) {
3806 c
= strchr(key
, '\\');
3810 /* we have subkeys */
3814 if (!test_EnumPrinterKey(tctx
, b
, handle
, key
, &subkeys
)) {
3818 for (k
=0; subkeys
&& subkeys
[k
]; k
++) {
3820 const char *current_key
= talloc_asprintf(tctx
, "%s\\%s", key
, subkeys
[k
]);
3822 if (!test_DeletePrinterKey(tctx
, b
, handle
, current_key
)) {
3827 if (!test_DeletePrinterKey(tctx
, b
, handle
, key
)) {
3832 if (!test_DeletePrinterKey(tctx
, b
, handle
, key
)) {
3843 static bool test_PrinterData_winreg(struct torture_context
*tctx
,
3844 struct dcerpc_pipe
*p
,
3845 struct policy_handle
*handle
,
3846 const char *printer_name
)
3848 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
3849 struct dcerpc_pipe
*p2
;
3851 struct policy_handle hive_handle
;
3852 struct dcerpc_binding_handle
*b2
;
3854 torture_assert_ntstatus_ok(tctx
,
3855 torture_rpc_connection(tctx
, &p2
, &ndr_table_winreg
),
3856 "could not open winreg pipe");
3857 b2
= p2
->binding_handle
;
3859 torture_assert(tctx
, test_winreg_OpenHKLM(tctx
, b2
, &hive_handle
), "");
3861 ret
&= test_SetPrinterData_matrix(tctx
, b
, handle
, printer_name
, b2
, &hive_handle
);
3862 ret
&= test_SetPrinterDataEx_matrix(tctx
, p
, handle
, printer_name
, b2
, &hive_handle
);
3864 test_winreg_CloseKey(tctx
, b2
, &hive_handle
);
3871 static bool test_GetChangeID_PrinterData(struct torture_context
*tctx
,
3872 struct dcerpc_binding_handle
*b
,
3873 struct policy_handle
*handle
,
3874 uint32_t *change_id
)
3876 enum winreg_Type type
;
3880 torture_assert(tctx
,
3881 test_GetPrinterData(tctx
, b
, handle
, "ChangeID", &type
, &data
, &needed
),
3882 "failed to call GetPrinterData");
3884 torture_assert(tctx
, type
== REG_DWORD
, "unexpected type");
3885 torture_assert_int_equal(tctx
, needed
, 4, "unexpected size");
3887 *change_id
= IVAL(data
, 0);
3892 static bool test_GetChangeID_PrinterDataEx(struct torture_context
*tctx
,
3893 struct dcerpc_pipe
*p
,
3894 struct policy_handle
*handle
,
3895 uint32_t *change_id
)
3897 enum winreg_Type type
;
3901 torture_assert(tctx
,
3902 test_GetPrinterDataEx(tctx
, p
, handle
, "PrinterDriverData", "ChangeID", &type
, &data
, &needed
),
3903 "failed to call GetPrinterData");
3905 torture_assert(tctx
, type
== REG_DWORD
, "unexpected type");
3906 torture_assert_int_equal(tctx
, needed
, 4, "unexpected size");
3908 *change_id
= IVAL(data
, 0);
3913 static bool test_GetChangeID_PrinterInfo(struct torture_context
*tctx
,
3914 struct dcerpc_binding_handle
*b
,
3915 struct policy_handle
*handle
,
3916 uint32_t *change_id
)
3918 union spoolss_PrinterInfo info
;
3920 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 0, &info
),
3921 "failed to query Printer level 0");
3923 *change_id
= info
.info0
.change_id
;
3928 static bool test_ChangeID(struct torture_context
*tctx
,
3929 struct dcerpc_pipe
*p
,
3930 struct policy_handle
*handle
)
3932 uint32_t change_id
, change_id_ex
, change_id_info
;
3933 uint32_t change_id2
, change_id_ex2
, change_id_info2
;
3934 union spoolss_PrinterInfo info
;
3935 const char *comment
;
3936 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
3938 torture_comment(tctx
, "Testing ChangeID: id change test #1\n");
3940 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id
),
3941 "failed to query for ChangeID");
3942 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex
),
3943 "failed to query for ChangeID");
3944 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info
),
3945 "failed to query for ChangeID");
3947 torture_assert_int_equal(tctx
, change_id
, change_id_ex
,
3948 "change_ids should all be equal");
3949 torture_assert_int_equal(tctx
, change_id_ex
, change_id_info
,
3950 "change_ids should all be equal");
3953 torture_comment(tctx
, "Testing ChangeID: id change test #2\n");
3955 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id
),
3956 "failed to query for ChangeID");
3957 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
3958 "failed to query Printer level 2");
3959 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex
),
3960 "failed to query for ChangeID");
3961 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info
),
3962 "failed to query for ChangeID");
3963 torture_assert_int_equal(tctx
, change_id
, change_id_ex
,
3964 "change_id should not have changed");
3965 torture_assert_int_equal(tctx
, change_id_ex
, change_id_info
,
3966 "change_id should not have changed");
3969 torture_comment(tctx
, "Testing ChangeID: id change test #3\n");
3971 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id
),
3972 "failed to query for ChangeID");
3973 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex
),
3974 "failed to query for ChangeID");
3975 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info
),
3976 "failed to query for ChangeID");
3977 torture_assert(tctx
, test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
3978 "failed to query Printer level 2");
3979 comment
= talloc_strdup(tctx
, info
.info2
.comment
);
3982 struct spoolss_SetPrinterInfoCtr info_ctr
;
3983 struct spoolss_DevmodeContainer devmode_ctr
;
3984 struct sec_desc_buf secdesc_ctr
;
3985 union spoolss_SetPrinterInfo sinfo
;
3987 ZERO_STRUCT(info_ctr
);
3988 ZERO_STRUCT(devmode_ctr
);
3989 ZERO_STRUCT(secdesc_ctr
);
3992 torture_assert(tctx
, PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
3993 sinfo
.info2
->comment
= "torture_comment";
3996 info_ctr
.info
= sinfo
;
3998 torture_assert(tctx
, test_SetPrinter(tctx
, b
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0),
3999 "failed to call SetPrinter");
4001 sinfo
.info2
->comment
= comment
;
4003 torture_assert(tctx
, test_SetPrinter(tctx
, b
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0),
4004 "failed to call SetPrinter");
4008 torture_assert(tctx
, test_GetChangeID_PrinterData(tctx
, b
, handle
, &change_id2
),
4009 "failed to query for ChangeID");
4010 torture_assert(tctx
, test_GetChangeID_PrinterDataEx(tctx
, p
, handle
, &change_id_ex2
),
4011 "failed to query for ChangeID");
4012 torture_assert(tctx
, test_GetChangeID_PrinterInfo(tctx
, b
, handle
, &change_id_info2
),
4013 "failed to query for ChangeID");
4015 torture_assert_int_equal(tctx
, change_id2
, change_id_ex2
,
4016 "change_ids should all be equal");
4017 torture_assert_int_equal(tctx
, change_id_ex2
, change_id_info2
,
4018 "change_ids should all be equal");
4020 torture_assert(tctx
, (change_id
< change_id2
),
4021 talloc_asprintf(tctx
, "change_id %d needs to be larger than change_id %d",
4022 change_id2
, change_id
));
4023 torture_assert(tctx
, (change_id_ex
< change_id_ex2
),
4024 talloc_asprintf(tctx
, "change_id %d needs to be larger than change_id %d",
4025 change_id_ex2
, change_id_ex
));
4026 torture_assert(tctx
, (change_id_info
< change_id_info2
),
4027 talloc_asprintf(tctx
, "change_id %d needs to be larger than change_id %d",
4028 change_id_info2
, change_id_info
));
4030 torture_comment(tctx
, "ChangeID tests succeeded\n\n");
4035 static bool test_SecondaryClosePrinter(struct torture_context
*tctx
,
4036 struct dcerpc_pipe
*p
,
4037 struct policy_handle
*handle
)
4040 struct dcerpc_binding
*b
;
4041 struct dcerpc_pipe
*p2
;
4042 struct spoolss_ClosePrinter cp
;
4044 /* only makes sense on SMB */
4045 if (p
->conn
->transport
.transport
!= NCACN_NP
) {
4049 torture_comment(tctx
, "testing close on secondary pipe\n");
4051 status
= dcerpc_parse_binding(tctx
, p
->conn
->binding_string
, &b
);
4052 torture_assert_ntstatus_ok(tctx
, status
, "Failed to parse dcerpc binding");
4054 status
= dcerpc_secondary_connection(p
, &p2
, b
);
4055 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create secondary connection");
4057 status
= dcerpc_bind_auth_none(p2
, &ndr_table_spoolss
);
4058 torture_assert_ntstatus_ok(tctx
, status
, "Failed to create bind on secondary connection");
4060 cp
.in
.handle
= handle
;
4061 cp
.out
.handle
= handle
;
4063 status
= dcerpc_spoolss_ClosePrinter_r(p2
->binding_handle
, tctx
, &cp
);
4064 torture_assert_ntstatus_equal(tctx
, status
, NT_STATUS_NET_WRITE_FAULT
,
4065 "ERROR: Allowed close on secondary connection");
4067 torture_assert_int_equal(tctx
, p2
->last_fault_code
, DCERPC_FAULT_CONTEXT_MISMATCH
,
4068 "Unexpected fault code");
4075 static bool test_OpenPrinter_badname(struct torture_context
*tctx
,
4076 struct dcerpc_binding_handle
*b
, const char *name
)
4079 struct spoolss_OpenPrinter op
;
4080 struct spoolss_OpenPrinterEx opEx
;
4081 struct policy_handle handle
;
4084 op
.in
.printername
= name
;
4085 op
.in
.datatype
= NULL
;
4086 op
.in
.devmode_ctr
.devmode
= NULL
;
4087 op
.in
.access_mask
= 0;
4088 op
.out
.handle
= &handle
;
4090 torture_comment(tctx
, "Testing OpenPrinter(%s) with bad name\n", op
.in
.printername
);
4092 status
= dcerpc_spoolss_OpenPrinter_r(b
, tctx
, &op
);
4093 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
4094 torture_assert_werr_equal(tctx
, op
.out
.result
, WERR_INVALID_PRINTER_NAME
,
4095 "unexpected result");
4097 if (W_ERROR_IS_OK(op
.out
.result
)) {
4098 ret
&=test_ClosePrinter(tctx
, b
, &handle
);
4101 opEx
.in
.printername
= name
;
4102 opEx
.in
.datatype
= NULL
;
4103 opEx
.in
.devmode_ctr
.devmode
= NULL
;
4104 opEx
.in
.access_mask
= 0;
4106 opEx
.in
.userlevel
.level1
= NULL
;
4107 opEx
.out
.handle
= &handle
;
4109 torture_comment(tctx
, "Testing OpenPrinterEx(%s) with bad name\n", opEx
.in
.printername
);
4111 status
= dcerpc_spoolss_OpenPrinterEx_r(b
, tctx
, &opEx
);
4112 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinterEx failed");
4113 torture_assert_werr_equal(tctx
, opEx
.out
.result
, WERR_INVALID_PARAM
,
4114 "unexpected result");
4116 if (W_ERROR_IS_OK(opEx
.out
.result
)) {
4117 ret
&=test_ClosePrinter(tctx
, b
, &handle
);
4123 static bool test_OpenPrinter(struct torture_context
*tctx
,
4124 struct dcerpc_pipe
*p
,
4126 const char *environment
)
4129 struct spoolss_OpenPrinter r
;
4130 struct policy_handle handle
;
4132 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4134 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s\\%s", dcerpc_server_name(p
), name
);
4135 r
.in
.datatype
= NULL
;
4136 r
.in
.devmode_ctr
.devmode
= NULL
;
4137 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4138 r
.out
.handle
= &handle
;
4140 torture_comment(tctx
, "Testing OpenPrinter(%s)\n", r
.in
.printername
);
4142 status
= dcerpc_spoolss_OpenPrinter_r(b
, tctx
, &r
);
4144 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinter failed");
4146 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenPrinter failed");
4148 if (!test_GetPrinter(tctx
, b
, &handle
, environment
)) {
4152 if (!torture_setting_bool(tctx
, "samba3", false)) {
4153 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
4158 if (!test_ClosePrinter(tctx
, b
, &handle
)) {
4165 static bool call_OpenPrinterEx(struct torture_context
*tctx
,
4166 struct dcerpc_pipe
*p
,
4168 struct spoolss_DeviceMode
*devmode
,
4169 struct policy_handle
*handle
)
4171 struct spoolss_OpenPrinterEx r
;
4172 struct spoolss_UserLevel1 userlevel1
;
4174 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4176 if (name
&& name
[0]) {
4177 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s\\%s",
4178 dcerpc_server_name(p
), name
);
4180 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s",
4181 dcerpc_server_name(p
));
4184 r
.in
.datatype
= NULL
;
4185 r
.in
.devmode_ctr
.devmode
= devmode
;
4186 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
4188 r
.in
.userlevel
.level1
= &userlevel1
;
4189 r
.out
.handle
= handle
;
4191 userlevel1
.size
= 1234;
4192 userlevel1
.client
= "hello";
4193 userlevel1
.user
= "spottyfoot!";
4194 userlevel1
.build
= 1;
4195 userlevel1
.major
= 2;
4196 userlevel1
.minor
= 3;
4197 userlevel1
.processor
= 4;
4199 torture_comment(tctx
, "Testing OpenPrinterEx(%s)\n", r
.in
.printername
);
4201 status
= dcerpc_spoolss_OpenPrinterEx_r(b
, tctx
, &r
);
4203 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinterEx failed");
4205 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenPrinterEx failed");
4210 static bool test_printer_rename(struct torture_context
*tctx
,
4211 struct dcerpc_pipe
*p
,
4212 struct policy_handle
*handle
,
4216 union spoolss_PrinterInfo info
;
4217 union spoolss_SetPrinterInfo sinfo
;
4218 struct spoolss_SetPrinterInfoCtr info_ctr
;
4219 struct spoolss_DevmodeContainer devmode_ctr
;
4220 struct sec_desc_buf secdesc_ctr
;
4221 const char *printer_name
;
4222 const char *printer_name_orig
;
4223 const char *printer_name_new
= "SAMBA smbtorture Test Printer (Copy 2)";
4224 struct policy_handle new_handle
;
4226 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4228 ZERO_STRUCT(devmode_ctr
);
4229 ZERO_STRUCT(secdesc_ctr
);
4231 torture_comment(tctx
, "Testing Printer rename operations\n");
4233 torture_assert(tctx
,
4234 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
4235 "failed to call GetPrinter level 2");
4237 printer_name_orig
= talloc_strdup(tctx
, info
.info2
.printername
);
4239 q
= strrchr(info
.info2
.printername
, '\\');
4241 torture_warning(tctx
,
4242 "server returns printername %s incl. servername although we did not set servername", info
.info2
.printername
);
4245 torture_assert(tctx
,
4246 PrinterInfo_to_SetPrinterInfo(tctx
, &info
, 2, &sinfo
), "");
4248 sinfo
.info2
->printername
= printer_name_new
;
4251 info_ctr
.info
= sinfo
;
4253 torture_assert(tctx
,
4254 test_SetPrinter(tctx
, b
, handle
, &info_ctr
, &devmode_ctr
, &secdesc_ctr
, 0),
4255 "failed to call SetPrinter level 2");
4257 torture_assert(tctx
,
4258 test_GetPrinter_level(tctx
, b
, handle
, 2, &info
),
4259 "failed to call GetPrinter level 2");
4261 printer_name
= talloc_strdup(tctx
, info
.info2
.printername
);
4263 q
= strrchr(info
.info2
.printername
, '\\');
4265 torture_warning(tctx
,
4266 "server returns printername %s incl. servername although we did not set servername", info
.info2
.printername
);
4271 torture_assert_str_equal(tctx
, printer_name
, printer_name_new
,
4272 "new printer name was not set");
4274 /* samba currently cannot fully rename printers */
4275 if (!torture_setting_bool(tctx
, "samba3", false)) {
4276 torture_assert(tctx
,
4277 test_OpenPrinter_badname(tctx
, b
, printer_name_orig
),
4278 "still can open printer with oldname after rename");
4280 torture_warning(tctx
, "*not* checking for open with oldname after rename for samba3");
4283 torture_assert(tctx
,
4284 call_OpenPrinterEx(tctx
, p
, printer_name_new
, NULL
, &new_handle
),
4285 "failed to open printer with new name");
4287 torture_assert(tctx
,
4288 test_GetPrinter_level(tctx
, b
, &new_handle
, 2, &info
),
4289 "failed to call GetPrinter level 2");
4291 /* FIXME: we openend with servername! */
4292 printer_name
= talloc_asprintf(tctx
, "\\\\%s\\%s",
4293 dcerpc_server_name(p
), printer_name_new
);
4295 torture_assert_str_equal(tctx
, info
.info2
.printername
, printer_name
,
4296 "new printer name was not set");
4298 torture_assert(tctx
,
4299 test_ClosePrinter(tctx
, b
, &new_handle
),
4300 "failed to close printer");
4302 torture_comment(tctx
, "Printer rename operations test succeeded\n\n");
4308 static bool test_OpenPrinterEx(struct torture_context
*tctx
,
4309 struct dcerpc_pipe
*p
,
4311 const char *environment
)
4313 struct policy_handle handle
;
4315 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4317 if (!call_OpenPrinterEx(tctx
, p
, name
, NULL
, &handle
)) {
4321 if (!test_PrinterInfo_SD(tctx
, b
, &handle
)) {
4325 if (!test_GetPrinter(tctx
, b
, &handle
, environment
)) {
4329 if (!test_EnumForms(tctx
, b
, &handle
, false)) {
4333 if (!test_AddForm(tctx
, b
, &handle
, false)) {
4337 if (!test_EnumPrinterData_all(tctx
, p
, &handle
)) {
4341 if (!test_EnumPrinterDataEx(tctx
, b
, &handle
, "PrinterDriverData", NULL
, NULL
)) {
4345 if (!test_EnumPrinterData_consistency(tctx
, p
, &handle
)) {
4349 if (!test_printer_keys(tctx
, b
, &handle
)) {
4353 if (!test_PausePrinter(tctx
, b
, &handle
)) {
4357 if (!test_DoPrintTest(tctx
, b
, &handle
)) {
4361 if (!test_ResumePrinter(tctx
, b
, &handle
)) {
4365 if (!test_SetPrinterData_matrix(tctx
, b
, &handle
, name
, NULL
, NULL
)) {
4369 if (!test_SetPrinterDataEx_matrix(tctx
, p
, &handle
, name
, NULL
, NULL
)) {
4373 if (!torture_setting_bool(tctx
, "samba3", false)) {
4374 if (!test_SecondaryClosePrinter(tctx
, p
, &handle
)) {
4379 if (!test_ClosePrinter(tctx
, b
, &handle
)) {
4386 static bool test_EnumPrinters_old(struct torture_context
*tctx
,
4387 struct dcerpc_pipe
*p
,
4388 const char *environment
)
4390 struct spoolss_EnumPrinters r
;
4392 uint16_t levels
[] = {1, 2, 4, 5};
4395 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4397 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
4398 union spoolss_PrinterInfo
*info
;
4403 r
.in
.flags
= PRINTER_ENUM_LOCAL
;
4405 r
.in
.level
= levels
[i
];
4408 r
.out
.needed
= &needed
;
4409 r
.out
.count
= &count
;
4412 torture_comment(tctx
, "Testing EnumPrinters level %u\n", r
.in
.level
);
4414 status
= dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &r
);
4415 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
4417 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
4418 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
4419 data_blob_clear(&blob
);
4420 r
.in
.buffer
= &blob
;
4421 r
.in
.offered
= needed
;
4422 status
= dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &r
);
4425 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed");
4427 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinters failed");
4429 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
4432 torture_comment(tctx
, "No printers returned\n");
4436 for (j
=0;j
<count
;j
++) {
4437 if (r
.in
.level
== 1) {
4438 char *unc
= talloc_strdup(tctx
, info
[j
].info1
.name
);
4441 if (unc
[0] == '\\' && unc
[1] == '\\') {
4444 slash
= strchr(unc
, '\\');
4449 if (!test_OpenPrinter(tctx
, p
, name
, environment
)) {
4452 if (!test_OpenPrinterEx(tctx
, p
, name
, environment
)) {
4462 static bool test_GetPrinterDriver(struct torture_context
*tctx
,
4463 struct dcerpc_binding_handle
*b
,
4464 struct policy_handle
*handle
,
4465 const char *driver_name
)
4467 struct spoolss_GetPrinterDriver r
;
4470 r
.in
.handle
= handle
;
4471 r
.in
.architecture
= "W32X86";
4475 r
.out
.needed
= &needed
;
4477 torture_comment(tctx
, "Testing GetPrinterDriver level %d\n", r
.in
.level
);
4479 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver_r(b
, tctx
, &r
),
4480 "failed to call GetPrinterDriver");
4481 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
4482 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
4483 data_blob_clear(&blob
);
4484 r
.in
.buffer
= &blob
;
4485 r
.in
.offered
= needed
;
4486 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver_r(b
, tctx
, &r
),
4487 "failed to call GetPrinterDriver");
4490 torture_assert_werr_ok(tctx
, r
.out
.result
,
4491 "failed to call GetPrinterDriver");
4493 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
4498 static bool test_GetPrinterDriver2(struct torture_context
*tctx
,
4499 struct dcerpc_binding_handle
*b
,
4500 struct policy_handle
*handle
,
4501 const char *driver_name
,
4502 const char *architecture
)
4504 struct spoolss_GetPrinterDriver2 r
;
4505 uint16_t levels
[] = {1, 2, 3, 4, 5, 6, 8, 101 };
4507 uint32_t server_major_version
;
4508 uint32_t server_minor_version
;
4511 r
.in
.handle
= handle
;
4512 r
.in
.architecture
= architecture
;
4513 r
.in
.client_major_version
= 3;
4514 r
.in
.client_minor_version
= 0;
4515 r
.out
.needed
= &needed
;
4516 r
.out
.server_major_version
= &server_major_version
;
4517 r
.out
.server_minor_version
= &server_minor_version
;
4519 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
4523 r
.in
.level
= levels
[i
];
4525 torture_comment(tctx
, "Testing GetPrinterDriver2(%s) level %d\n",
4526 driver_name
, r
.in
.level
);
4528 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver2_r(b
, tctx
, &r
),
4529 "failed to call GetPrinterDriver2");
4530 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
4531 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
4532 data_blob_clear(&blob
);
4533 r
.in
.buffer
= &blob
;
4534 r
.in
.offered
= needed
;
4535 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_GetPrinterDriver2_r(b
, tctx
, &r
),
4536 "failed to call GetPrinterDriver2");
4539 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INVALID_LEVEL
)) {
4540 switch (r
.in
.level
) {
4549 torture_assert_werr_ok(tctx
, r
.out
.result
,
4550 "failed to call GetPrinterDriver2");
4552 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo
, r
.out
.info
, r
.in
.level
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
4558 static bool test_EnumPrinterDrivers_old(struct torture_context
*tctx
,
4559 struct dcerpc_pipe
*p
,
4560 const char *environment
)
4562 struct spoolss_EnumPrinterDrivers r
;
4564 uint16_t levels
[] = {1, 2, 3, 4, 5, 6};
4566 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4568 for (i
=0;i
<ARRAY_SIZE(levels
);i
++) {
4572 union spoolss_DriverInfo
*info
;
4574 r
.in
.server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
4575 r
.in
.environment
= environment
;
4576 r
.in
.level
= levels
[i
];
4579 r
.out
.needed
= &needed
;
4580 r
.out
.count
= &count
;
4583 torture_comment(tctx
, "Testing EnumPrinterDrivers level %u\n", r
.in
.level
);
4585 status
= dcerpc_spoolss_EnumPrinterDrivers_r(b
, tctx
, &r
);
4587 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterDrivers failed");
4589 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
4590 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
4591 data_blob_clear(&blob
);
4592 r
.in
.buffer
= &blob
;
4593 r
.in
.offered
= needed
;
4594 status
= dcerpc_spoolss_EnumPrinterDrivers_r(b
, tctx
, &r
);
4597 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterDrivers failed");
4599 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumPrinterDrivers failed");
4602 torture_comment(tctx
, "No printer drivers returned\n");
4606 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers
, info
, r
.in
.level
, count
, lp_iconv_convenience(tctx
->lp_ctx
), needed
, 4);
4612 static bool test_DeletePrinter(struct torture_context
*tctx
,
4613 struct dcerpc_binding_handle
*b
,
4614 struct policy_handle
*handle
)
4616 struct spoolss_DeletePrinter r
;
4618 torture_comment(tctx
, "Testing DeletePrinter\n");
4620 r
.in
.handle
= handle
;
4622 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_DeletePrinter_r(b
, tctx
, &r
),
4623 "failed to delete printer");
4624 torture_assert_werr_ok(tctx
, r
.out
.result
,
4625 "failed to delete printer");
4630 static bool test_EnumPrinters_findname(struct torture_context
*tctx
,
4631 struct dcerpc_binding_handle
*b
,
4637 struct spoolss_EnumPrinters e
;
4639 union spoolss_PrinterInfo
*info
;
4650 e
.out
.count
= &count
;
4652 e
.out
.needed
= &needed
;
4654 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &e
),
4655 "failed to enum printers");
4657 if (W_ERROR_EQUAL(e
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
4658 DATA_BLOB blob
= data_blob_talloc(tctx
, NULL
, needed
);
4659 data_blob_clear(&blob
);
4660 e
.in
.buffer
= &blob
;
4661 e
.in
.offered
= needed
;
4663 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &e
),
4664 "failed to enum printers");
4667 torture_assert_werr_ok(tctx
, e
.out
.result
,
4668 "failed to enum printers");
4670 for (i
=0; i
< count
; i
++) {
4672 const char *current
= NULL
;
4677 current
= info
[i
].info1
.name
;
4681 if (strequal(current
, name
)) {
4686 q
= strrchr(current
, '\\');
4689 torture_warning(tctx
,
4690 "server returns printername %s incl. servername although we did not set servername", current
);
4693 if (strequal(q
, name
)) {
4703 static bool test_AddPrinter_wellknown(struct torture_context
*tctx
,
4704 struct dcerpc_pipe
*p
,
4705 const char *printername
,
4709 struct spoolss_AddPrinter r
;
4710 struct spoolss_AddPrinterEx rex
;
4711 struct spoolss_SetPrinterInfoCtr info_ctr
;
4712 struct spoolss_SetPrinterInfo1 info1
;
4713 struct spoolss_DevmodeContainer devmode_ctr
;
4714 struct sec_desc_buf secdesc_ctr
;
4715 struct spoolss_UserLevelCtr userlevel_ctr
;
4716 struct policy_handle handle
;
4718 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4720 ZERO_STRUCT(devmode_ctr
);
4721 ZERO_STRUCT(secdesc_ctr
);
4722 ZERO_STRUCT(userlevel_ctr
);
4725 torture_comment(tctx
, "Testing AddPrinter%s level 1\n", ex
? "Ex":"");
4727 /* try to add printer to wellknown printer list (level 1) */
4729 userlevel_ctr
.level
= 1;
4731 info_ctr
.info
.info1
= &info1
;
4734 rex
.in
.server
= NULL
;
4735 rex
.in
.info_ctr
= &info_ctr
;
4736 rex
.in
.devmode_ctr
= &devmode_ctr
;
4737 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
4738 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
4739 rex
.out
.handle
= &handle
;
4742 r
.in
.info_ctr
= &info_ctr
;
4743 r
.in
.devmode_ctr
= &devmode_ctr
;
4744 r
.in
.secdesc_ctr
= &secdesc_ctr
;
4745 r
.out
.handle
= &handle
;
4747 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
4748 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
4749 "failed to add printer");
4750 result
= ex
? rex
.out
.result
: r
.out
.result
;
4751 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
4752 "unexpected result code");
4754 info1
.name
= printername
;
4755 info1
.flags
= PRINTER_ATTRIBUTE_SHARED
;
4757 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
4758 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
4759 "failed to add printer");
4760 result
= ex
? rex
.out
.result
: r
.out
.result
;
4761 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
4762 "unexpected result code");
4764 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
4765 better do a real check to see the printer is really there */
4767 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, b
,
4768 PRINTER_ENUM_NETWORK
, 1,
4771 "failed to enum printers");
4773 torture_assert(tctx
, found
, "failed to find newly added printer");
4777 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
4778 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
4779 "failed to add printer");
4780 result
= ex
? rex
.out
.result
: r
.out
.result
;
4781 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
4782 "unexpected result code");
4784 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
4785 better do a real check to see the printer has really been removed
4786 from the well known printer list */
4790 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, b
,
4791 PRINTER_ENUM_NETWORK
, 1,
4794 "failed to enum printers");
4796 torture_assert(tctx
, !found
, "printer still in well known printer list");
4801 static bool test_AddPrinter_normal(struct torture_context
*tctx
,
4802 struct dcerpc_pipe
*p
,
4803 struct policy_handle
*handle_p
,
4804 const char *printername
,
4805 const char *drivername
,
4806 const char *portname
,
4810 struct spoolss_AddPrinter r
;
4811 struct spoolss_AddPrinterEx rex
;
4812 struct spoolss_SetPrinterInfoCtr info_ctr
;
4813 struct spoolss_SetPrinterInfo2 info2
;
4814 struct spoolss_DevmodeContainer devmode_ctr
;
4815 struct sec_desc_buf secdesc_ctr
;
4816 struct spoolss_UserLevelCtr userlevel_ctr
;
4817 struct policy_handle handle
;
4819 bool existing_printer_deleted
= false;
4820 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
4822 ZERO_STRUCT(devmode_ctr
);
4823 ZERO_STRUCT(secdesc_ctr
);
4824 ZERO_STRUCT(userlevel_ctr
);
4826 torture_comment(tctx
, "Testing AddPrinter%s level 2\n", ex
? "Ex":"");
4828 userlevel_ctr
.level
= 1;
4830 rex
.in
.server
= NULL
;
4831 rex
.in
.info_ctr
= &info_ctr
;
4832 rex
.in
.devmode_ctr
= &devmode_ctr
;
4833 rex
.in
.secdesc_ctr
= &secdesc_ctr
;
4834 rex
.in
.userlevel_ctr
= &userlevel_ctr
;
4835 rex
.out
.handle
= &handle
;
4838 r
.in
.info_ctr
= &info_ctr
;
4839 r
.in
.devmode_ctr
= &devmode_ctr
;
4840 r
.in
.secdesc_ctr
= &secdesc_ctr
;
4841 r
.out
.handle
= &handle
;
4845 /* try to add printer to printer list (level 2) */
4849 info_ctr
.info
.info2
= &info2
;
4852 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
4853 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
4854 "failed to add printer");
4855 result
= ex
? rex
.out
.result
: r
.out
.result
;
4856 torture_assert_werr_equal(tctx
, result
, WERR_INVALID_PRINTER_NAME
,
4857 "unexpected result code");
4859 info2
.printername
= printername
;
4861 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
4862 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
4863 "failed to add printer");
4864 result
= ex
? rex
.out
.result
: r
.out
.result
;
4866 if (W_ERROR_EQUAL(result
, WERR_PRINTER_ALREADY_EXISTS
)) {
4867 struct policy_handle printer_handle
;
4869 if (existing_printer_deleted
) {
4870 torture_fail(tctx
, "already deleted printer still existing?");
4873 torture_assert(tctx
, call_OpenPrinterEx(tctx
, p
, printername
, NULL
, &printer_handle
),
4874 "failed to open printer handle");
4876 torture_assert(tctx
, test_DeletePrinter(tctx
, b
, &printer_handle
),
4877 "failed to delete printer");
4879 torture_assert(tctx
, test_ClosePrinter(tctx
, b
, &printer_handle
),
4880 "failed to close server handle");
4882 existing_printer_deleted
= true;
4887 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PORT
,
4888 "unexpected result code");
4890 info2
.portname
= portname
;
4892 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
4893 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
4894 "failed to add printer");
4895 result
= ex
? rex
.out
.result
: r
.out
.result
;
4896 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTER_DRIVER
,
4897 "unexpected result code");
4899 info2
.drivername
= drivername
;
4901 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
4902 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
4903 "failed to add printer");
4904 result
= ex
? rex
.out
.result
: r
.out
.result
;
4906 /* w2k8r2 allows to add printer w/o defining printprocessor */
4908 if (!W_ERROR_IS_OK(result
)) {
4909 torture_assert_werr_equal(tctx
, result
, WERR_UNKNOWN_PRINTPROCESSOR
,
4910 "unexpected result code");
4912 info2
.printprocessor
= "winprint";
4914 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
4915 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
4916 "failed to add printer");
4917 result
= ex
? rex
.out
.result
: r
.out
.result
;
4918 torture_assert_werr_ok(tctx
, result
,
4919 "failed to add printer");
4924 /* we are paranoid, really check if the printer is there now */
4926 torture_assert(tctx
, test_EnumPrinters_findname(tctx
, b
,
4927 PRINTER_ENUM_LOCAL
, 1,
4930 "failed to enum printers");
4931 torture_assert(tctx
, found
, "failed to find newly added printer");
4933 torture_assert_ntstatus_ok(tctx
, ex
? dcerpc_spoolss_AddPrinterEx_r(b
, tctx
, &rex
) :
4934 dcerpc_spoolss_AddPrinter_r(b
, tctx
, &r
),
4935 "failed to add printer");
4936 result
= ex
? rex
.out
.result
: r
.out
.result
;
4937 torture_assert_werr_equal(tctx
, result
, WERR_PRINTER_ALREADY_EXISTS
,
4938 "unexpected result code");
4943 static bool test_AddPrinterEx(struct torture_context
*tctx
,
4944 struct dcerpc_pipe
*p
,
4945 struct policy_handle
*handle_p
,
4946 const char *printername
,
4947 const char *drivername
,
4948 const char *portname
)
4952 if (!torture_setting_bool(tctx
, "samba3", false)) {
4953 if (!test_AddPrinter_wellknown(tctx
, p
, TORTURE_WELLKNOWN_PRINTER_EX
, true)) {
4954 torture_comment(tctx
, "failed to add printer to well known list\n");
4959 if (!test_AddPrinter_normal(tctx
, p
, handle_p
,
4960 printername
, drivername
, portname
,
4962 torture_comment(tctx
, "failed to add printer to printer list\n");
4969 static bool test_AddPrinter(struct torture_context
*tctx
,
4970 struct dcerpc_pipe
*p
,
4971 struct policy_handle
*handle_p
,
4972 const char *printername
,
4973 const char *drivername
,
4974 const char *portname
)
4978 if (!torture_setting_bool(tctx
, "samba3", false)) {
4979 if (!test_AddPrinter_wellknown(tctx
, p
, TORTURE_WELLKNOWN_PRINTER
, false)) {
4980 torture_comment(tctx
, "failed to add printer to well known list\n");
4985 if (!test_AddPrinter_normal(tctx
, p
, handle_p
,
4986 printername
, drivername
, portname
,
4988 torture_comment(tctx
, "failed to add printer to printer list\n");
4995 static bool test_printer_info(struct torture_context
*tctx
,
4996 struct dcerpc_binding_handle
*b
,
4997 struct policy_handle
*handle
)
5001 if (torture_setting_bool(tctx
, "samba3", false)) {
5002 torture_skip(tctx
, "skipping printer info cross tests against samba 3");
5005 if (!test_PrinterInfo(tctx
, b
, handle
)) {
5009 if (!test_SetPrinter_errors(tctx
, b
, handle
)) {
5016 static bool test_EnumPrinterKey(struct torture_context
*tctx
,
5017 struct dcerpc_binding_handle
*b
,
5018 struct policy_handle
*handle
,
5019 const char *key_name
,
5020 const char ***array
)
5022 struct spoolss_EnumPrinterKey r
;
5023 uint32_t needed
= 0;
5024 union spoolss_KeyNames key_buffer
;
5025 int32_t offered
[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
5029 r
.in
.handle
= handle
;
5030 r
.in
.key_name
= key_name
;
5031 r
.out
.key_buffer
= &key_buffer
;
5032 r
.out
.needed
= &needed
;
5033 r
.out
._ndr_size
= &_ndr_size
;
5035 for (i
=0; i
< ARRAY_SIZE(offered
); i
++) {
5037 if (offered
[i
] < 0 && needed
) {
5041 r
.in
.offered
= needed
+ offered
[i
];
5043 r
.in
.offered
= offered
[i
];
5046 ZERO_STRUCT(key_buffer
);
5048 torture_comment(tctx
, "Testing EnumPrinterKey(%s) with %d offered\n", r
.in
.key_name
, r
.in
.offered
);
5050 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterKey_r(b
, tctx
, &r
),
5051 "failed to call EnumPrinterKey");
5052 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
5054 torture_assert(tctx
, (_ndr_size
== r
.in
.offered
/2),
5055 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
5056 _ndr_size
, r
.in
.offered
/2));
5058 r
.in
.offered
= needed
;
5059 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinterKey_r(b
, tctx
, &r
),
5060 "failed to call EnumPrinterKey");
5063 if (offered
[i
] > 0) {
5064 torture_assert_werr_ok(tctx
, r
.out
.result
,
5065 "failed to call EnumPrinterKey");
5068 torture_assert(tctx
, (_ndr_size
== r
.in
.offered
/2),
5069 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
5070 _ndr_size
, r
.in
.offered
/2));
5072 torture_assert(tctx
, (*r
.out
.needed
<= r
.in
.offered
),
5073 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r
.out
.needed
, r
.in
.offered
));
5075 torture_assert(tctx
, (*r
.out
.needed
<= _ndr_size
* 2),
5076 talloc_asprintf(tctx
, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r
.out
.needed
, _ndr_size
));
5078 if (key_buffer
.string_array
) {
5079 uint32_t calc_needed
= 0;
5081 for (s
=0; key_buffer
.string_array
[s
]; s
++) {
5082 calc_needed
+= strlen_m_term(key_buffer
.string_array
[s
])*2;
5084 if (!key_buffer
.string_array
[0]) {
5089 torture_assert_int_equal(tctx
, *r
.out
.needed
, calc_needed
,
5090 "EnumPrinterKey unexpected size");
5095 *array
= key_buffer
.string_array
;
5101 bool test_printer_keys(struct torture_context
*tctx
,
5102 struct dcerpc_binding_handle
*b
,
5103 struct policy_handle
*handle
)
5105 const char **key_array
= NULL
;
5108 torture_comment(tctx
, "Testing Printer Keys\n");
5110 torture_assert(tctx
, test_EnumPrinterKey(tctx
, b
, handle
, "", &key_array
),
5111 "failed to call test_EnumPrinterKey");
5113 for (i
=0; key_array
&& key_array
[i
]; i
++) {
5114 torture_assert(tctx
, test_EnumPrinterKey(tctx
, b
, handle
, key_array
[i
], NULL
),
5115 "failed to call test_EnumPrinterKey");
5117 for (i
=0; key_array
&& key_array
[i
]; i
++) {
5118 torture_assert(tctx
, test_EnumPrinterDataEx(tctx
, b
, handle
, key_array
[i
], NULL
, NULL
),
5119 "failed to call test_EnumPrinterDataEx");
5122 torture_comment(tctx
, "Printer Keys test succeeded\n\n");
5127 static bool test_one_printer(struct torture_context
*tctx
,
5128 struct dcerpc_pipe
*p
,
5129 struct policy_handle
*handle
,
5133 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5135 if (!test_printer_info(tctx
, b
, handle
)) {
5139 if (!test_PrinterInfo_SD(tctx
, b
, handle
)) {
5143 if (!test_PrinterInfo_DevMode(tctx
, p
, handle
, name
)) {
5147 if (!test_ChangeID(tctx
, p
, handle
)) {
5151 if (!test_printer_keys(tctx
, b
, handle
)) {
5155 if (!test_EnumPrinterData_consistency(tctx
, p
, handle
)) {
5159 if (!test_SetPrinterDataEx_matrix(tctx
, p
, handle
, name
, NULL
, NULL
)) {
5163 if (!test_PrinterData_winreg(tctx
, p
, handle
, name
)) {
5167 if (!test_printer_rename(tctx
, p
, handle
, name
)) {
5174 static bool test_printer(struct torture_context
*tctx
,
5175 struct dcerpc_pipe
*p
)
5178 struct policy_handle handle
[2];
5180 const char *drivername
= "Microsoft XPS Document Writer";
5181 const char *portname
= "LPT1:";
5182 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5184 /* test printer created via AddPrinter */
5186 if (!test_AddPrinter(tctx
, p
, &handle
[0], TORTURE_PRINTER
, drivername
, portname
)) {
5190 if (!test_one_printer(tctx
, p
, &handle
[0], TORTURE_PRINTER
)) {
5194 if (!test_DeletePrinter(tctx
, b
, &handle
[0])) {
5198 if (!test_EnumPrinters_findname(tctx
, b
, PRINTER_ENUM_LOCAL
, 1,
5199 TORTURE_PRINTER
, &found
)) {
5203 torture_assert(tctx
, !found
, "deleted printer still there");
5205 /* test printer created via AddPrinterEx */
5207 if (!test_AddPrinterEx(tctx
, p
, &handle
[1], TORTURE_PRINTER_EX
, drivername
, portname
)) {
5211 if (!test_one_printer(tctx
, p
, &handle
[1], TORTURE_PRINTER_EX
)) {
5215 if (!test_DeletePrinter(tctx
, b
, &handle
[1])) {
5219 if (!test_EnumPrinters_findname(tctx
, b
, PRINTER_ENUM_LOCAL
, 1,
5220 TORTURE_PRINTER_EX
, &found
)) {
5224 torture_assert(tctx
, !found
, "deleted printer still there");
5229 static bool test_architecture_buffer(struct torture_context
*tctx
,
5230 struct dcerpc_pipe
*p
)
5232 struct spoolss_OpenPrinterEx r
;
5233 struct spoolss_UserLevel1 u1
;
5234 struct policy_handle handle
;
5235 uint32_t architectures
[] = {
5236 PROCESSOR_ARCHITECTURE_INTEL
,
5237 PROCESSOR_ARCHITECTURE_IA64
,
5238 PROCESSOR_ARCHITECTURE_AMD64
5242 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
5244 for (i
=0; i
< ARRAY_SIZE(architectures
); i
++) {
5246 torture_comment(tctx
, "Testing OpenPrinterEx with architecture %d\n", architectures
[i
]);
5254 u1
.processor
= architectures
[i
];
5256 r
.in
.printername
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
5257 r
.in
.datatype
= NULL
;
5258 r
.in
.devmode_ctr
.devmode
= NULL
;
5259 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
5261 r
.in
.userlevel
.level1
= &u1
;
5262 r
.out
.handle
= &handle
;
5264 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_OpenPrinterEx_r(b
, tctx
, &r
), "");
5265 torture_assert_werr_ok(tctx
, r
.out
.result
, "");
5268 struct spoolss_EnumPrinters e
;
5270 union spoolss_PrinterInfo
*info
;
5272 e
.in
.flags
= PRINTER_ENUM_LOCAL
;
5277 e
.out
.count
= &count
;
5279 e
.out
.needed
= &needed
[i
];
5281 torture_assert_ntstatus_ok(tctx
, dcerpc_spoolss_EnumPrinters_r(b
, tctx
, &e
), "");
5283 torture_comment(tctx
, "needed was %d\n", needed
[i
]);
5287 torture_assert(tctx
, test_ClosePrinter(tctx
, b
, &handle
), "");
5290 for (i
=1; i
< ARRAY_SIZE(architectures
); i
++) {
5291 if (needed
[i
-1] != needed
[i
]) {
5293 talloc_asprintf(tctx
, "needed size %d for architecture %d != needed size %d for architecture %d\n",
5294 needed
[i
-1], architectures
[i
-1], needed
[i
], architectures
[i
]));
5301 bool torture_rpc_spoolss(struct torture_context
*torture
)
5304 struct dcerpc_pipe
*p
;
5305 struct dcerpc_binding_handle
*b
;
5307 struct test_spoolss_context
*ctx
;
5308 const char *environment
= SPOOLSS_ARCHITECTURE_NT_X86
;
5310 status
= torture_rpc_connection(torture
, &p
, &ndr_table_spoolss
);
5311 if (!NT_STATUS_IS_OK(status
)) {
5314 b
= p
->binding_handle
;
5316 ctx
= talloc_zero(torture
, struct test_spoolss_context
);
5318 ret
&= test_OpenPrinter_server(torture
, p
, &ctx
->server_handle
);
5319 ret
&= test_GetPrinterData_list(torture
, p
, &ctx
->server_handle
, &environment
);
5320 ret
&= test_EnumForms(torture
, b
, &ctx
->server_handle
, true);
5321 ret
&= test_AddForm(torture
, b
, &ctx
->server_handle
, true);
5322 ret
&= test_EnumPorts(torture
, b
, ctx
);
5323 ret
&= test_GetPrinterDriverDirectory(torture
, p
, ctx
, environment
);
5324 ret
&= test_GetPrintProcessorDirectory(torture
, p
, ctx
, environment
);
5325 ret
&= test_EnumPrinterDrivers(torture
, p
, ctx
, environment
);
5326 ret
&= test_EnumPrinterDrivers(torture
, p
, ctx
, SPOOLSS_ARCHITECTURE_ALL
);
5327 ret
&= test_EnumMonitors(torture
, b
, ctx
);
5328 ret
&= test_EnumPrintProcessors(torture
, b
, ctx
, environment
);
5329 ret
&= test_EnumPrintProcDataTypes(torture
, b
, ctx
);
5330 ret
&= test_EnumPrinters(torture
, b
, ctx
);
5331 ret
&= test_OpenPrinter_badname(torture
, b
, "__INVALID_PRINTER__");
5332 ret
&= test_OpenPrinter_badname(torture
, b
, "\\\\__INVALID_HOST__");
5333 ret
&= test_OpenPrinter_badname(torture
, b
, "");
5334 ret
&= test_OpenPrinter_badname(torture
, b
, "\\\\\\");
5335 ret
&= test_OpenPrinter_badname(torture
, b
, "\\\\\\__INVALID_PRINTER__");
5336 ret
&= test_OpenPrinter_badname(torture
, b
, talloc_asprintf(torture
, "\\\\%s\\", dcerpc_server_name(p
)));
5337 ret
&= test_OpenPrinter_badname(torture
, b
,
5338 talloc_asprintf(torture
, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p
)));
5341 ret
&= test_AddPort(torture
, p
);
5342 ret
&= test_EnumPorts_old(torture
, p
);
5343 ret
&= test_EnumPrinters_old(torture
, p
, environment
);
5344 ret
&= test_EnumPrinterDrivers_old(torture
, p
, environment
);
5345 ret
&= test_architecture_buffer(torture
, p
);
5350 struct torture_suite
*torture_rpc_spoolss_printer(TALLOC_CTX
*mem_ctx
)
5352 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "SPOOLSS-PRINTER");
5354 struct torture_rpc_tcase
*tcase
= torture_suite_add_rpc_iface_tcase(suite
,
5355 "printer", &ndr_table_spoolss
);
5357 torture_rpc_tcase_add_test(tcase
, "printer", test_printer
);