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_security.h"
30 #include "libcli/security/security.h"
31 #include "torture/rpc/rpc.h"
32 #include "param/param.h"
33 #include "lib/registry/registry.h"
35 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
36 #define TORTURE_PRINTER "torture_printer"
37 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
38 #define TORTURE_PRINTER_EX "torture_printer_ex"
40 struct test_spoolss_context {
41 /* print server handle */
42 struct policy_handle server_handle;
45 uint32_t port_count[3];
46 union spoolss_PortInfo *ports[3];
48 /* for EnumPrinterDrivers */
49 uint32_t driver_count[8];
50 union spoolss_DriverInfo *drivers[8];
52 /* for EnumMonitors */
53 uint32_t monitor_count[3];
54 union spoolss_MonitorInfo *monitors[3];
56 /* for EnumPrintProcessors */
57 uint32_t print_processor_count[2];
58 union spoolss_PrintProcessorInfo *print_processors[2];
60 /* for EnumPrinters */
61 uint32_t printer_count[6];
62 union spoolss_PrinterInfo *printers[6];
65 #define COMPARE_STRING(tctx, c,r,e) \
66 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
68 /* not every compiler supports __typeof__() */
70 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
71 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
72 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
74 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
75 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
79 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
82 #define COMPARE_UINT32(tctx, c, r, e) do {\
83 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
84 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
87 #define COMPARE_UINT64(tctx, c, r, e) do {\
88 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
89 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
93 #define COMPARE_NTTIME(tctx, c, r, e) do {\
94 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
95 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
98 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
100 if (!c.e && !r.e) { \
104 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
107 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
109 for (__i=0;c.e[__i] != NULL; __i++) { \
110 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
114 #define CHECK_ALIGN(size, n) do {\
116 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
117 size, n, size + n - (size % n));\
121 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
123 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, ic, needed, align) do { \
124 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
125 uint32_t size = ndr_size_##fn##_info(tctx, ic, level, count, info);\
126 uint32_t round_size = DO_ROUND(size, align);\
127 if (round_size != needed) {\
128 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
129 CHECK_ALIGN(size, align);\
134 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, ic, needed, align) do { \
135 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
136 uint32_t size = ndr_size_##fn##_info(tctx, ic, count, info);\
137 uint32_t round_size = DO_ROUND(size, align);\
138 if (round_size != needed) {\
139 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
140 CHECK_ALIGN(size, align);\
145 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, ic, needed, align) do { \
146 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
147 uint32_t size = ndr_size_##fn(info, level, ic, 0);\
148 uint32_t round_size = DO_ROUND(size, align);\
149 if (round_size != needed) {\
150 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
151 CHECK_ALIGN(size, align);\
156 static bool test_OpenPrinter_server(struct torture_context *tctx,
157 struct dcerpc_pipe *p,
158 struct policy_handle *server_handle)
161 struct spoolss_OpenPrinter op;
163 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
164 op.in.datatype = NULL;
165 op.in.devmode_ctr.devmode= NULL;
166 op.in.access_mask = 0;
167 op.out.handle = server_handle;
169 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
171 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
172 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
173 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
178 static bool test_EnumPorts(struct torture_context *tctx,
179 struct dcerpc_pipe *p,
180 struct test_spoolss_context *ctx)
183 struct spoolss_EnumPorts r;
184 uint16_t levels[] = { 1, 2 };
187 for (i=0;i<ARRAY_SIZE(levels);i++) {
188 int level = levels[i];
192 union spoolss_PortInfo *info;
194 r.in.servername = "";
198 r.out.needed = &needed;
199 r.out.count = &count;
202 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
204 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
205 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
206 if (W_ERROR_IS_OK(r.out.result)) {
207 /* TODO: do some more checks here */
210 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
211 "EnumPorts unexpected return code");
213 blob = data_blob_talloc(ctx, NULL, needed);
214 data_blob_clear(&blob);
216 r.in.offered = needed;
218 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
219 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
221 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
223 torture_assert(tctx, info, "EnumPorts returned no info");
225 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
227 ctx->port_count[level] = count;
228 ctx->ports[level] = info;
231 for (i=1;i<ARRAY_SIZE(levels);i++) {
232 int level = levels[i];
233 int old_level = levels[i-1];
234 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
235 "EnumPorts invalid value");
237 /* if the array sizes are not the same we would maybe segfault in the following code */
239 for (i=0;i<ARRAY_SIZE(levels);i++) {
240 int level = levels[i];
241 for (j=0;j<ctx->port_count[level];j++) {
242 union spoolss_PortInfo *cur = &ctx->ports[level][j];
243 union spoolss_PortInfo *ref = &ctx->ports[2][j];
246 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
249 /* level 2 is our reference, and it makes no sense to compare it to itself */
258 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
259 struct dcerpc_pipe *p,
260 struct test_spoolss_context *ctx,
261 const char *environment)
264 struct spoolss_GetPrintProcessorDirectory r;
279 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
282 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
288 for (i=0;i<ARRAY_SIZE(levels);i++) {
289 int level = levels[i].level;
292 r.in.server = levels[i].server;
293 r.in.environment = environment;
297 r.out.needed = &needed;
299 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
301 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
302 torture_assert_ntstatus_ok(tctx, status,
303 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
304 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
305 "GetPrintProcessorDirectory unexpected return code");
307 blob = data_blob_talloc(ctx, NULL, needed);
308 data_blob_clear(&blob);
310 r.in.offered = needed;
312 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
313 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
315 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
317 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
324 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
325 struct dcerpc_pipe *p,
326 struct test_spoolss_context *ctx,
327 const char *environment)
330 struct spoolss_GetPrinterDriverDirectory r;
345 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
348 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
354 for (i=0;i<ARRAY_SIZE(levels);i++) {
355 int level = levels[i].level;
358 r.in.server = levels[i].server;
359 r.in.environment = environment;
363 r.out.needed = &needed;
365 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
367 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
368 torture_assert_ntstatus_ok(tctx, status,
369 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
370 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
371 "GetPrinterDriverDirectory unexpected return code");
373 blob = data_blob_talloc(ctx, NULL, needed);
374 data_blob_clear(&blob);
376 r.in.offered = needed;
378 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
379 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
381 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
383 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
389 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
390 struct dcerpc_pipe *p,
391 struct test_spoolss_context *ctx,
392 const char *architecture)
395 struct spoolss_EnumPrinterDrivers r;
396 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
399 for (i=0;i<ARRAY_SIZE(levels);i++) {
400 int level = levels[i];
404 union spoolss_DriverInfo *info;
406 /* FIXME: gd, come back and fix "" as server, and handle
407 * priority of returned error codes in torture test and samba 3
410 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
411 r.in.environment = architecture;
415 r.out.needed = &needed;
416 r.out.count = &count;
419 torture_comment(tctx, "Testing EnumPrinterDrivers level %u (%s)\n", r.in.level, r.in.environment);
421 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
422 torture_assert_ntstatus_ok(tctx, status,
423 "dcerpc_spoolss_EnumPrinterDrivers failed");
424 if (W_ERROR_IS_OK(r.out.result)) {
425 /* TODO: do some more checks here */
428 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
429 blob = data_blob_talloc(ctx, NULL, needed);
430 data_blob_clear(&blob);
432 r.in.offered = needed;
434 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
435 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
438 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
440 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
442 ctx->driver_count[level] = count;
443 ctx->drivers[level] = info;
446 for (i=1;i<ARRAY_SIZE(levels);i++) {
447 int level = levels[i];
448 int old_level = levels[i-1];
450 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
451 "EnumPrinterDrivers invalid value");
454 for (i=0;i<ARRAY_SIZE(levels);i++) {
455 int level = levels[i];
457 for (j=0;j<ctx->driver_count[level];j++) {
458 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
459 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
463 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
466 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
467 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
468 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
469 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
470 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
471 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
474 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
475 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
476 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
477 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
478 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
479 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
480 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
481 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
482 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
483 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
486 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
487 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
488 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
489 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
490 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
491 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
492 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
493 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
494 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
495 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
496 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
499 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
500 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
501 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
502 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
503 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
504 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
505 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
506 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
507 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
510 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
511 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
512 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
513 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
514 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
515 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
516 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
517 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
518 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
519 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
520 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
521 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
522 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
523 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
524 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
525 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
526 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
529 /* level 8 is our reference, and it makes no sense to compare it to itself */
538 static bool test_EnumMonitors(struct torture_context *tctx,
539 struct dcerpc_pipe *p,
540 struct test_spoolss_context *ctx)
543 struct spoolss_EnumMonitors r;
544 uint16_t levels[] = { 1, 2 };
547 for (i=0;i<ARRAY_SIZE(levels);i++) {
548 int level = levels[i];
552 union spoolss_MonitorInfo *info;
554 r.in.servername = "";
558 r.out.needed = &needed;
559 r.out.count = &count;
562 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
564 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
565 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
566 if (W_ERROR_IS_OK(r.out.result)) {
567 /* TODO: do some more checks here */
570 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
571 "EnumMonitors failed");
573 blob = data_blob_talloc(ctx, NULL, needed);
574 data_blob_clear(&blob);
576 r.in.offered = needed;
578 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
579 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
581 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
583 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
585 ctx->monitor_count[level] = count;
586 ctx->monitors[level] = info;
589 for (i=1;i<ARRAY_SIZE(levels);i++) {
590 int level = levels[i];
591 int old_level = levels[i-1];
592 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
593 "EnumMonitors invalid value");
596 for (i=0;i<ARRAY_SIZE(levels);i++) {
597 int level = levels[i];
598 for (j=0;j<ctx->monitor_count[level];j++) {
599 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
600 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
603 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
606 /* level 2 is our reference, and it makes no sense to compare it to itself */
615 static bool test_EnumPrintProcessors(struct torture_context *tctx,
616 struct dcerpc_pipe *p,
617 struct test_spoolss_context *ctx,
618 const char *environment)
621 struct spoolss_EnumPrintProcessors r;
622 uint16_t levels[] = { 1 };
625 for (i=0;i<ARRAY_SIZE(levels);i++) {
626 int level = levels[i];
630 union spoolss_PrintProcessorInfo *info;
632 r.in.servername = "";
633 r.in.environment = environment;
637 r.out.needed = &needed;
638 r.out.count = &count;
641 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
643 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
644 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
645 if (W_ERROR_IS_OK(r.out.result)) {
646 /* TODO: do some more checks here */
649 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
650 "EnumPrintProcessors unexpected return code");
652 blob = data_blob_talloc(ctx, NULL, needed);
653 data_blob_clear(&blob);
655 r.in.offered = needed;
657 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
658 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
660 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
662 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
664 ctx->print_processor_count[level] = count;
665 ctx->print_processors[level] = info;
668 for (i=1;i<ARRAY_SIZE(levels);i++) {
669 int level = levels[i];
670 int old_level = levels[i-1];
671 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
672 "EnumPrintProcessors failed");
675 for (i=0;i<ARRAY_SIZE(levels);i++) {
676 int level = levels[i];
677 for (j=0;j<ctx->print_processor_count[level];j++) {
679 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
680 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
684 /* level 1 is our reference, and it makes no sense to compare it to itself */
693 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
694 struct dcerpc_pipe *p,
695 struct test_spoolss_context *ctx)
698 struct spoolss_EnumPrintProcDataTypes r;
699 uint16_t levels[] = { 1 };
702 for (i=0;i<ARRAY_SIZE(levels);i++) {
703 int level = levels[i];
707 union spoolss_PrintProcDataTypesInfo *info;
709 r.in.servername = "";
710 r.in.print_processor_name = "winprint";
714 r.out.needed = &needed;
715 r.out.count = &count;
718 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
720 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
721 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
722 if (W_ERROR_IS_OK(r.out.result)) {
723 /* TODO: do some more checks here */
726 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
727 "EnumPrintProcDataTypes unexpected return code");
729 blob = data_blob_talloc(ctx, NULL, needed);
730 data_blob_clear(&blob);
732 r.in.offered = needed;
734 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
735 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
737 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
739 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
747 static bool test_EnumPrinters(struct torture_context *tctx,
748 struct dcerpc_pipe *p,
749 struct test_spoolss_context *ctx)
751 struct spoolss_EnumPrinters r;
753 uint16_t levels[] = { 0, 1, 2, 4, 5 };
756 for (i=0;i<ARRAY_SIZE(levels);i++) {
757 int level = levels[i];
761 union spoolss_PrinterInfo *info;
763 r.in.flags = PRINTER_ENUM_LOCAL;
768 r.out.needed = &needed;
769 r.out.count = &count;
772 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
774 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
775 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters 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 "EnumPrinters 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_EnumPrinters(p, ctx, &r);
789 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
791 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
793 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
795 ctx->printer_count[level] = count;
796 ctx->printers[level] = info;
799 for (i=1;i<ARRAY_SIZE(levels);i++) {
800 int level = levels[i];
801 int old_level = levels[i-1];
802 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
803 "EnumPrinters invalid value");
806 for (i=0;i<ARRAY_SIZE(levels);i++) {
807 int level = levels[i];
808 for (j=0;j<ctx->printer_count[level];j++) {
809 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
810 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
813 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
814 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
815 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
816 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
817 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
818 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
819 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
820 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
821 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
822 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
823 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
824 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
825 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
826 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
827 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
828 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
829 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
830 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
831 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
832 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
833 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
834 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
835 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
836 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
837 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
838 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
839 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
840 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
841 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
844 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
845 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
846 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
847 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
850 /* level 2 is our reference, and it makes no sense to compare it to itself */
853 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
854 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
855 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
858 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
859 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
860 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
861 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
862 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
869 * - verify that the port of a printer was in the list returned by EnumPorts
875 static bool test_GetPrinterDriver2(struct torture_context *tctx,
876 struct dcerpc_pipe *p,
877 struct policy_handle *handle,
878 const char *driver_name,
879 const char *environment);
881 bool test_GetPrinter_level(struct torture_context *tctx,
882 struct dcerpc_pipe *p,
883 struct policy_handle *handle,
885 union spoolss_PrinterInfo *info)
887 struct spoolss_GetPrinter r;
890 r.in.handle = handle;
894 r.out.needed = &needed;
896 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
898 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter(p, tctx, &r),
899 "GetPrinter failed");
901 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
902 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
903 data_blob_clear(&blob);
905 r.in.offered = needed;
907 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter(p, tctx, &r),
908 "GetPrinter failed");
911 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
913 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
915 if (info && r.out.info) {
923 static bool test_GetPrinter(struct torture_context *tctx,
924 struct dcerpc_pipe *p,
925 struct policy_handle *handle,
926 const char *environment)
928 uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
931 for (i=0;i<ARRAY_SIZE(levels);i++) {
933 union spoolss_PrinterInfo info;
937 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, levels[i], &info),
938 "failed to call GetPrinter");
940 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
942 test_GetPrinterDriver2(tctx, p, handle, info.info2.drivername, environment),
943 "failed to call test_GetPrinterDriver2");
950 static bool test_SetPrinter(struct torture_context *tctx,
951 struct dcerpc_pipe *p,
952 struct policy_handle *handle,
953 struct spoolss_SetPrinterInfoCtr *info_ctr,
954 struct spoolss_DevmodeContainer *devmode_ctr,
955 struct sec_desc_buf *secdesc_ctr,
956 enum spoolss_PrinterControl command)
958 struct spoolss_SetPrinter r;
960 r.in.handle = handle;
961 r.in.info_ctr = info_ctr;
962 r.in.devmode_ctr = devmode_ctr;
963 r.in.secdesc_ctr = secdesc_ctr;
964 r.in.command = command;
966 torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
968 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
969 "failed to call SetPrinter");
970 torture_assert_werr_ok(tctx, r.out.result,
971 "failed to call SetPrinter");
976 static bool test_SetPrinter_errors(struct torture_context *tctx,
977 struct dcerpc_pipe *p,
978 struct policy_handle *handle)
980 struct spoolss_SetPrinter r;
981 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
984 struct spoolss_SetPrinterInfoCtr info_ctr;
985 struct spoolss_DevmodeContainer devmode_ctr;
986 struct sec_desc_buf secdesc_ctr;
989 info_ctr.info.info0 = NULL;
991 ZERO_STRUCT(devmode_ctr);
992 ZERO_STRUCT(secdesc_ctr);
994 r.in.handle = handle;
995 r.in.info_ctr = &info_ctr;
996 r.in.devmode_ctr = &devmode_ctr;
997 r.in.secdesc_ctr = &secdesc_ctr;
1000 torture_comment(tctx, "Testing SetPrinter all zero\n");
1002 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
1003 "failed to call SetPrinter");
1004 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1005 "failed to call SetPrinter");
1008 for (i=0; i < ARRAY_SIZE(levels); i++) {
1010 struct spoolss_SetPrinterInfo0 info0;
1011 struct spoolss_SetPrinterInfo1 info1;
1012 struct spoolss_SetPrinterInfo2 info2;
1013 struct spoolss_SetPrinterInfo3 info3;
1014 struct spoolss_SetPrinterInfo4 info4;
1015 struct spoolss_SetPrinterInfo5 info5;
1016 struct spoolss_SetPrinterInfo6 info6;
1017 struct spoolss_SetPrinterInfo7 info7;
1018 struct spoolss_SetPrinterInfo8 info8;
1019 struct spoolss_SetPrinterInfo9 info9;
1022 info_ctr.level = levels[i];
1023 switch (levels[i]) {
1026 info_ctr.info.info0 = &info0;
1030 info_ctr.info.info1 = &info1;
1034 info_ctr.info.info2 = &info2;
1038 info_ctr.info.info3 = &info3;
1042 info_ctr.info.info4 = &info4;
1046 info_ctr.info.info5 = &info5;
1050 info_ctr.info.info6 = &info6;
1054 info_ctr.info.info7 = &info7;
1058 info_ctr.info.info8 = &info8;
1062 info_ctr.info.info9 = &info9;
1066 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1067 info_ctr.level, r.in.command);
1069 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
1070 "failed to call SetPrinter");
1072 switch (r.in.command) {
1073 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1074 /* is ignored for all levels other then 0 */
1075 if (info_ctr.level > 0) {
1079 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1080 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1081 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1082 if (info_ctr.level > 0) {
1083 /* is invalid for all levels other then 0 */
1084 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1085 "unexpected error code returned");
1088 torture_assert_werr_ok(tctx, r.out.result,
1089 "failed to call SetPrinter with non 0 command");
1094 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1095 /* FIXME: gd needs further investigation */
1097 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1098 "unexpected error code returned");
1102 switch (info_ctr.level) {
1104 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1105 "unexpected error code returned");
1108 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1109 "unexpected error code returned");
1115 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1116 "unexpected error code returned");
1119 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1120 "unexpected error code returned");
1123 torture_assert_werr_ok(tctx, r.out.result,
1124 "failed to call SetPrinter");
1129 if (r.in.command < 5) {
1137 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1139 if ((r->level == 2) && (r->info.info2)) {
1140 r->info.info2->secdesc_ptr = 0;
1141 r->info.info2->devmode_ptr = 0;
1145 static bool test_PrinterInfo(struct torture_context *tctx,
1146 struct dcerpc_pipe *p,
1147 struct policy_handle *handle)
1150 struct spoolss_SetPrinter s;
1151 struct spoolss_GetPrinter q;
1152 struct spoolss_GetPrinter q0;
1153 struct spoolss_SetPrinterInfoCtr info_ctr;
1154 union spoolss_PrinterInfo info;
1155 struct spoolss_DevmodeContainer devmode_ctr;
1156 struct sec_desc_buf secdesc_ctr;
1161 uint32_t status_list[] = {
1162 /* these do not stick
1163 PRINTER_STATUS_PAUSED,
1164 PRINTER_STATUS_ERROR,
1165 PRINTER_STATUS_PENDING_DELETION, */
1166 PRINTER_STATUS_PAPER_JAM,
1167 PRINTER_STATUS_PAPER_OUT,
1168 PRINTER_STATUS_MANUAL_FEED,
1169 PRINTER_STATUS_PAPER_PROBLEM,
1170 PRINTER_STATUS_OFFLINE,
1171 PRINTER_STATUS_IO_ACTIVE,
1172 PRINTER_STATUS_BUSY,
1173 PRINTER_STATUS_PRINTING,
1174 PRINTER_STATUS_OUTPUT_BIN_FULL,
1175 PRINTER_STATUS_NOT_AVAILABLE,
1176 PRINTER_STATUS_WAITING,
1177 PRINTER_STATUS_PROCESSING,
1178 PRINTER_STATUS_INITIALIZING,
1179 PRINTER_STATUS_WARMING_UP,
1180 PRINTER_STATUS_TONER_LOW,
1181 PRINTER_STATUS_NO_TONER,
1182 PRINTER_STATUS_PAGE_PUNT,
1183 PRINTER_STATUS_USER_INTERVENTION,
1184 PRINTER_STATUS_OUT_OF_MEMORY,
1185 PRINTER_STATUS_DOOR_OPEN,
1186 PRINTER_STATUS_SERVER_UNKNOWN,
1187 PRINTER_STATUS_POWER_SAVE,
1188 /* these do not stick
1197 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1198 uint32_t attribute_list[] = {
1199 PRINTER_ATTRIBUTE_QUEUED,
1200 /* fails with WERR_INVALID_DATATYPE:
1201 PRINTER_ATTRIBUTE_DIRECT, */
1203 PRINTER_ATTRIBUTE_DEFAULT, */
1204 PRINTER_ATTRIBUTE_SHARED,
1206 PRINTER_ATTRIBUTE_NETWORK, */
1207 PRINTER_ATTRIBUTE_HIDDEN,
1208 PRINTER_ATTRIBUTE_LOCAL,
1209 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1210 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1211 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1212 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1214 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1215 /* fails with WERR_INVALID_DATATYPE:
1216 PRINTER_ATTRIBUTE_RAW_ONLY, */
1217 /* these do not stick
1218 PRINTER_ATTRIBUTE_PUBLISHED,
1219 PRINTER_ATTRIBUTE_FAX,
1220 PRINTER_ATTRIBUTE_TS,
1239 ZERO_STRUCT(devmode_ctr);
1240 ZERO_STRUCT(secdesc_ctr);
1242 s.in.handle = handle;
1244 s.in.info_ctr = &info_ctr;
1245 s.in.devmode_ctr = &devmode_ctr;
1246 s.in.secdesc_ctr = &secdesc_ctr;
1248 q.in.handle = handle;
1252 #define TESTGETCALL(call, r) \
1253 r.in.buffer = NULL; \
1255 r.out.needed = &needed; \
1256 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1257 if (!NT_STATUS_IS_OK(status)) { \
1258 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1259 r.in.level, nt_errstr(status), __location__); \
1263 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1264 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1265 data_blob_clear(&blob); \
1266 r.in.buffer = &blob; \
1267 r.in.offered = needed; \
1269 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1270 if (!NT_STATUS_IS_OK(status)) { \
1271 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1272 r.in.level, nt_errstr(status), __location__); \
1276 if (!W_ERROR_IS_OK(r.out.result)) { \
1277 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1278 r.in.level, win_errstr(r.out.result), __location__); \
1284 #define TESTSETCALL_EXP(call, r, err) \
1285 clear_info2(&info_ctr);\
1286 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1287 if (!NT_STATUS_IS_OK(status)) { \
1288 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1289 r.in.info_ctr->level, nt_errstr(status), __location__); \
1293 if (!W_ERROR_IS_OK(err)) { \
1294 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1295 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1296 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1301 if (!W_ERROR_IS_OK(r.out.result)) { \
1302 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1303 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1308 #define TESTSETCALL(call, r) \
1309 TESTSETCALL_EXP(call, r, WERR_OK)
1311 #define STRING_EQUAL(s1, s2, field) \
1312 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1313 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1314 #field, s2, __location__); \
1319 #define MEM_EQUAL(s1, s2, length, field) \
1320 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1321 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1322 #field, (const char *)s2, __location__); \
1327 #define INT_EQUAL(i1, i2, field) \
1329 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1330 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1335 #define SD_EQUAL(sd1, sd2, field) \
1336 if (!security_descriptor_equal(sd1, sd2)) { \
1337 torture_comment(tctx, "Failed to set %s (%s)\n", \
1338 #field, __location__); \
1343 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1344 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1345 q.in.level = lvl1; \
1346 TESTGETCALL(GetPrinter, q) \
1347 info_ctr.level = lvl1; \
1348 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1349 info_ctr.info.info ## lvl1->field1 = value;\
1350 TESTSETCALL_EXP(SetPrinter, s, err) \
1351 info_ctr.info.info ## lvl1->field1 = ""; \
1352 TESTGETCALL(GetPrinter, q) \
1353 info_ctr.info.info ## lvl1->field1 = value; \
1354 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1355 q.in.level = lvl2; \
1356 TESTGETCALL(GetPrinter, q) \
1357 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1358 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1361 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1362 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1365 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1366 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1367 q.in.level = lvl1; \
1368 TESTGETCALL(GetPrinter, q) \
1369 info_ctr.level = lvl1; \
1370 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1371 info_ctr.info.info ## lvl1->field1 = value; \
1372 TESTSETCALL(SetPrinter, s) \
1373 info_ctr.info.info ## lvl1->field1 = 0; \
1374 TESTGETCALL(GetPrinter, q) \
1375 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1376 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1377 q.in.level = lvl2; \
1378 TESTGETCALL(GetPrinter, q) \
1379 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1380 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1383 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1384 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1388 do { TESTGETCALL(GetPrinter, q0) } while (0);
1390 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1391 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1393 /* level 0 printername does not stick */
1394 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1395 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1396 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1397 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1398 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1399 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1400 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1401 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1402 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1403 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1404 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1405 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1406 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1407 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1408 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1410 /* servername can be set but does not stick
1411 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1412 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1413 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1416 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1417 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1418 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1419 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1420 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1422 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1423 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1424 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1425 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1426 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1427 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1428 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1429 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1430 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1431 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1433 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1434 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1436 (attribute_list[i] | default_attribute)
1438 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1440 (attribute_list[i] | default_attribute)
1442 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1444 (attribute_list[i] | default_attribute)
1446 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1448 (attribute_list[i] | default_attribute)
1450 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1452 (attribute_list[i] | default_attribute)
1454 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1456 (attribute_list[i] | default_attribute)
1458 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1460 (attribute_list[i] | default_attribute)
1462 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1464 (attribute_list[i] | default_attribute)
1466 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1468 (attribute_list[i] | default_attribute)
1470 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1472 (attribute_list[i] | default_attribute)
1474 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1476 (attribute_list[i] | default_attribute)
1478 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1480 (attribute_list[i] | default_attribute)
1484 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1485 /* level 2 sets do not stick
1486 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1487 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1488 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1489 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1490 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1491 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1494 /* priorities need to be between 0 and 99
1495 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1496 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1497 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1498 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1499 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1500 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1501 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1502 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1503 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1505 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1506 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1509 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1510 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1513 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1514 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1516 /* FIXME: gd also test devmode and secdesc behavior */
1519 /* verify composition of level 1 description field */
1520 const char *description;
1524 do { TESTGETCALL(GetPrinter, q0) } while (0);
1526 description = talloc_strdup(tctx, q0.out.info->info1.description);
1529 do { TESTGETCALL(GetPrinter, q0) } while (0);
1531 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1532 q0.out.info->info2.printername,
1533 q0.out.info->info2.drivername,
1534 q0.out.info->info2.location);
1536 do { STRING_EQUAL(description, tmp, "description")} while (0);
1542 #define torture_assert_sid_equal(torture_ctx,got,expected,cmt)\
1543 do { struct dom_sid *__got = (got), *__expected = (expected); \
1544 if (!dom_sid_equal(__got, __expected)) { \
1545 torture_result(torture_ctx, TORTURE_FAIL, \
1546 __location__": "#got" was %s, expected %s: %s", \
1547 dom_sid_string(torture_ctx, __got), dom_sid_string(torture_ctx, __expected), cmt); \
1552 static bool test_security_descriptor_equal(struct torture_context *tctx,
1553 const struct security_descriptor *sd1,
1554 const struct security_descriptor *sd2)
1561 torture_comment(tctx, "%s\n", __location__);
1565 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1566 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1568 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1569 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1571 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1572 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1573 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1574 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1577 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1578 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1579 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1580 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1587 static bool test_sd_set_level(struct torture_context *tctx,
1588 struct dcerpc_pipe *p,
1589 struct policy_handle *handle,
1591 struct security_descriptor *sd)
1593 struct spoolss_SetPrinterInfoCtr info_ctr;
1594 struct spoolss_DevmodeContainer devmode_ctr;
1595 struct sec_desc_buf secdesc_ctr;
1597 ZERO_STRUCT(devmode_ctr);
1598 ZERO_STRUCT(secdesc_ctr);
1602 union spoolss_PrinterInfo info;
1603 struct spoolss_SetPrinterInfo2 info2;
1604 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1606 info2.servername = info.info2.servername;
1607 info2.printername = info.info2.printername;
1608 info2.sharename = info.info2.sharename;
1609 info2.portname = info.info2.portname;
1610 info2.drivername = info.info2.drivername;
1611 info2.comment = info.info2.comment;
1612 info2.location = info.info2.location;
1613 info2.devmode_ptr = 0;
1614 info2.sepfile = info.info2.sepfile;
1615 info2.printprocessor = info.info2.printprocessor;
1616 info2.datatype = info.info2.datatype;
1617 info2.parameters = info.info2.parameters;
1618 info2.secdesc_ptr = 0;
1619 info2.attributes = info.info2.attributes;
1620 info2.priority = info.info2.priority;
1621 info2.defaultpriority = info.info2.defaultpriority;
1622 info2.starttime = info.info2.starttime;
1623 info2.untiltime = info.info2.untiltime;
1624 info2.status = info.info2.status;
1625 info2.cjobs = info.info2.cjobs;
1626 info2.averageppm = info.info2.averageppm;
1629 info_ctr.info.info2 = &info2;
1634 struct spoolss_SetPrinterInfo3 info3;
1636 info3.sec_desc_ptr = 0;
1639 info_ctr.info.info3 = &info3;
1647 secdesc_ctr.sd = sd;
1649 torture_assert(tctx,
1650 test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1655 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1656 struct dcerpc_pipe *p,
1657 struct policy_handle *handle)
1659 union spoolss_PrinterInfo info;
1660 struct security_descriptor *sd1, *sd2;
1663 /* just compare level 2 and level 3 */
1665 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1667 sd1 = info.info2.secdesc;
1669 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 3, &info), "");
1671 sd2 = info.info3.secdesc;
1673 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1674 "SD level 2 != SD level 3");
1677 /* query level 2, set level 2, query level 2 */
1679 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1681 sd1 = info.info2.secdesc;
1683 torture_assert(tctx, test_sd_set_level(tctx, p, handle, 2, sd1), "");
1685 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1687 sd2 = info.info2.secdesc;
1688 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1689 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1690 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1693 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1694 "SD level 2 != SD level 2 after SD has been set via level 2");
1697 /* query level 2, set level 3, query level 2 */
1699 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1701 sd1 = info.info2.secdesc;
1703 torture_assert(tctx, test_sd_set_level(tctx, p, handle, 3, sd1), "");
1705 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1707 sd2 = info.info2.secdesc;
1709 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1710 "SD level 2 != SD level 2 after SD has been set via level 3");
1712 /* set modified sd level 3, query level 2 */
1714 for (i=0; i < 93; i++) {
1715 struct security_ace a;
1716 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1717 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1719 a.size = 0; /* autogenerated */
1721 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1722 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1725 torture_assert(tctx, test_sd_set_level(tctx, p, handle, 3, sd1), "");
1727 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1728 sd2 = info.info2.secdesc;
1730 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1731 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1732 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1735 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1736 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1743 * wrapper call that saves original sd, runs tests, and restores sd
1746 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1747 struct dcerpc_pipe *p,
1748 struct policy_handle *handle)
1750 union spoolss_PrinterInfo info;
1751 struct security_descriptor *sd;
1754 torture_comment(tctx, "\nTesting Printer Security Descriptors\n");
1756 /* save original sd */
1758 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
1759 "failed to get initial security descriptor");
1761 sd = security_descriptor_copy(tctx, info.info2.secdesc);
1765 ret = test_PrinterInfo_SDs(tctx, p, handle);
1767 /* restore original sd */
1769 torture_assert(tctx, test_sd_set_level(tctx, p, handle, 3, sd),
1770 "failed to restore initial security descriptor");
1772 torture_comment(tctx, "Printer Security Descriptors test %s\n",
1773 ret ? "succeeded" : "failed");
1779 static bool test_devmode_set_level(struct torture_context *tctx,
1780 struct dcerpc_pipe *p,
1781 struct policy_handle *handle,
1783 struct spoolss_DeviceMode *devmode)
1785 struct spoolss_SetPrinterInfoCtr info_ctr;
1786 struct spoolss_DevmodeContainer devmode_ctr;
1787 struct sec_desc_buf secdesc_ctr;
1789 ZERO_STRUCT(devmode_ctr);
1790 ZERO_STRUCT(secdesc_ctr);
1794 union spoolss_PrinterInfo info;
1795 struct spoolss_SetPrinterInfo2 info2;
1796 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1798 info2.servername = info.info2.servername;
1799 info2.printername = info.info2.printername;
1800 info2.sharename = info.info2.sharename;
1801 info2.portname = info.info2.portname;
1802 info2.drivername = info.info2.drivername;
1803 info2.comment = info.info2.comment;
1804 info2.location = info.info2.location;
1805 info2.devmode_ptr = 0;
1806 info2.sepfile = info.info2.sepfile;
1807 info2.printprocessor = info.info2.printprocessor;
1808 info2.datatype = info.info2.datatype;
1809 info2.parameters = info.info2.parameters;
1810 info2.secdesc_ptr = 0;
1811 info2.attributes = info.info2.attributes;
1812 info2.priority = info.info2.priority;
1813 info2.defaultpriority = info.info2.defaultpriority;
1814 info2.starttime = info.info2.starttime;
1815 info2.untiltime = info.info2.untiltime;
1816 info2.status = info.info2.status;
1817 info2.cjobs = info.info2.cjobs;
1818 info2.averageppm = info.info2.averageppm;
1821 info_ctr.info.info2 = &info2;
1826 struct spoolss_SetPrinterInfo8 info8;
1828 info8.devmode_ptr = 0;
1831 info_ctr.info.info8 = &info8;
1839 devmode_ctr.devmode = devmode;
1841 torture_assert(tctx,
1842 test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1848 static bool test_devicemode_equal(struct torture_context *tctx,
1849 const struct spoolss_DeviceMode *d1,
1850 const struct spoolss_DeviceMode *d2)
1857 torture_comment(tctx, "%s\n", __location__);
1860 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
1861 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
1862 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
1863 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
1864 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
1865 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
1866 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
1867 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
1868 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
1869 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
1870 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
1871 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
1872 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
1873 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
1874 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
1875 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
1876 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
1877 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
1878 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
1879 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
1880 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
1881 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
1882 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
1883 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
1884 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
1885 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
1886 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
1887 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
1888 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
1889 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
1890 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
1891 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
1892 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
1893 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
1894 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
1899 static bool test_devicemode_full(struct torture_context *tctx,
1900 struct dcerpc_pipe *p,
1901 struct policy_handle *handle)
1903 struct spoolss_SetPrinter s;
1904 struct spoolss_GetPrinter q;
1905 struct spoolss_GetPrinter q0;
1906 struct spoolss_SetPrinterInfoCtr info_ctr;
1907 struct spoolss_SetPrinterInfo8 info8;
1908 union spoolss_PrinterInfo info;
1909 struct spoolss_DevmodeContainer devmode_ctr;
1910 struct sec_desc_buf secdesc_ctr;
1915 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1916 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1917 q.in.level = lvl1; \
1918 TESTGETCALL(GetPrinter, q) \
1919 info_ctr.level = lvl1; \
1921 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1922 } else if (lvl1 == 8) {\
1923 info_ctr.info.info ## lvl1 = &info8; \
1925 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
1926 devmode_ctr.devmode->field1 = value; \
1927 TESTSETCALL(SetPrinter, s) \
1928 TESTGETCALL(GetPrinter, q) \
1929 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
1930 q.in.level = lvl2; \
1931 TESTGETCALL(GetPrinter, q) \
1932 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
1935 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
1936 TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1939 ZERO_STRUCT(devmode_ctr);
1940 ZERO_STRUCT(secdesc_ctr);
1943 s.in.handle = handle;
1945 s.in.info_ctr = &info_ctr;
1946 s.in.devmode_ctr = &devmode_ctr;
1947 s.in.secdesc_ctr = &secdesc_ctr;
1949 q.in.handle = handle;
1954 const char *devicename;/* [charset(UTF16)] */
1955 enum spoolss_DeviceModeSpecVersion specversion;
1956 uint16_t driverversion;
1958 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
1962 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
1963 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
1964 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
1965 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
1966 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
1967 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
1968 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
1969 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
1970 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
1971 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
1972 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
1973 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
1974 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
1976 const char *formname;/* [charset(UTF16)] */
1978 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
1979 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
1980 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
1981 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
1982 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
1983 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
1984 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
1985 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
1986 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
1987 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
1988 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
1989 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
1990 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
1991 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
1996 static bool call_OpenPrinterEx(struct torture_context *tctx,
1997 struct dcerpc_pipe *p,
1999 struct spoolss_DeviceMode *devmode,
2000 struct policy_handle *handle);
2002 static bool test_ClosePrinter(struct torture_context *tctx,
2003 struct dcerpc_pipe *p,
2004 struct policy_handle *handle);
2006 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2007 struct dcerpc_pipe *p,
2008 struct policy_handle *handle,
2011 union spoolss_PrinterInfo info;
2012 struct spoolss_DeviceMode *devmode;
2013 struct spoolss_DeviceMode *devmode2;
2014 struct policy_handle handle_devmode;
2016 /* simply compare level8 and level2 devmode */
2018 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 8, &info), "");
2020 devmode = info.info8.devmode;
2022 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
2024 devmode2 = info.info2.devmode;
2026 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2027 "DM level 8 != DM level 2");
2030 /* set devicemode level 8 and see if it persists */
2032 devmode->copies = 93;
2033 devmode->formname = talloc_strdup(tctx, "Legal");
2035 torture_assert(tctx, test_devmode_set_level(tctx, p, handle, 8, devmode), "");
2037 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 8, &info), "");
2039 devmode2 = info.info8.devmode;
2041 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2042 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2044 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
2046 devmode2 = info.info2.devmode;
2048 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2049 "modified DM level 8 != DM level 2");
2052 /* set devicemode level 2 and see if it persists */
2054 devmode->copies = 39;
2055 devmode->formname = talloc_strdup(tctx, "Executive");
2057 torture_assert(tctx, test_devmode_set_level(tctx, p, handle, 2, devmode), "");
2059 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 8, &info), "");
2061 devmode2 = info.info8.devmode;
2063 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2064 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2066 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
2068 devmode2 = info.info2.devmode;
2070 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2071 "modified DM level 8 != DM level 2");
2074 /* check every single bit in public part of devicemode */
2076 torture_assert(tctx, test_devicemode_full(tctx, p, handle),
2077 "failed to set every single devicemode component");
2080 /* change formname upon open and see if it persists in getprinter calls */
2082 devmode->formname = talloc_strdup(tctx, "A4");
2083 devmode->copies = 42;
2085 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2086 "failed to open printer handle");
2088 torture_assert(tctx, test_GetPrinter_level(tctx, p, &handle_devmode, 8, &info), "");
2090 devmode2 = info.info8.devmode;
2092 if (strequal(devmode->devicename, devmode2->devicename)) {
2093 torture_comment(tctx, "devicenames are the same\n");
2095 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2096 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2099 if (strequal(devmode->formname, devmode2->formname)) {
2100 torture_warning(tctx, "formname are the same\n");
2102 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2103 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2106 if (devmode->copies == devmode2->copies) {
2107 torture_warning(tctx, "copies are the same\n");
2109 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2110 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2113 torture_assert(tctx, test_GetPrinter_level(tctx, p, &handle_devmode, 2, &info), "");
2115 devmode2 = info.info2.devmode;
2117 if (strequal(devmode->devicename, devmode2->devicename)) {
2118 torture_comment(tctx, "devicenames are the same\n");
2120 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2121 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2124 if (strequal(devmode->formname, devmode2->formname)) {
2125 torture_warning(tctx, "formname is the same\n");
2127 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2128 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2131 if (devmode->copies == devmode2->copies) {
2132 torture_warning(tctx, "copies are the same\n");
2134 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2135 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2138 test_ClosePrinter(tctx, p, &handle_devmode);
2144 * wrapper call that saves original devmode, runs tests, and restores devmode
2147 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2148 struct dcerpc_pipe *p,
2149 struct policy_handle *handle,
2152 union spoolss_PrinterInfo info;
2153 struct spoolss_DeviceMode *devmode;
2156 torture_comment(tctx, "\nTesting Printer Devicemodes\n");
2158 /* save original devmode */
2160 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 8, &info),
2161 "failed to get initial global devicemode");
2163 devmode = info.info8.devmode;
2167 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2169 /* restore original devmode */
2171 torture_assert(tctx, test_devmode_set_level(tctx, p, handle, 8, devmode),
2172 "failed to restore initial global device mode");
2174 torture_comment(tctx, "Printer Devicemodes test %s\n",
2175 ret ? "succeeded" : "failed");
2181 static bool test_ClosePrinter(struct torture_context *tctx,
2182 struct dcerpc_pipe *p,
2183 struct policy_handle *handle)
2186 struct spoolss_ClosePrinter r;
2188 r.in.handle = handle;
2189 r.out.handle = handle;
2191 torture_comment(tctx, "Testing ClosePrinter\n");
2193 status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
2194 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2195 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2200 static bool test_GetForm(struct torture_context *tctx,
2201 struct dcerpc_pipe *p,
2202 struct policy_handle *handle,
2203 const char *form_name,
2207 struct spoolss_GetForm r;
2210 r.in.handle = handle;
2211 r.in.form_name = form_name;
2215 r.out.needed = &needed;
2217 torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
2219 status = dcerpc_spoolss_GetForm(p, tctx, &r);
2220 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2222 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2223 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2224 data_blob_clear(&blob);
2225 r.in.buffer = &blob;
2226 r.in.offered = needed;
2227 status = dcerpc_spoolss_GetForm(p, tctx, &r);
2228 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2230 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2232 torture_assert(tctx, r.out.info, "No form info returned");
2235 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2237 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2242 static bool test_EnumForms(struct torture_context *tctx,
2243 struct dcerpc_pipe *p,
2244 struct policy_handle *handle, bool print_server)
2247 struct spoolss_EnumForms r;
2251 uint32_t levels[] = { 1, 2 };
2254 for (i=0; i<ARRAY_SIZE(levels); i++) {
2256 union spoolss_FormInfo *info;
2258 r.in.handle = handle;
2259 r.in.level = levels[i];
2262 r.out.needed = &needed;
2263 r.out.count = &count;
2266 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
2268 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
2269 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
2271 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2275 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
2276 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2278 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2280 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2281 data_blob_clear(&blob);
2282 r.in.buffer = &blob;
2283 r.in.offered = needed;
2285 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
2287 torture_assert(tctx, info, "No forms returned");
2289 for (j = 0; j < count; j++) {
2291 ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
2295 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
2297 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2299 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2305 static bool test_DeleteForm(struct torture_context *tctx,
2306 struct dcerpc_pipe *p,
2307 struct policy_handle *handle,
2308 const char *form_name)
2311 struct spoolss_DeleteForm r;
2313 r.in.handle = handle;
2314 r.in.form_name = form_name;
2316 status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
2318 torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
2320 torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
2325 static bool test_AddForm(struct torture_context *tctx,
2326 struct dcerpc_pipe *p,
2327 struct policy_handle *handle, bool print_server)
2329 struct spoolss_AddForm r;
2330 struct spoolss_AddFormInfo1 addform;
2331 const char *form_name = "testform3";
2335 r.in.handle = handle;
2337 r.in.info.info1 = &addform;
2338 addform.flags = SPOOLSS_FORM_USER;
2339 addform.form_name = form_name;
2340 addform.size.width = 50;
2341 addform.size.height = 25;
2342 addform.area.left = 5;
2343 addform.area.top = 10;
2344 addform.area.right = 45;
2345 addform.area.bottom = 15;
2347 status = dcerpc_spoolss_AddForm(p, tctx, &r);
2349 torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
2351 torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
2353 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
2356 struct spoolss_SetForm sf;
2357 struct spoolss_AddFormInfo1 setform;
2359 sf.in.handle = handle;
2360 sf.in.form_name = form_name;
2362 sf.in.info.info1= &setform;
2363 setform.flags = addform.flags;
2364 setform.form_name = addform.form_name;
2365 setform.size = addform.size;
2366 setform.area = addform.area;
2368 setform.size.width = 1234;
2370 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
2372 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
2374 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
2377 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
2380 struct spoolss_EnumForms e;
2381 union spoolss_FormInfo *info;
2386 e.in.handle = handle;
2390 e.out.needed = &needed;
2391 e.out.count = &count;
2394 torture_comment(tctx, "Testing EnumForms level 1\n");
2396 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
2397 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
2399 if (print_server && W_ERROR_EQUAL(e.out.result, WERR_BADFID))
2400 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2402 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
2404 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2405 data_blob_clear(&blob);
2406 e.in.buffer = &blob;
2407 e.in.offered = needed;
2409 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
2411 torture_assert(tctx, info, "No forms returned");
2413 for (j = 0; j < count; j++) {
2414 if (strequal(form_name, info[j].info1.form_name)) {
2420 torture_assert(tctx, found, "Newly added form not found in enum call");
2423 if (!test_DeleteForm(tctx, p, handle, form_name)) {
2430 static bool test_EnumPorts_old(struct torture_context *tctx,
2431 struct dcerpc_pipe *p)
2434 struct spoolss_EnumPorts r;
2437 union spoolss_PortInfo *info;
2439 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2440 dcerpc_server_name(p));
2444 r.out.needed = &needed;
2445 r.out.count = &count;
2448 torture_comment(tctx, "Testing EnumPorts\n");
2450 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
2452 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2454 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2455 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2456 data_blob_clear(&blob);
2457 r.in.buffer = &blob;
2458 r.in.offered = needed;
2460 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
2461 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2462 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2464 torture_assert(tctx, info, "No ports returned");
2467 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2469 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2474 static bool test_AddPort(struct torture_context *tctx,
2475 struct dcerpc_pipe *p)
2478 struct spoolss_AddPort r;
2480 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
2481 dcerpc_server_name(p));
2483 r.in.monitor_name = "foo";
2485 torture_comment(tctx, "Testing AddPort\n");
2487 status = dcerpc_spoolss_AddPort(p, tctx, &r);
2489 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
2491 /* win2k3 returns WERR_NOT_SUPPORTED */
2495 if (!W_ERROR_IS_OK(r.out.result)) {
2496 printf("AddPort failed - %s\n", win_errstr(r.out.result));
2505 static bool test_GetJob(struct torture_context *tctx,
2506 struct dcerpc_pipe *p,
2507 struct policy_handle *handle, uint32_t job_id)
2510 struct spoolss_GetJob r;
2511 union spoolss_JobInfo info;
2513 uint32_t levels[] = {1, 2 /* 3, 4 */};
2516 r.in.handle = handle;
2517 r.in.job_id = job_id;
2521 r.out.needed = &needed;
2524 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
2526 status = dcerpc_spoolss_GetJob(p, tctx, &r);
2527 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
2529 for (i = 0; i < ARRAY_SIZE(levels); i++) {
2531 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
2535 r.in.level = levels[i];
2539 status = dcerpc_spoolss_GetJob(p, tctx, &r);
2540 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2542 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2543 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2544 data_blob_clear(&blob);
2545 r.in.buffer = &blob;
2546 r.in.offered = needed;
2548 status = dcerpc_spoolss_GetJob(p, tctx, &r);
2549 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2552 torture_assert(tctx, r.out.info, "No job info returned");
2553 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
2555 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2561 static bool test_SetJob(struct torture_context *tctx,
2562 struct dcerpc_pipe *p,
2563 struct policy_handle *handle, uint32_t job_id,
2564 enum spoolss_JobControl command)
2567 struct spoolss_SetJob r;
2569 r.in.handle = handle;
2570 r.in.job_id = job_id;
2572 r.in.command = command;
2575 case SPOOLSS_JOB_CONTROL_PAUSE:
2576 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
2578 case SPOOLSS_JOB_CONTROL_RESUME:
2579 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
2581 case SPOOLSS_JOB_CONTROL_CANCEL:
2582 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
2584 case SPOOLSS_JOB_CONTROL_RESTART:
2585 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
2587 case SPOOLSS_JOB_CONTROL_DELETE:
2588 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
2590 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
2591 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
2593 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
2594 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
2596 case SPOOLSS_JOB_CONTROL_RETAIN:
2597 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
2599 case SPOOLSS_JOB_CONTROL_RELEASE:
2600 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
2603 torture_comment(tctx, "Testing SetJob\n");
2607 status = dcerpc_spoolss_SetJob(p, tctx, &r);
2608 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
2609 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
2614 static bool test_AddJob(struct torture_context *tctx,
2615 struct dcerpc_pipe *p,
2616 struct policy_handle *handle)
2619 struct spoolss_AddJob r;
2623 r.in.handle = handle;
2625 r.out.needed = &needed;
2626 r.in.buffer = r.out.buffer = NULL;
2628 torture_comment(tctx, "Testing AddJob\n");
2630 status = dcerpc_spoolss_AddJob(p, tctx, &r);
2631 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
2635 status = dcerpc_spoolss_AddJob(p, tctx, &r);
2636 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
2642 static bool test_EnumJobs(struct torture_context *tctx,
2643 struct dcerpc_pipe *p,
2644 struct policy_handle *handle)
2647 struct spoolss_EnumJobs r;
2650 union spoolss_JobInfo *info;
2652 r.in.handle = handle;
2654 r.in.numjobs = 0xffffffff;
2658 r.out.needed = &needed;
2659 r.out.count = &count;
2662 torture_comment(tctx, "Testing EnumJobs\n");
2664 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
2666 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
2668 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2670 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2671 data_blob_clear(&blob);
2672 r.in.buffer = &blob;
2673 r.in.offered = needed;
2675 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
2677 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
2678 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
2679 torture_assert(tctx, info, "No jobs returned");
2681 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2683 for (j = 0; j < count; j++) {
2685 torture_assert(tctx, test_GetJob(tctx, p, handle, info[j].info1.job_id),
2686 "failed to call test_GetJob");
2689 if (!torture_setting_bool(tctx, "samba3", false)) {
2690 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
2691 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
2696 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
2702 static bool test_DoPrintTest(struct torture_context *tctx,
2703 struct dcerpc_pipe *p,
2704 struct policy_handle *handle)
2708 struct spoolss_StartDocPrinter s;
2709 struct spoolss_DocumentInfo1 info1;
2710 struct spoolss_StartPagePrinter sp;
2711 struct spoolss_WritePrinter w;
2712 struct spoolss_EndPagePrinter ep;
2713 struct spoolss_EndDocPrinter e;
2716 uint32_t num_written;
2718 torture_comment(tctx, "Testing StartDocPrinter\n");
2720 s.in.handle = handle;
2722 s.in.info.info1 = &info1;
2723 s.out.job_id = &job_id;
2724 info1.document_name = "TorturePrintJob";
2725 info1.output_file = NULL;
2726 info1.datatype = "RAW";
2728 status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
2729 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
2730 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
2732 for (i=1; i < 4; i++) {
2733 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
2735 sp.in.handle = handle;
2737 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
2738 torture_assert_ntstatus_ok(tctx, status,
2739 "dcerpc_spoolss_StartPagePrinter failed");
2740 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
2742 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
2744 w.in.handle = handle;
2745 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
2746 w.out.num_written = &num_written;
2748 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
2749 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
2750 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
2752 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
2754 ep.in.handle = handle;
2756 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
2757 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
2758 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
2761 torture_comment(tctx, "Testing EndDocPrinter\n");
2763 e.in.handle = handle;
2765 status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
2766 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
2767 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
2769 ret &= test_AddJob(tctx, p, handle);
2770 ret &= test_EnumJobs(tctx, p, handle);
2772 ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
2777 static bool test_PausePrinter(struct torture_context *tctx,
2778 struct dcerpc_pipe *p,
2779 struct policy_handle *handle)
2782 struct spoolss_SetPrinter r;
2783 struct spoolss_SetPrinterInfoCtr info_ctr;
2784 struct spoolss_DevmodeContainer devmode_ctr;
2785 struct sec_desc_buf secdesc_ctr;
2788 info_ctr.info.info0 = NULL;
2790 ZERO_STRUCT(devmode_ctr);
2791 ZERO_STRUCT(secdesc_ctr);
2793 r.in.handle = handle;
2794 r.in.info_ctr = &info_ctr;
2795 r.in.devmode_ctr = &devmode_ctr;
2796 r.in.secdesc_ctr = &secdesc_ctr;
2797 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
2799 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
2801 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2803 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2805 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2810 static bool test_ResumePrinter(struct torture_context *tctx,
2811 struct dcerpc_pipe *p,
2812 struct policy_handle *handle)
2815 struct spoolss_SetPrinter r;
2816 struct spoolss_SetPrinterInfoCtr info_ctr;
2817 struct spoolss_DevmodeContainer devmode_ctr;
2818 struct sec_desc_buf secdesc_ctr;
2821 info_ctr.info.info0 = NULL;
2823 ZERO_STRUCT(devmode_ctr);
2824 ZERO_STRUCT(secdesc_ctr);
2826 r.in.handle = handle;
2827 r.in.info_ctr = &info_ctr;
2828 r.in.devmode_ctr = &devmode_ctr;
2829 r.in.secdesc_ctr = &secdesc_ctr;
2830 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
2832 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2834 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2836 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2838 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2843 static bool test_GetPrinterData(struct torture_context *tctx,
2844 struct dcerpc_pipe *p,
2845 struct policy_handle *handle,
2846 const char *value_name,
2847 enum winreg_Type *type_p,
2852 struct spoolss_GetPrinterData r;
2854 enum winreg_Type type;
2855 union spoolss_PrinterData data;
2857 r.in.handle = handle;
2858 r.in.value_name = value_name;
2860 r.out.needed = &needed;
2862 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
2864 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
2866 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2867 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2869 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2870 r.in.offered = needed;
2871 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
2872 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2873 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2876 torture_assert_werr_ok(tctx, r.out.result,
2877 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
2879 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2886 *data_p = r.out.data;
2896 static bool test_GetPrinterDataEx(struct torture_context *tctx,
2897 struct dcerpc_pipe *p,
2898 struct policy_handle *handle,
2899 const char *key_name,
2900 const char *value_name,
2901 enum winreg_Type *type_p,
2906 struct spoolss_GetPrinterDataEx r;
2907 enum winreg_Type type;
2909 union spoolss_PrinterData data;
2911 r.in.handle = handle;
2912 r.in.key_name = key_name;
2913 r.in.value_name = value_name;
2916 r.out.needed = &needed;
2917 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
2919 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
2920 r.in.key_name, r.in.value_name);
2922 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2923 if (!NT_STATUS_IS_OK(status)) {
2924 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
2925 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
2926 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
2928 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2931 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2932 r.in.offered = needed;
2933 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
2934 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2935 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2938 torture_assert_werr_ok(tctx, r.out.result,
2939 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
2941 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2948 *data_p = r.out.data;
2958 static bool test_GetPrinterData_list(struct torture_context *tctx,
2959 struct dcerpc_pipe *p,
2960 struct policy_handle *handle)
2962 const char *list[] = {
2966 /* "NetPopup", not on w2k8 */
2967 /* "NetPopupToComputer", not on w2k8 */
2970 "DefaultSpoolDirectory",
2974 /* "OSVersionEx", not on s3 */
2979 for (i=0; i < ARRAY_SIZE(list); i++) {
2980 enum winreg_Type type, type_ex;
2981 uint8_t *data, *data_ex;
2982 uint32_t needed, needed_ex;
2984 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, list[i], &type, &data, &needed),
2985 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
2986 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
2987 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
2988 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
2989 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
2990 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
2996 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
2997 struct policy_handle *handle)
3000 struct spoolss_EnumPrinterData r;
3003 r.in.handle = handle;
3004 r.in.enum_index = 0;
3007 uint32_t value_size = 0;
3008 uint32_t data_size = 0;
3009 enum winreg_Type type = 0;
3011 r.in.value_offered = value_size;
3012 r.out.value_needed = &value_size;
3013 r.in.data_offered = data_size;
3014 r.out.data_needed = &data_size;
3017 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
3019 torture_comment(tctx, "Testing EnumPrinterData\n");
3021 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
3023 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
3024 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3027 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData");
3029 r.in.value_offered = value_size;
3030 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
3031 r.in.data_offered = data_size;
3032 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
3034 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
3036 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
3037 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3041 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData failed");
3043 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, r.out.value_name, NULL, NULL, NULL),
3044 talloc_asprintf(tctx, "failed to call GetPrinterData for %s\n", r.out.value_name));
3046 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", r.out.value_name, NULL, NULL, NULL),
3047 talloc_asprintf(tctx, "failed to call GetPrinterDataEx on PrinterDriverData for %s\n", r.out.value_name));
3051 } while (W_ERROR_IS_OK(r.out.result));
3056 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3057 struct dcerpc_pipe *p,
3058 struct policy_handle *handle,
3059 const char *key_name)
3061 struct spoolss_EnumPrinterDataEx r;
3062 struct spoolss_PrinterEnumValues *info;
3066 r.in.handle = handle;
3067 r.in.key_name = key_name;
3069 r.out.needed = &needed;
3070 r.out.count = &count;
3073 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3075 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
3076 "EnumPrinterDataEx failed");
3077 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3078 r.in.offered = needed;
3079 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
3080 "EnumPrinterDataEx failed");
3083 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3085 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3091 static bool test_DeletePrinterData(struct torture_context *tctx,
3092 struct dcerpc_pipe *p,
3093 struct policy_handle *handle,
3094 const char *value_name)
3097 struct spoolss_DeletePrinterData r;
3099 r.in.handle = handle;
3100 r.in.value_name = value_name;
3102 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
3105 status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
3107 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
3108 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
3113 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
3114 struct dcerpc_pipe *p,
3115 struct policy_handle *handle,
3116 const char *key_name,
3117 const char *value_name)
3119 struct spoolss_DeletePrinterDataEx r;
3121 r.in.handle = handle;
3122 r.in.key_name = key_name;
3123 r.in.value_name = value_name;
3125 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
3126 r.in.key_name, r.in.value_name);
3128 torture_assert_ntstatus_ok(tctx,
3129 dcerpc_spoolss_DeletePrinterDataEx(p, tctx, &r),
3130 "DeletePrinterDataEx failed");
3131 torture_assert_werr_ok(tctx, r.out.result,
3132 "DeletePrinterDataEx failed");
3137 static bool test_DeletePrinterKey(struct torture_context *tctx,
3138 struct dcerpc_pipe *p,
3139 struct policy_handle *handle,
3140 const char *key_name)
3142 struct spoolss_DeletePrinterKey r;
3144 r.in.handle = handle;
3145 r.in.key_name = key_name;
3147 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
3149 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
3150 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
3154 torture_assert_ntstatus_ok(tctx,
3155 dcerpc_spoolss_DeletePrinterKey(p, tctx, &r),
3156 "DeletePrinterKey failed");
3157 torture_assert_werr_ok(tctx, r.out.result,
3158 "DeletePrinterKey failed");
3163 static bool test_SetPrinterData(struct torture_context *tctx,
3164 struct dcerpc_pipe *p,
3165 struct policy_handle *handle)
3168 struct spoolss_SetPrinterData r;
3169 const char *values[] = {
3173 /* FIXME: not working with s3 atm. */
3179 /* FIXME: not working with s3 atm. */
3186 for (i=0; i < ARRAY_SIZE(values); i++) {
3188 enum winreg_Type type;
3193 torture_assert(tctx,
3194 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3195 "REG_SZ", "dog", &r.in.type, &blob), "");
3197 r.in.handle = handle;
3198 r.in.value_name = values[i];
3199 r.in.data = blob.data;
3200 r.in.offered = blob.length;
3202 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
3205 status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
3207 torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
3208 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterData failed");
3210 if (!test_GetPrinterData(tctx, p, handle, r.in.value_name, &type, &data, &needed)) {
3214 torture_assert_int_equal(tctx, r.in.type, type, "type mismatch");
3215 torture_assert_int_equal(tctx, r.in.offered, needed, "size mismatch");
3216 torture_assert_mem_equal(tctx, blob.data, data, needed, "buffer mismatch");
3218 if (!test_DeletePrinterData(tctx, p, handle, r.in.value_name)) {
3226 static bool test_EnumPrinterKey(struct torture_context *tctx,
3227 struct dcerpc_pipe *p,
3228 struct policy_handle *handle,
3229 const char *key_name,
3230 const char ***array);
3232 static bool test_SetPrinterDataEx(struct torture_context *tctx,
3233 struct dcerpc_pipe *p,
3234 struct policy_handle *handle,
3235 const char *key_name,
3236 const char *value_name,
3237 enum winreg_Type type,
3242 struct spoolss_SetPrinterDataEx r;
3244 r.in.handle = handle;
3245 r.in.key_name = key_name;
3246 r.in.value_name = value_name;
3249 r.in.offered = offered;
3251 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
3252 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
3254 status = dcerpc_spoolss_SetPrinterDataEx(p, tctx, &r);
3256 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
3257 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
3262 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
3263 struct dcerpc_pipe *p,
3264 struct policy_handle *handle,
3265 const char *printername)
3267 const char *value_name = "dog";
3268 const char *keys[] = {
3272 /* FIXME: not working with s3 atm. */
3273 "torturedataex_with_subkey\\subkey",
3274 "torturedataex_with_subkey\\subkey:0",
3275 "torturedataex_with_subkey\\subkey:1",
3276 "torturedataex_with_subkey\\subkey\\subsubkey",
3277 "torturedataex_with_subkey\\subkey\\subsubkey:0",
3278 "torturedataex_with_subkey\\subkey\\subsubkey:1",
3282 /* FIXME: not working with s3 atm. */
3289 enum winreg_Type types[] = {
3294 const char *str = "abcdefghijklmnopqrstuvwxzy";
3298 for (i=0; i < ARRAY_SIZE(keys); i++) {
3299 for (t=0; t < ARRAY_SIZE(types); t++) {
3300 for (s=0; s < strlen(str); s++) {
3304 enum winreg_Type type;
3305 const char *string = talloc_strndup(tctx, str, s);
3306 DATA_BLOB blob = data_blob_string_const(string);
3307 const char **subkeys;
3310 uint32_t needed, offered = 0;
3316 offered = blob.length;
3319 torture_assert(tctx,
3320 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3321 "REG_SZ", string, &type, &data), "");
3322 offered = data.length;
3323 /*strlen_m_term(data.string)*2;*/
3326 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
3329 torture_assert(tctx,
3330 test_SetPrinterDataEx(tctx, p, handle, keys[i], value_name, types[t], data.data, offered),
3331 "failed to call SetPrinterDataEx");
3333 if (!test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &data_out, &needed)) {
3336 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
3337 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
3338 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
3340 key = talloc_strdup(tctx, keys[i]);
3342 if (!test_EnumPrinterDataEx(tctx, p, handle, keys[i])) {
3346 if (!test_DeletePrinterDataEx(tctx, p, handle, keys[i], value_name)) {
3350 c = strchr(key, '\\');
3354 /* we have subkeys */
3358 if (!test_EnumPrinterKey(tctx, p, handle, key, &subkeys)) {
3362 for (i=0; subkeys && subkeys[i]; i++) {
3364 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[i]);
3366 if (!test_DeletePrinterKey(tctx, p, handle, current_key)) {
3371 if (!test_DeletePrinterKey(tctx, p, handle, key)) {
3376 if (!test_DeletePrinterKey(tctx, p, handle, key)) {
3387 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
3388 struct dcerpc_pipe *p,
3389 struct policy_handle *handle,
3390 uint32_t *change_id)
3392 enum winreg_Type type;
3396 torture_assert(tctx,
3397 test_GetPrinterData(tctx, p, handle, "ChangeID", &type, &data, &needed),
3398 "failed to call GetPrinterData");
3400 torture_assert(tctx, type == REG_DWORD, "unexpected type");
3401 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
3403 *change_id = IVAL(data, 0);
3408 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
3409 struct dcerpc_pipe *p,
3410 struct policy_handle *handle,
3411 uint32_t *change_id)
3413 enum winreg_Type type;
3417 torture_assert(tctx,
3418 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
3419 "failed to call GetPrinterData");
3421 torture_assert(tctx, type == REG_DWORD, "unexpected type");
3422 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
3424 *change_id = IVAL(data, 0);
3429 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
3430 struct dcerpc_pipe *p,
3431 struct policy_handle *handle,
3432 uint32_t *change_id)
3434 union spoolss_PrinterInfo info;
3436 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 0, &info),
3437 "failed to query Printer level 0");
3439 *change_id = info.info0.change_id;
3444 static bool test_ChangeID(struct torture_context *tctx,
3445 struct dcerpc_pipe *p,
3446 struct policy_handle *handle)
3448 uint32_t change_id, change_id_ex, change_id_info;
3449 uint32_t change_id2, change_id_ex2, change_id_info2;
3450 union spoolss_PrinterInfo info;
3451 const char *comment;
3454 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
3456 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3457 "failed to query for ChangeID");
3458 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3459 "failed to query for ChangeID");
3460 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3461 "failed to query for ChangeID");
3463 torture_assert_int_equal(tctx, change_id, change_id_ex,
3464 "change_ids should all be equal");
3465 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
3466 "change_ids should all be equal");
3469 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
3471 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3472 "failed to query for ChangeID");
3473 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
3474 "failed to query Printer level 2");
3475 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3476 "failed to query for ChangeID");
3477 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3478 "failed to query for ChangeID");
3479 torture_assert_int_equal(tctx, change_id, change_id_ex,
3480 "change_id should not have changed");
3481 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
3482 "change_id should not have changed");
3485 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
3487 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3488 "failed to query for ChangeID");
3489 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3490 "failed to query for ChangeID");
3491 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3492 "failed to query for ChangeID");
3493 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
3494 "failed to query Printer level 2");
3495 comment = talloc_strdup(tctx, info.info2.comment);
3498 struct spoolss_SetPrinterInfoCtr info_ctr;
3499 struct spoolss_DevmodeContainer devmode_ctr;
3500 struct sec_desc_buf secdesc_ctr;
3501 struct spoolss_SetPrinterInfo2 info2;
3503 ZERO_STRUCT(info_ctr);
3504 ZERO_STRUCT(devmode_ctr);
3505 ZERO_STRUCT(secdesc_ctr);
3507 info2.servername = info.info2.servername;
3508 info2.printername = info.info2.printername;
3509 info2.sharename = info.info2.sharename;
3510 info2.portname = info.info2.portname;
3511 info2.drivername = info.info2.drivername;
3512 info2.comment = "torture_comment";
3513 info2.location = info.info2.location;
3514 info2.devmode_ptr = 0;
3515 info2.sepfile = info.info2.sepfile;
3516 info2.printprocessor = info.info2.printprocessor;
3517 info2.datatype = info.info2.datatype;
3518 info2.parameters = info.info2.parameters;
3519 info2.secdesc_ptr = 0;
3520 info2.attributes = info.info2.attributes;
3521 info2.priority = info.info2.priority;
3522 info2.defaultpriority = info.info2.defaultpriority;
3523 info2.starttime = info.info2.starttime;
3524 info2.untiltime = info.info2.untiltime;
3525 info2.status = info.info2.status;
3526 info2.cjobs = info.info2.cjobs;
3527 info2.averageppm = info.info2.averageppm;
3530 info_ctr.info.info2 = &info2;
3532 torture_assert(tctx, test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
3533 "failed to call SetPrinter");
3535 info2.comment = comment;
3537 torture_assert(tctx, test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
3538 "failed to call SetPrinter");
3542 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id2),
3543 "failed to query for ChangeID");
3544 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
3545 "failed to query for ChangeID");
3546 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info2),
3547 "failed to query for ChangeID");
3549 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
3550 "change_ids should all be equal");
3551 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
3552 "change_ids should all be equal");
3554 torture_assert(tctx, (change_id < change_id2),
3555 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3556 change_id2, change_id));
3557 torture_assert(tctx, (change_id_ex < change_id_ex2),
3558 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3559 change_id_ex2, change_id_ex));
3560 torture_assert(tctx, (change_id_info < change_id_info2),
3561 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3562 change_id_info2, change_id_info));
3567 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
3568 struct dcerpc_pipe *p,
3569 struct policy_handle *handle)
3572 struct dcerpc_binding *b;
3573 struct dcerpc_pipe *p2;
3574 struct spoolss_ClosePrinter cp;
3576 /* only makes sense on SMB */
3577 if (p->conn->transport.transport != NCACN_NP) {
3581 torture_comment(tctx, "testing close on secondary pipe\n");
3583 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
3584 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
3586 status = dcerpc_secondary_connection(p, &p2, b);
3587 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
3589 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
3590 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
3592 cp.in.handle = handle;
3593 cp.out.handle = handle;
3595 status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
3596 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
3597 "ERROR: Allowed close on secondary connection");
3599 torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
3600 "Unexpected fault code");
3607 static bool test_OpenPrinter_badname(struct torture_context *tctx,
3608 struct dcerpc_pipe *p, const char *name)
3611 struct spoolss_OpenPrinter op;
3612 struct spoolss_OpenPrinterEx opEx;
3613 struct policy_handle handle;
3616 op.in.printername = name;
3617 op.in.datatype = NULL;
3618 op.in.devmode_ctr.devmode= NULL;
3619 op.in.access_mask = 0;
3620 op.out.handle = &handle;
3622 torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
3624 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
3625 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
3626 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
3627 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
3628 name, win_errstr(op.out.result));
3631 if (W_ERROR_IS_OK(op.out.result)) {
3632 ret &=test_ClosePrinter(tctx, p, &handle);
3635 opEx.in.printername = name;
3636 opEx.in.datatype = NULL;
3637 opEx.in.devmode_ctr.devmode = NULL;
3638 opEx.in.access_mask = 0;
3640 opEx.in.userlevel.level1 = NULL;
3641 opEx.out.handle = &handle;
3643 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
3645 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
3646 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
3647 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
3648 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
3649 name, win_errstr(opEx.out.result));
3652 if (W_ERROR_IS_OK(opEx.out.result)) {
3653 ret &=test_ClosePrinter(tctx, p, &handle);
3659 static bool test_OpenPrinter(struct torture_context *tctx,
3660 struct dcerpc_pipe *p,
3662 const char *environment)
3665 struct spoolss_OpenPrinter r;
3666 struct policy_handle handle;
3669 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
3670 r.in.datatype = NULL;
3671 r.in.devmode_ctr.devmode= NULL;
3672 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3673 r.out.handle = &handle;
3675 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
3677 status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
3679 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
3681 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
3683 if (!test_GetPrinter(tctx, p, &handle, environment)) {
3687 if (!torture_setting_bool(tctx, "samba3", false)) {
3688 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
3693 if (!test_ClosePrinter(tctx, p, &handle)) {
3700 static bool call_OpenPrinterEx(struct torture_context *tctx,
3701 struct dcerpc_pipe *p,
3703 struct spoolss_DeviceMode *devmode,
3704 struct policy_handle *handle)
3706 struct spoolss_OpenPrinterEx r;
3707 struct spoolss_UserLevel1 userlevel1;
3710 if (name && name[0]) {
3711 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
3712 dcerpc_server_name(p), name);
3714 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
3715 dcerpc_server_name(p));
3718 r.in.datatype = NULL;
3719 r.in.devmode_ctr.devmode= devmode;
3720 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3722 r.in.userlevel.level1 = &userlevel1;
3723 r.out.handle = handle;
3725 userlevel1.size = 1234;
3726 userlevel1.client = "hello";
3727 userlevel1.user = "spottyfoot!";
3728 userlevel1.build = 1;
3729 userlevel1.major = 2;
3730 userlevel1.minor = 3;
3731 userlevel1.processor = 4;
3733 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
3735 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
3737 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
3739 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
3744 static bool test_OpenPrinterEx(struct torture_context *tctx,
3745 struct dcerpc_pipe *p,
3747 const char *environment)
3749 struct policy_handle handle;
3752 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
3756 if (!test_PrinterInfo_SD(tctx, p, &handle)) {
3760 if (!test_GetPrinter(tctx, p, &handle, environment)) {
3764 if (!test_EnumForms(tctx, p, &handle, false)) {
3768 if (!test_AddForm(tctx, p, &handle, false)) {
3772 if (!test_EnumPrinterData(tctx, p, &handle)) {
3776 if (!test_EnumPrinterDataEx(tctx, p, &handle, "PrinterDriverData")) {
3780 if (!test_printer_keys(tctx, p, &handle)) {
3784 if (!test_PausePrinter(tctx, p, &handle)) {
3788 if (!test_DoPrintTest(tctx, p, &handle)) {
3792 if (!test_ResumePrinter(tctx, p, &handle)) {
3796 if (!test_SetPrinterData(tctx, p, &handle)) {
3800 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name)) {
3804 if (!torture_setting_bool(tctx, "samba3", false)) {
3805 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
3810 if (!test_ClosePrinter(tctx, p, &handle)) {
3817 static bool test_EnumPrinters_old(struct torture_context *tctx,
3818 struct dcerpc_pipe *p,
3819 const char *environment)
3821 struct spoolss_EnumPrinters r;
3823 uint16_t levels[] = {1, 2, 4, 5};
3827 for (i=0;i<ARRAY_SIZE(levels);i++) {
3828 union spoolss_PrinterInfo *info;
3833 r.in.flags = PRINTER_ENUM_LOCAL;
3835 r.in.level = levels[i];
3838 r.out.needed = &needed;
3839 r.out.count = &count;
3842 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
3844 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
3845 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
3847 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3848 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3849 data_blob_clear(&blob);
3850 r.in.buffer = &blob;
3851 r.in.offered = needed;
3852 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
3855 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
3857 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
3859 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3862 torture_comment(tctx, "No printers returned\n");
3866 for (j=0;j<count;j++) {
3867 if (r.in.level == 1) {
3868 char *unc = talloc_strdup(tctx, info[j].info1.name);
3871 if (unc[0] == '\\' && unc[1] == '\\') {
3874 slash = strchr(unc, '\\');
3879 if (!test_OpenPrinter(tctx, p, name, environment)) {
3882 if (!test_OpenPrinterEx(tctx, p, name, environment)) {
3892 static bool test_GetPrinterDriver(struct torture_context *tctx,
3893 struct dcerpc_pipe *p,
3894 struct policy_handle *handle,
3895 const char *driver_name)
3897 struct spoolss_GetPrinterDriver r;
3900 r.in.handle = handle;
3901 r.in.architecture = "W32X86";
3905 r.out.needed = &needed;
3907 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
3909 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
3910 "failed to call GetPrinterDriver");
3911 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3912 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3913 data_blob_clear(&blob);
3914 r.in.buffer = &blob;
3915 r.in.offered = needed;
3916 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
3917 "failed to call GetPrinterDriver");
3920 torture_assert_werr_ok(tctx, r.out.result,
3921 "failed to call GetPrinterDriver");
3923 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3928 static bool test_GetPrinterDriver2(struct torture_context *tctx,
3929 struct dcerpc_pipe *p,
3930 struct policy_handle *handle,
3931 const char *driver_name,
3932 const char *architecture)
3934 struct spoolss_GetPrinterDriver2 r;
3935 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
3937 uint32_t server_major_version;
3938 uint32_t server_minor_version;
3941 r.in.handle = handle;
3942 r.in.architecture = architecture;
3943 r.in.client_major_version = 3;
3944 r.in.client_minor_version = 0;
3945 r.out.needed = &needed;
3946 r.out.server_major_version = &server_major_version;
3947 r.out.server_minor_version = &server_minor_version;
3949 for (i=0;i<ARRAY_SIZE(levels);i++) {
3953 r.in.level = levels[i];
3955 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
3956 driver_name, r.in.level);
3958 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
3959 "failed to call GetPrinterDriver2");
3960 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3961 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3962 data_blob_clear(&blob);
3963 r.in.buffer = &blob;
3964 r.in.offered = needed;
3965 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
3966 "failed to call GetPrinterDriver2");
3969 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
3970 switch (r.in.level) {
3979 torture_assert_werr_ok(tctx, r.out.result,
3980 "failed to call GetPrinterDriver2");
3982 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3988 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
3989 struct dcerpc_pipe *p,
3990 const char *environment)
3992 struct spoolss_EnumPrinterDrivers r;
3994 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
3997 for (i=0;i<ARRAY_SIZE(levels);i++) {
4001 union spoolss_DriverInfo *info;
4003 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
4004 r.in.environment = environment;
4005 r.in.level = levels[i];
4008 r.out.needed = &needed;
4009 r.out.count = &count;
4012 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
4014 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
4016 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
4018 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4019 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4020 data_blob_clear(&blob);
4021 r.in.buffer = &blob;
4022 r.in.offered = needed;
4023 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
4026 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
4028 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
4031 torture_comment(tctx, "No printer drivers returned\n");
4035 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4041 static bool test_DeletePrinter(struct torture_context *tctx,
4042 struct dcerpc_pipe *p,
4043 struct policy_handle *handle)
4045 struct spoolss_DeletePrinter r;
4047 torture_comment(tctx, "Testing DeletePrinter\n");
4049 r.in.handle = handle;
4051 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter(p, tctx, &r),
4052 "failed to delete printer");
4053 torture_assert_werr_ok(tctx, r.out.result,
4054 "failed to delete printer");
4059 static bool test_EnumPrinters_findname(struct torture_context *tctx,
4060 struct dcerpc_pipe *p,
4066 struct spoolss_EnumPrinters e;
4068 union spoolss_PrinterInfo *info;
4079 e.out.count = &count;
4081 e.out.needed = &needed;
4083 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
4084 "failed to enum printers");
4086 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
4087 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4088 data_blob_clear(&blob);
4089 e.in.buffer = &blob;
4090 e.in.offered = needed;
4092 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
4093 "failed to enum printers");
4096 torture_assert_werr_ok(tctx, e.out.result,
4097 "failed to enum printers");
4099 for (i=0; i < count; i++) {
4101 const char *current = NULL;
4106 current = info[i].info1.name;
4110 if (strequal(current, name)) {
4115 p = strrchr(current, '\\');
4118 torture_warning(tctx,
4119 "server returns printername %s incl. servername although we did not set servername", current);
4122 if (strequal(p, name)) {
4132 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
4133 struct dcerpc_pipe *p,
4134 const char *printername,
4138 struct spoolss_AddPrinter r;
4139 struct spoolss_AddPrinterEx rex;
4140 struct spoolss_SetPrinterInfoCtr info_ctr;
4141 struct spoolss_SetPrinterInfo1 info1;
4142 struct spoolss_DevmodeContainer devmode_ctr;
4143 struct sec_desc_buf secdesc_ctr;
4144 struct spoolss_UserLevelCtr userlevel_ctr;
4145 struct policy_handle handle;
4148 ZERO_STRUCT(devmode_ctr);
4149 ZERO_STRUCT(secdesc_ctr);
4150 ZERO_STRUCT(userlevel_ctr);
4153 torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
4155 /* try to add printer to wellknown printer list (level 1) */
4157 userlevel_ctr.level = 1;
4159 info_ctr.info.info1 = &info1;
4162 rex.in.server = NULL;
4163 rex.in.info_ctr = &info_ctr;
4164 rex.in.devmode_ctr = &devmode_ctr;
4165 rex.in.secdesc_ctr = &secdesc_ctr;
4166 rex.in.userlevel_ctr = &userlevel_ctr;
4167 rex.out.handle = &handle;
4170 r.in.info_ctr = &info_ctr;
4171 r.in.devmode_ctr = &devmode_ctr;
4172 r.in.secdesc_ctr = &secdesc_ctr;
4173 r.out.handle = &handle;
4175 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4176 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4177 "failed to add printer");
4178 result = ex ? rex.out.result : r.out.result;
4179 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
4180 "unexpected result code");
4182 info1.name = printername;
4183 info1.flags = PRINTER_ATTRIBUTE_SHARED;
4185 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4186 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4187 "failed to add printer");
4188 result = ex ? rex.out.result : r.out.result;
4189 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4190 "unexpected result code");
4192 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
4193 better do a real check to see the printer is really there */
4195 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4196 PRINTER_ENUM_NETWORK, 1,
4199 "failed to enum printers");
4201 torture_assert(tctx, found, "failed to find newly added printer");
4205 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4206 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4207 "failed to add printer");
4208 result = ex ? rex.out.result : r.out.result;
4209 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4210 "unexpected result code");
4212 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
4213 better do a real check to see the printer has really been removed
4214 from the well known printer list */
4218 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4219 PRINTER_ENUM_NETWORK, 1,
4222 "failed to enum printers");
4224 torture_assert(tctx, !found, "printer still in well known printer list");
4229 static bool test_AddPrinter_normal(struct torture_context *tctx,
4230 struct dcerpc_pipe *p,
4231 struct policy_handle *handle_p,
4232 const char *printername,
4233 const char *drivername,
4234 const char *portname,
4238 struct spoolss_AddPrinter r;
4239 struct spoolss_AddPrinterEx rex;
4240 struct spoolss_SetPrinterInfoCtr info_ctr;
4241 struct spoolss_SetPrinterInfo2 info2;
4242 struct spoolss_DevmodeContainer devmode_ctr;
4243 struct sec_desc_buf secdesc_ctr;
4244 struct spoolss_UserLevelCtr userlevel_ctr;
4245 struct policy_handle handle;
4247 bool existing_printer_deleted = false;
4249 ZERO_STRUCT(devmode_ctr);
4250 ZERO_STRUCT(secdesc_ctr);
4251 ZERO_STRUCT(userlevel_ctr);
4253 torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
4255 userlevel_ctr.level = 1;
4257 rex.in.server = NULL;
4258 rex.in.info_ctr = &info_ctr;
4259 rex.in.devmode_ctr = &devmode_ctr;
4260 rex.in.secdesc_ctr = &secdesc_ctr;
4261 rex.in.userlevel_ctr = &userlevel_ctr;
4262 rex.out.handle = &handle;
4265 r.in.info_ctr = &info_ctr;
4266 r.in.devmode_ctr = &devmode_ctr;
4267 r.in.secdesc_ctr = &secdesc_ctr;
4268 r.out.handle = &handle;
4272 /* try to add printer to printer list (level 2) */
4276 info_ctr.info.info2 = &info2;
4279 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4280 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4281 "failed to add printer");
4282 result = ex ? rex.out.result : r.out.result;
4283 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
4284 "unexpected result code");
4286 info2.printername = printername;
4288 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4289 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4290 "failed to add printer");
4291 result = ex ? rex.out.result : r.out.result;
4293 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
4294 struct policy_handle printer_handle;
4296 if (existing_printer_deleted) {
4297 torture_fail(tctx, "already deleted printer still existing?");
4300 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
4301 "failed to open printer handle");
4303 torture_assert(tctx, test_DeletePrinter(tctx, p, &printer_handle),
4304 "failed to delete printer");
4306 torture_assert(tctx, test_ClosePrinter(tctx, p, &printer_handle),
4307 "failed to close server handle");
4309 existing_printer_deleted = true;
4314 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
4315 "unexpected result code");
4317 info2.portname = portname;
4319 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4320 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4321 "failed to add printer");
4322 result = ex ? rex.out.result : r.out.result;
4323 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
4324 "unexpected result code");
4326 info2.drivername = drivername;
4328 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4329 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4330 "failed to add printer");
4331 result = ex ? rex.out.result : r.out.result;
4333 /* w2k8r2 allows to add printer w/o defining printprocessor */
4335 if (!W_ERROR_IS_OK(result)) {
4336 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
4337 "unexpected result code");
4339 info2.printprocessor = "winprint";
4341 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4342 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4343 "failed to add printer");
4344 result = ex ? rex.out.result : r.out.result;
4345 torture_assert_werr_ok(tctx, result,
4346 "failed to add printer");
4351 /* we are paranoid, really check if the printer is there now */
4353 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4354 PRINTER_ENUM_LOCAL, 1,
4357 "failed to enum printers");
4358 torture_assert(tctx, found, "failed to find newly added printer");
4360 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4361 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4362 "failed to add printer");
4363 result = ex ? rex.out.result : r.out.result;
4364 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4365 "unexpected result code");
4370 static bool test_AddPrinterEx(struct torture_context *tctx,
4371 struct dcerpc_pipe *p,
4372 struct policy_handle *handle_p,
4373 const char *printername,
4374 const char *drivername,
4375 const char *portname)
4379 if (!torture_setting_bool(tctx, "samba3", false)) {
4380 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
4381 torture_comment(tctx, "failed to add printer to well known list\n");
4386 if (!test_AddPrinter_normal(tctx, p, handle_p,
4387 printername, drivername, portname,
4389 torture_comment(tctx, "failed to add printer to printer list\n");
4396 static bool test_AddPrinter(struct torture_context *tctx,
4397 struct dcerpc_pipe *p,
4398 struct policy_handle *handle_p,
4399 const char *printername,
4400 const char *drivername,
4401 const char *portname)
4405 if (!torture_setting_bool(tctx, "samba3", false)) {
4406 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
4407 torture_comment(tctx, "failed to add printer to well known list\n");
4412 if (!test_AddPrinter_normal(tctx, p, handle_p,
4413 printername, drivername, portname,
4415 torture_comment(tctx, "failed to add printer to printer list\n");
4422 static bool test_printer_info(struct torture_context *tctx,
4423 struct dcerpc_pipe *p,
4424 struct policy_handle *handle)
4428 if (torture_setting_bool(tctx, "samba3", false)) {
4429 torture_skip(tctx, "skipping printer info cross tests against samba 3");
4432 if (!test_PrinterInfo(tctx, p, handle)) {
4436 if (!test_SetPrinter_errors(tctx, p, handle)) {
4443 static bool test_EnumPrinterKey(struct torture_context *tctx,
4444 struct dcerpc_pipe *p,
4445 struct policy_handle *handle,
4446 const char *key_name,
4447 const char ***array)
4449 struct spoolss_EnumPrinterKey r;
4450 uint32_t needed = 0;
4451 union spoolss_KeyNames key_buffer;
4452 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
4456 r.in.handle = handle;
4457 r.in.key_name = key_name;
4458 r.out.key_buffer = &key_buffer;
4459 r.out.needed = &needed;
4460 r.out._ndr_size = &_ndr_size;
4462 for (i=0; i < ARRAY_SIZE(offered); i++) {
4464 if (offered[i] < 0 && needed) {
4468 r.in.offered = needed + offered[i];
4470 r.in.offered = offered[i];
4473 ZERO_STRUCT(key_buffer);
4475 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
4477 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
4478 "failed to call EnumPrinterKey");
4479 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4481 torture_assert(tctx, (_ndr_size == r.in.offered/2),
4482 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
4483 _ndr_size, r.in.offered/2));
4485 r.in.offered = needed;
4486 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
4487 "failed to call EnumPrinterKey");
4490 if (offered[i] > 0) {
4491 torture_assert_werr_ok(tctx, r.out.result,
4492 "failed to call EnumPrinterKey");
4495 torture_assert(tctx, (_ndr_size == r.in.offered/2),
4496 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
4497 _ndr_size, r.in.offered/2));
4499 torture_assert(tctx, (*r.out.needed <= r.in.offered),
4500 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
4502 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
4503 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
4505 if (key_buffer.string_array) {
4506 uint32_t calc_needed = 0;
4508 for (s=0; key_buffer.string_array[s]; s++) {
4509 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
4511 if (!key_buffer.string_array[0]) {
4516 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
4517 "EnumPrinterKey unexpected size");
4522 *array = key_buffer.string_array;
4528 bool test_printer_keys(struct torture_context *tctx,
4529 struct dcerpc_pipe *p,
4530 struct policy_handle *handle)
4532 const char **key_array = NULL;
4535 torture_comment(tctx, "\nTesting Printer Keys\n");
4537 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, "", &key_array),
4538 "failed to call test_EnumPrinterKey");
4540 for (i=0; key_array && key_array[i]; i++) {
4541 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, key_array[i], NULL),
4542 "failed to call test_EnumPrinterKey");
4544 for (i=0; key_array && key_array[i]; i++) {
4545 torture_assert(tctx, test_EnumPrinterDataEx(tctx, p, handle, key_array[i]),
4546 "failed to call test_EnumPrinterDataEx");
4552 static bool test_one_printer(struct torture_context *tctx,
4553 struct dcerpc_pipe *p,
4554 struct policy_handle *handle,
4559 if (!test_printer_info(tctx, p, handle)) {
4563 if (!test_PrinterInfo_SD(tctx, p, handle)) {
4567 if (!test_PrinterInfo_DevMode(tctx, p, handle, name)) {
4571 if (!test_ChangeID(tctx, p, handle)) {
4575 if (!test_printer_keys(tctx, p, handle)) {
4579 if (!test_SetPrinterDataEx_matrix(tctx, p, handle, name)) {
4586 static bool test_printer(struct torture_context *tctx,
4587 struct dcerpc_pipe *p)
4590 struct policy_handle handle[2];
4592 const char *drivername = "Microsoft XPS Document Writer";
4593 const char *portname = "LPT1:";
4595 /* test printer created via AddPrinter */
4597 if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
4601 if (!test_one_printer(tctx, p, &handle[0], TORTURE_PRINTER)) {
4605 if (!test_DeletePrinter(tctx, p, &handle[0])) {
4609 if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
4610 TORTURE_PRINTER, &found)) {
4614 torture_assert(tctx, !found, "deleted printer still there");
4616 /* test printer created via AddPrinterEx */
4618 if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
4622 if (!test_one_printer(tctx, p, &handle[1], TORTURE_PRINTER_EX)) {
4626 if (!test_DeletePrinter(tctx, p, &handle[1])) {
4630 if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
4631 TORTURE_PRINTER_EX, &found)) {
4635 torture_assert(tctx, !found, "deleted printer still there");
4640 static bool test_architecture_buffer(struct torture_context *tctx,
4641 struct dcerpc_pipe *p)
4643 struct spoolss_OpenPrinterEx r;
4644 struct spoolss_UserLevel1 u1;
4645 struct policy_handle handle;
4646 uint32_t architectures[] = {
4647 PROCESSOR_ARCHITECTURE_INTEL,
4648 PROCESSOR_ARCHITECTURE_IA64,
4649 PROCESSOR_ARCHITECTURE_AMD64
4654 for (i=0; i < ARRAY_SIZE(architectures); i++) {
4656 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
4664 u1.processor = architectures[i];
4666 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
4667 r.in.datatype = NULL;
4668 r.in.devmode_ctr.devmode= NULL;
4669 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4671 r.in.userlevel.level1 = &u1;
4672 r.out.handle = &handle;
4674 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx(p, tctx, &r), "");
4675 torture_assert_werr_ok(tctx, r.out.result, "");
4678 struct spoolss_EnumPrinters e;
4680 union spoolss_PrinterInfo *info;
4682 e.in.flags = PRINTER_ENUM_LOCAL;
4687 e.out.count = &count;
4689 e.out.needed = &needed[i];
4691 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e), "");
4693 torture_comment(tctx, "needed was %d\n", needed[i]);
4697 torture_assert(tctx, test_ClosePrinter(tctx, p, &handle), "");
4700 for (i=1; i < ARRAY_SIZE(architectures); i++) {
4701 if (needed[i-1] != needed[i]) {
4703 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
4704 needed[i-1], architectures[i-1], needed[i], architectures[i]));
4711 bool torture_rpc_spoolss(struct torture_context *torture)
4714 struct dcerpc_pipe *p;
4716 struct test_spoolss_context *ctx;
4717 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
4719 status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
4720 if (!NT_STATUS_IS_OK(status)) {
4724 ctx = talloc_zero(torture, struct test_spoolss_context);
4726 ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
4727 ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle);
4728 ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
4729 ret &= test_AddForm(torture, p, &ctx->server_handle, true);
4730 ret &= test_EnumPorts(torture, p, ctx);
4731 ret &= test_GetPrinterDriverDirectory(torture, p, ctx, environment);
4732 ret &= test_GetPrintProcessorDirectory(torture, p, ctx, environment);
4733 ret &= test_EnumPrinterDrivers(torture, p, ctx, environment);
4734 ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
4735 ret &= test_EnumMonitors(torture, p, ctx);
4736 ret &= test_EnumPrintProcessors(torture, p, ctx, environment);
4737 ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
4738 ret &= test_EnumPrinters(torture, p, ctx);
4739 ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
4740 ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
4741 ret &= test_OpenPrinter_badname(torture, p, "");
4742 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
4743 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
4744 ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
4745 ret &= test_OpenPrinter_badname(torture, p,
4746 talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
4749 ret &= test_AddPort(torture, p);
4750 ret &= test_EnumPorts_old(torture, p);
4751 ret &= test_EnumPrinters_old(torture, p, environment);
4752 ret &= test_EnumPrinterDrivers_old(torture, p, environment);
4753 ret &= test_architecture_buffer(torture, p);
4758 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
4760 struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
4762 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
4763 "printer", &ndr_table_spoolss);
4765 torture_rpc_tcase_add_test(tcase, "printer", test_printer);