2 Unix SMB/CIFS implementation.
3 test suite for spoolss rpc operations
5 Copyright (C) Tim Potter 2003
6 Copyright (C) Stefan Metzmacher 2005
7 Copyright (C) Jelmer Vernooij 2007
8 Copyright (C) Guenther Deschner 2009
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "torture/torture.h"
26 #include "torture/rpc/rpc.h"
27 #include "librpc/gen_ndr/ndr_misc.h"
28 #include "librpc/gen_ndr/ndr_spoolss.h"
29 #include "librpc/gen_ndr/ndr_spoolss_c.h"
30 #include "param/param.h"
32 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
33 #define TORTURE_PRINTER "torture_printer"
34 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
35 #define TORTURE_PRINTER_EX "torture_printer_ex"
37 struct test_spoolss_context {
38 /* print server handle */
39 struct policy_handle server_handle;
42 uint32_t port_count[3];
43 union spoolss_PortInfo *ports[3];
45 /* for EnumPrinterDrivers */
46 uint32_t driver_count[8];
47 union spoolss_DriverInfo *drivers[8];
49 /* for EnumMonitors */
50 uint32_t monitor_count[3];
51 union spoolss_MonitorInfo *monitors[3];
53 /* for EnumPrintProcessors */
54 uint32_t print_processor_count[2];
55 union spoolss_PrintProcessorInfo *print_processors[2];
57 /* for EnumPrinters */
58 uint32_t printer_count[6];
59 union spoolss_PrinterInfo *printers[6];
62 #define COMPARE_STRING(tctx, c,r,e) \
63 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
65 /* not every compiler supports __typeof__() */
67 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
68 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
69 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
71 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
72 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
76 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
79 #define COMPARE_UINT32(tctx, c, r, e) do {\
80 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
81 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
84 #define COMPARE_UINT64(tctx, c, r, e) do {\
85 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
86 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
90 #define COMPARE_NTTIME(tctx, c, r, e) do {\
91 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
92 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
95 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
101 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
104 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
106 for (__i=0;c.e[__i] != NULL; __i++) { \
107 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
111 #define CHECK_ALIGN(size, n) do {\
113 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
114 size, n, size + n - (size % n));\
118 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
120 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, ic, needed, align) do { \
121 uint32_t size = ndr_size_##fn##_info(tctx, ic, level, count, info);\
122 uint32_t round_size = DO_ROUND(size, align);\
123 if (round_size != needed) {\
124 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
125 CHECK_ALIGN(size, align);\
129 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, ic, needed, align) do { \
130 uint32_t size = ndr_size_##fn##_info(tctx, ic, count, info);\
131 uint32_t round_size = DO_ROUND(size, align);\
132 if (round_size != needed) {\
133 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
134 CHECK_ALIGN(size, align);\
138 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, ic, needed, align) do { \
139 uint32_t size = ndr_size_##fn(info, level, ic, 0);\
140 uint32_t round_size = DO_ROUND(size, align);\
141 if (round_size != needed) {\
142 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
143 CHECK_ALIGN(size, align);\
147 static bool test_OpenPrinter_server(struct torture_context *tctx,
148 struct dcerpc_pipe *p,
149 struct policy_handle *server_handle)
152 struct spoolss_OpenPrinter op;
154 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
155 op.in.datatype = NULL;
156 op.in.devmode_ctr.devmode= NULL;
157 op.in.access_mask = 0;
158 op.out.handle = server_handle;
160 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
162 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
163 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
164 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
169 static bool test_EnumPorts(struct torture_context *tctx,
170 struct dcerpc_pipe *p,
171 struct test_spoolss_context *ctx)
174 struct spoolss_EnumPorts r;
175 uint16_t levels[] = { 1, 2 };
178 for (i=0;i<ARRAY_SIZE(levels);i++) {
179 int level = levels[i];
183 union spoolss_PortInfo *info;
185 r.in.servername = "";
189 r.out.needed = &needed;
190 r.out.count = &count;
193 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
195 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
196 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
197 if (W_ERROR_IS_OK(r.out.result)) {
198 /* TODO: do some more checks here */
201 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
202 "EnumPorts unexpected return code");
204 blob = data_blob_talloc(ctx, NULL, needed);
205 data_blob_clear(&blob);
207 r.in.offered = needed;
209 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
210 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
212 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
214 torture_assert(tctx, info, "EnumPorts returned no info");
216 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
218 ctx->port_count[level] = count;
219 ctx->ports[level] = info;
222 for (i=1;i<ARRAY_SIZE(levels);i++) {
223 int level = levels[i];
224 int old_level = levels[i-1];
225 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
226 "EnumPorts invalid value");
228 /* if the array sizes are not the same we would maybe segfault in the following code */
230 for (i=0;i<ARRAY_SIZE(levels);i++) {
231 int level = levels[i];
232 for (j=0;j<ctx->port_count[level];j++) {
233 union spoolss_PortInfo *cur = &ctx->ports[level][j];
234 union spoolss_PortInfo *ref = &ctx->ports[2][j];
237 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
240 /* level 2 is our reference, and it makes no sense to compare it to itself */
249 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
250 struct dcerpc_pipe *p,
251 struct test_spoolss_context *ctx)
254 struct spoolss_GetPrintProcessorDirectory r;
269 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
272 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
278 for (i=0;i<ARRAY_SIZE(levels);i++) {
279 int level = levels[i].level;
282 r.in.server = levels[i].server;
283 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
287 r.out.needed = &needed;
289 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
291 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
292 torture_assert_ntstatus_ok(tctx, status,
293 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
294 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
295 "GetPrintProcessorDirectory unexpected return code");
297 blob = data_blob_talloc(ctx, NULL, needed);
298 data_blob_clear(&blob);
300 r.in.offered = needed;
302 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
303 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
305 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
307 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
314 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
315 struct dcerpc_pipe *p,
316 struct test_spoolss_context *ctx)
319 struct spoolss_GetPrinterDriverDirectory r;
334 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
337 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
343 for (i=0;i<ARRAY_SIZE(levels);i++) {
344 int level = levels[i].level;
347 r.in.server = levels[i].server;
348 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
352 r.out.needed = &needed;
354 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
356 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
357 torture_assert_ntstatus_ok(tctx, status,
358 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
359 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
360 "GetPrinterDriverDirectory unexpected return code");
362 blob = data_blob_talloc(ctx, NULL, needed);
363 data_blob_clear(&blob);
365 r.in.offered = needed;
367 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
368 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
370 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
372 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
378 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
379 struct dcerpc_pipe *p,
380 struct test_spoolss_context *ctx,
381 const char *architecture)
384 struct spoolss_EnumPrinterDrivers r;
385 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
388 for (i=0;i<ARRAY_SIZE(levels);i++) {
389 int level = levels[i];
393 union spoolss_DriverInfo *info;
395 /* FIXME: gd, come back and fix "" as server, and handle
396 * priority of returned error codes in torture test and samba 3
399 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
400 r.in.environment = architecture;
404 r.out.needed = &needed;
405 r.out.count = &count;
408 torture_comment(tctx, "Testing EnumPrinterDrivers level %u (%s)\n", r.in.level, r.in.environment);
410 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
411 torture_assert_ntstatus_ok(tctx, status,
412 "dcerpc_spoolss_EnumPrinterDrivers failed");
413 if (W_ERROR_IS_OK(r.out.result)) {
414 /* TODO: do some more checks here */
417 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
418 blob = data_blob_talloc(ctx, NULL, needed);
419 data_blob_clear(&blob);
421 r.in.offered = needed;
423 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
424 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
427 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
429 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
431 ctx->driver_count[level] = count;
432 ctx->drivers[level] = info;
435 for (i=1;i<ARRAY_SIZE(levels);i++) {
436 int level = levels[i];
437 int old_level = levels[i-1];
439 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
440 "EnumPrinterDrivers invalid value");
443 for (i=0;i<ARRAY_SIZE(levels);i++) {
444 int level = levels[i];
446 for (j=0;j<ctx->driver_count[level];j++) {
447 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
448 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
452 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
455 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
456 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
457 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
458 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
459 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
460 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
463 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
464 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
465 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
466 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
467 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
468 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
469 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
470 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
471 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
472 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
475 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
476 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
477 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
478 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
479 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
480 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
481 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
482 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
483 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
484 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
485 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
488 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
489 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
490 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
491 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
492 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
493 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
494 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
495 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
496 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
499 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
500 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
501 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
502 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
503 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
504 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
505 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
506 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
507 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
508 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
509 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
510 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
511 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
512 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
513 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
514 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
515 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
518 /* level 8 is our reference, and it makes no sense to compare it to itself */
527 static bool test_EnumMonitors(struct torture_context *tctx,
528 struct dcerpc_pipe *p,
529 struct test_spoolss_context *ctx)
532 struct spoolss_EnumMonitors r;
533 uint16_t levels[] = { 1, 2 };
536 for (i=0;i<ARRAY_SIZE(levels);i++) {
537 int level = levels[i];
541 union spoolss_MonitorInfo *info;
543 r.in.servername = "";
547 r.out.needed = &needed;
548 r.out.count = &count;
551 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
553 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
554 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
555 if (W_ERROR_IS_OK(r.out.result)) {
556 /* TODO: do some more checks here */
559 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
560 "EnumMonitors failed");
562 blob = data_blob_talloc(ctx, NULL, needed);
563 data_blob_clear(&blob);
565 r.in.offered = needed;
567 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
568 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
570 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
572 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
574 ctx->monitor_count[level] = count;
575 ctx->monitors[level] = info;
578 for (i=1;i<ARRAY_SIZE(levels);i++) {
579 int level = levels[i];
580 int old_level = levels[i-1];
581 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
582 "EnumMonitors invalid value");
585 for (i=0;i<ARRAY_SIZE(levels);i++) {
586 int level = levels[i];
587 for (j=0;j<ctx->monitor_count[level];j++) {
588 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
589 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
592 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
595 /* level 2 is our reference, and it makes no sense to compare it to itself */
604 static bool test_EnumPrintProcessors(struct torture_context *tctx,
605 struct dcerpc_pipe *p,
606 struct test_spoolss_context *ctx)
609 struct spoolss_EnumPrintProcessors r;
610 uint16_t levels[] = { 1 };
613 for (i=0;i<ARRAY_SIZE(levels);i++) {
614 int level = levels[i];
618 union spoolss_PrintProcessorInfo *info;
620 r.in.servername = "";
621 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
625 r.out.needed = &needed;
626 r.out.count = &count;
629 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
631 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
632 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
633 if (W_ERROR_IS_OK(r.out.result)) {
634 /* TODO: do some more checks here */
637 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
638 "EnumPrintProcessors unexpected return code");
640 blob = data_blob_talloc(ctx, NULL, needed);
641 data_blob_clear(&blob);
643 r.in.offered = needed;
645 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
646 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
648 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
650 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
652 ctx->print_processor_count[level] = count;
653 ctx->print_processors[level] = info;
656 for (i=1;i<ARRAY_SIZE(levels);i++) {
657 int level = levels[i];
658 int old_level = levels[i-1];
659 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
660 "EnumPrintProcessors failed");
663 for (i=0;i<ARRAY_SIZE(levels);i++) {
664 int level = levels[i];
665 for (j=0;j<ctx->print_processor_count[level];j++) {
667 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
668 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
672 /* level 1 is our reference, and it makes no sense to compare it to itself */
681 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
682 struct dcerpc_pipe *p,
683 struct test_spoolss_context *ctx)
686 struct spoolss_EnumPrintProcDataTypes r;
687 uint16_t levels[] = { 1 };
690 for (i=0;i<ARRAY_SIZE(levels);i++) {
691 int level = levels[i];
695 union spoolss_PrintProcDataTypesInfo *info;
697 r.in.servername = "";
698 r.in.print_processor_name = "winprint";
702 r.out.needed = &needed;
703 r.out.count = &count;
706 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
708 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
709 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
710 if (W_ERROR_IS_OK(r.out.result)) {
711 /* TODO: do some more checks here */
714 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
715 "EnumPrintProcDataTypes unexpected return code");
717 blob = data_blob_talloc(ctx, NULL, needed);
718 data_blob_clear(&blob);
720 r.in.offered = needed;
722 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
723 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
725 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
727 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
735 static bool test_EnumPrinters(struct torture_context *tctx,
736 struct dcerpc_pipe *p,
737 struct test_spoolss_context *ctx)
739 struct spoolss_EnumPrinters r;
741 uint16_t levels[] = { 0, 1, 2, 4, 5 };
744 for (i=0;i<ARRAY_SIZE(levels);i++) {
745 int level = levels[i];
749 union spoolss_PrinterInfo *info;
751 r.in.flags = PRINTER_ENUM_LOCAL;
756 r.out.needed = &needed;
757 r.out.count = &count;
760 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
762 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
763 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
764 if (W_ERROR_IS_OK(r.out.result)) {
765 /* TODO: do some more checks here */
768 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
769 "EnumPrinters unexpected return code");
771 blob = data_blob_talloc(ctx, NULL, needed);
772 data_blob_clear(&blob);
774 r.in.offered = needed;
776 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
777 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
779 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
781 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
783 ctx->printer_count[level] = count;
784 ctx->printers[level] = info;
787 for (i=1;i<ARRAY_SIZE(levels);i++) {
788 int level = levels[i];
789 int old_level = levels[i-1];
790 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
791 "EnumPrinters invalid value");
794 for (i=0;i<ARRAY_SIZE(levels);i++) {
795 int level = levels[i];
796 for (j=0;j<ctx->printer_count[level];j++) {
797 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
798 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
801 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
802 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
803 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
804 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
805 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
806 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
807 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
808 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
809 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
810 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
811 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
812 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
813 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
814 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
815 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
816 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
817 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
818 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
819 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
820 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
821 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
822 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
823 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
824 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
825 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
826 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
827 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
828 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
829 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
832 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
833 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
834 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
835 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
838 /* level 2 is our reference, and it makes no sense to compare it to itself */
841 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
842 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
843 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
846 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
847 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
848 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
849 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
850 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
857 * - verify that the port of a printer was in the list returned by EnumPorts
863 static bool test_GetPrinter(struct torture_context *tctx,
864 struct dcerpc_pipe *p,
865 struct policy_handle *handle)
868 struct spoolss_GetPrinter r;
869 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
873 for (i=0;i<ARRAY_SIZE(levels);i++) {
874 r.in.handle = handle;
875 r.in.level = levels[i];
878 r.out.needed = &needed;
880 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
882 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
883 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
885 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
886 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
887 data_blob_clear(&blob);
889 r.in.offered = needed;
890 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
893 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
895 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
897 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
903 static bool test_SetPrinter_errors(struct torture_context *tctx,
904 struct dcerpc_pipe *p,
905 struct policy_handle *handle)
907 struct spoolss_SetPrinter r;
908 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
911 struct spoolss_SetPrinterInfoCtr info_ctr;
912 struct spoolss_DevmodeContainer devmode_ctr;
913 struct sec_desc_buf secdesc_ctr;
916 info_ctr.info.info0 = NULL;
918 ZERO_STRUCT(devmode_ctr);
919 ZERO_STRUCT(secdesc_ctr);
921 r.in.handle = handle;
922 r.in.info_ctr = &info_ctr;
923 r.in.devmode_ctr = &devmode_ctr;
924 r.in.secdesc_ctr = &secdesc_ctr;
927 torture_comment(tctx, "Testing SetPrinter all zero\n");
929 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
930 "failed to call SetPrinter");
931 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
932 "failed to call SetPrinter");
935 for (i=0; i < ARRAY_SIZE(levels); i++) {
937 struct spoolss_SetPrinterInfo0 info0;
938 struct spoolss_SetPrinterInfo1 info1;
939 struct spoolss_SetPrinterInfo2 info2;
940 struct spoolss_SetPrinterInfo3 info3;
941 struct spoolss_SetPrinterInfo4 info4;
942 struct spoolss_SetPrinterInfo5 info5;
943 struct spoolss_SetPrinterInfo6 info6;
944 struct spoolss_SetPrinterInfo7 info7;
945 struct spoolss_DeviceModeInfo info8;
946 struct spoolss_DeviceModeInfo info9;
949 info_ctr.level = levels[i];
953 info_ctr.info.info0 = &info0;
957 info_ctr.info.info1 = &info1;
961 info_ctr.info.info2 = &info2;
965 info_ctr.info.info3 = &info3;
969 info_ctr.info.info4 = &info4;
973 info_ctr.info.info5 = &info5;
977 info_ctr.info.info6 = &info6;
981 info_ctr.info.info7 = &info7;
985 info_ctr.info.info8 = &info8;
989 info_ctr.info.info9 = &info9;
993 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
994 info_ctr.level, r.in.command);
996 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
997 "failed to call SetPrinter");
999 switch (r.in.command) {
1000 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1001 /* is ignored for all levels other then 0 */
1002 if (info_ctr.level > 0) {
1006 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1007 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1008 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1009 if (info_ctr.level > 0) {
1010 /* is invalid for all levels other then 0 */
1011 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1012 "unexpected error code returned");
1015 torture_assert_werr_ok(tctx, r.out.result,
1016 "failed to call SetPrinter with non 0 command");
1021 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1022 /* FIXME: gd needs further investigation */
1024 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1025 "unexpected error code returned");
1029 switch (info_ctr.level) {
1031 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1032 "unexpected error code returned");
1035 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1036 "unexpected error code returned");
1042 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1043 "unexpected error code returned");
1046 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1047 "unexpected error code returned");
1050 torture_assert_werr_ok(tctx, r.out.result,
1051 "failed to call SetPrinter");
1056 if (r.in.command < 5) {
1064 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1066 if ((r->level == 2) && (r->info.info2)) {
1067 r->info.info2->secdesc = NULL;
1068 r->info.info2->devmode = NULL;
1072 static bool test_PrinterInfo(struct torture_context *tctx,
1073 struct dcerpc_pipe *p,
1074 struct policy_handle *handle)
1077 struct spoolss_SetPrinter s;
1078 struct spoolss_GetPrinter q;
1079 struct spoolss_GetPrinter q0;
1080 struct spoolss_SetPrinterInfoCtr info_ctr;
1081 union spoolss_PrinterInfo info;
1082 struct spoolss_DevmodeContainer devmode_ctr;
1083 struct sec_desc_buf secdesc_ctr;
1088 uint32_t status_list[] = {
1089 /* these do not stick
1090 PRINTER_STATUS_PAUSED,
1091 PRINTER_STATUS_ERROR,
1092 PRINTER_STATUS_PENDING_DELETION, */
1093 PRINTER_STATUS_PAPER_JAM,
1094 PRINTER_STATUS_PAPER_OUT,
1095 PRINTER_STATUS_MANUAL_FEED,
1096 PRINTER_STATUS_PAPER_PROBLEM,
1097 PRINTER_STATUS_OFFLINE,
1098 PRINTER_STATUS_IO_ACTIVE,
1099 PRINTER_STATUS_BUSY,
1100 PRINTER_STATUS_PRINTING,
1101 PRINTER_STATUS_OUTPUT_BIN_FULL,
1102 PRINTER_STATUS_NOT_AVAILABLE,
1103 PRINTER_STATUS_WAITING,
1104 PRINTER_STATUS_PROCESSING,
1105 PRINTER_STATUS_INITIALIZING,
1106 PRINTER_STATUS_WARMING_UP,
1107 PRINTER_STATUS_TONER_LOW,
1108 PRINTER_STATUS_NO_TONER,
1109 PRINTER_STATUS_PAGE_PUNT,
1110 PRINTER_STATUS_USER_INTERVENTION,
1111 PRINTER_STATUS_OUT_OF_MEMORY,
1112 PRINTER_STATUS_DOOR_OPEN,
1113 PRINTER_STATUS_SERVER_UNKNOWN,
1114 PRINTER_STATUS_POWER_SAVE,
1115 /* these do not stick
1124 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1125 uint32_t attribute_list[] = {
1126 PRINTER_ATTRIBUTE_QUEUED,
1127 /* fails with WERR_INVALID_DATATYPE:
1128 PRINTER_ATTRIBUTE_DIRECT, */
1130 PRINTER_ATTRIBUTE_DEFAULT, */
1131 PRINTER_ATTRIBUTE_SHARED,
1133 PRINTER_ATTRIBUTE_NETWORK, */
1134 PRINTER_ATTRIBUTE_HIDDEN,
1135 PRINTER_ATTRIBUTE_LOCAL,
1136 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1137 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1138 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1139 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1141 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1142 /* fails with WERR_INVALID_DATATYPE:
1143 PRINTER_ATTRIBUTE_RAW_ONLY, */
1144 /* these do not stick
1145 PRINTER_ATTRIBUTE_PUBLISHED,
1146 PRINTER_ATTRIBUTE_FAX,
1147 PRINTER_ATTRIBUTE_TS,
1166 ZERO_STRUCT(devmode_ctr);
1167 ZERO_STRUCT(secdesc_ctr);
1169 s.in.handle = handle;
1171 s.in.info_ctr = &info_ctr;
1172 s.in.devmode_ctr = &devmode_ctr;
1173 s.in.secdesc_ctr = &secdesc_ctr;
1175 q.in.handle = handle;
1179 #define TESTGETCALL(call, r) \
1180 r.in.buffer = NULL; \
1182 r.out.needed = &needed; \
1183 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1184 if (!NT_STATUS_IS_OK(status)) { \
1185 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1186 r.in.level, nt_errstr(status), __location__); \
1190 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1191 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1192 data_blob_clear(&blob); \
1193 r.in.buffer = &blob; \
1194 r.in.offered = needed; \
1196 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1197 if (!NT_STATUS_IS_OK(status)) { \
1198 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1199 r.in.level, nt_errstr(status), __location__); \
1203 if (!W_ERROR_IS_OK(r.out.result)) { \
1204 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1205 r.in.level, win_errstr(r.out.result), __location__); \
1211 #define TESTSETCALL_EXP(call, r, err) \
1212 clear_info2(&info_ctr);\
1213 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1214 if (!NT_STATUS_IS_OK(status)) { \
1215 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1216 r.in.info_ctr->level, nt_errstr(status), __location__); \
1220 if (!W_ERROR_IS_OK(err)) { \
1221 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1222 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1223 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1228 if (!W_ERROR_IS_OK(r.out.result)) { \
1229 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1230 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1235 #define TESTSETCALL(call, r) \
1236 TESTSETCALL_EXP(call, r, WERR_OK)
1238 #define STRING_EQUAL(s1, s2, field) \
1239 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1240 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1241 #field, s2, __location__); \
1246 #define MEM_EQUAL(s1, s2, length, field) \
1247 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1248 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1249 #field, (const char *)s2, __location__); \
1254 #define INT_EQUAL(i1, i2, field) \
1256 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1257 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1262 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1263 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1264 q.in.level = lvl1; \
1265 TESTGETCALL(GetPrinter, q) \
1266 info_ctr.level = lvl1; \
1267 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1268 info_ctr.info.info ## lvl1->field1 = value;\
1269 TESTSETCALL_EXP(SetPrinter, s, err) \
1270 info_ctr.info.info ## lvl1->field1 = ""; \
1271 TESTGETCALL(GetPrinter, q) \
1272 info_ctr.info.info ## lvl1->field1 = value; \
1273 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1274 q.in.level = lvl2; \
1275 TESTGETCALL(GetPrinter, q) \
1276 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1277 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1280 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1281 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1284 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1285 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1286 q.in.level = lvl1; \
1287 TESTGETCALL(GetPrinter, q) \
1288 info_ctr.level = lvl1; \
1289 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1290 info_ctr.info.info ## lvl1->field1 = value; \
1291 TESTSETCALL(SetPrinter, s) \
1292 info_ctr.info.info ## lvl1->field1 = 0; \
1293 TESTGETCALL(GetPrinter, q) \
1294 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1295 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1296 q.in.level = lvl2; \
1297 TESTGETCALL(GetPrinter, q) \
1298 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1299 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1302 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1303 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1307 do { TESTGETCALL(GetPrinter, q0) } while (0);
1309 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1310 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1312 /* level 0 printername does not stick */
1313 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1314 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1315 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1316 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1317 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1318 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1319 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1320 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1321 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1322 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1323 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1324 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1325 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1326 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1327 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1329 /* servername can be set but does not stick
1330 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1331 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1332 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1335 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1336 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1337 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1338 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1339 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1341 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1342 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1343 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1344 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1345 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1346 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1347 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1348 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1349 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1350 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1352 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1353 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1355 (attribute_list[i] | default_attribute)
1357 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1359 (attribute_list[i] | default_attribute)
1361 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1363 (attribute_list[i] | default_attribute)
1365 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1367 (attribute_list[i] | default_attribute)
1369 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1371 (attribute_list[i] | default_attribute)
1373 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1375 (attribute_list[i] | default_attribute)
1377 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1379 (attribute_list[i] | default_attribute)
1381 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1383 (attribute_list[i] | default_attribute)
1385 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1387 (attribute_list[i] | default_attribute)
1389 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1391 (attribute_list[i] | default_attribute)
1393 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1395 (attribute_list[i] | default_attribute)
1397 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1399 (attribute_list[i] | default_attribute)
1403 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1404 /* level 2 sets do not stick
1405 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1406 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1407 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1408 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1409 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1410 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1413 /* priorities need to be between 0 and 99
1414 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1415 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1416 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1417 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1418 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1419 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1420 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1421 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1422 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1424 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1425 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1428 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1429 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1432 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1433 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1435 /* FIXME: gd also test devmode and secdesc behavior */
1438 /* verify composition of level 1 description field */
1439 const char *description;
1443 do { TESTGETCALL(GetPrinter, q0) } while (0);
1445 description = talloc_strdup(tctx, q0.out.info->info1.description);
1448 do { TESTGETCALL(GetPrinter, q0) } while (0);
1450 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1451 q0.out.info->info2.printername,
1452 q0.out.info->info2.drivername,
1453 q0.out.info->info2.location);
1455 do { STRING_EQUAL(description, tmp, "description")} while (0);
1462 static bool test_ClosePrinter(struct torture_context *tctx,
1463 struct dcerpc_pipe *p,
1464 struct policy_handle *handle)
1467 struct spoolss_ClosePrinter r;
1469 r.in.handle = handle;
1470 r.out.handle = handle;
1472 torture_comment(tctx, "Testing ClosePrinter\n");
1474 status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
1475 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
1476 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
1481 static bool test_GetForm(struct torture_context *tctx,
1482 struct dcerpc_pipe *p,
1483 struct policy_handle *handle,
1484 const char *form_name,
1488 struct spoolss_GetForm r;
1491 r.in.handle = handle;
1492 r.in.form_name = form_name;
1496 r.out.needed = &needed;
1498 torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
1500 status = dcerpc_spoolss_GetForm(p, tctx, &r);
1501 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1503 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1504 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1505 data_blob_clear(&blob);
1506 r.in.buffer = &blob;
1507 r.in.offered = needed;
1508 status = dcerpc_spoolss_GetForm(p, tctx, &r);
1509 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1511 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1513 torture_assert(tctx, r.out.info, "No form info returned");
1516 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1518 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
1523 static bool test_EnumForms(struct torture_context *tctx,
1524 struct dcerpc_pipe *p,
1525 struct policy_handle *handle, bool print_server)
1528 struct spoolss_EnumForms r;
1532 uint32_t levels[] = { 1, 2 };
1535 for (i=0; i<ARRAY_SIZE(levels); i++) {
1537 union spoolss_FormInfo *info;
1539 r.in.handle = handle;
1540 r.in.level = levels[i];
1543 r.out.needed = &needed;
1544 r.out.count = &count;
1547 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
1549 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1550 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1552 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
1556 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
1557 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1559 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1561 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1562 data_blob_clear(&blob);
1563 r.in.buffer = &blob;
1564 r.in.offered = needed;
1566 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1568 torture_assert(tctx, info, "No forms returned");
1570 for (j = 0; j < count; j++) {
1572 ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
1576 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1578 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
1580 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
1586 static bool test_DeleteForm(struct torture_context *tctx,
1587 struct dcerpc_pipe *p,
1588 struct policy_handle *handle,
1589 const char *form_name)
1592 struct spoolss_DeleteForm r;
1594 r.in.handle = handle;
1595 r.in.form_name = form_name;
1597 status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
1599 torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
1601 torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
1606 static bool test_AddForm(struct torture_context *tctx,
1607 struct dcerpc_pipe *p,
1608 struct policy_handle *handle, bool print_server)
1610 struct spoolss_AddForm r;
1611 struct spoolss_AddFormInfo1 addform;
1612 const char *form_name = "testform3";
1616 r.in.handle = handle;
1618 r.in.info.info1 = &addform;
1619 addform.flags = SPOOLSS_FORM_USER;
1620 addform.form_name = form_name;
1621 addform.size.width = 50;
1622 addform.size.height = 25;
1623 addform.area.left = 5;
1624 addform.area.top = 10;
1625 addform.area.right = 45;
1626 addform.area.bottom = 15;
1628 status = dcerpc_spoolss_AddForm(p, tctx, &r);
1630 torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
1632 torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
1634 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1637 struct spoolss_SetForm sf;
1638 struct spoolss_AddFormInfo1 setform;
1640 sf.in.handle = handle;
1641 sf.in.form_name = form_name;
1643 sf.in.info.info1= &setform;
1644 setform.flags = addform.flags;
1645 setform.form_name = addform.form_name;
1646 setform.size = addform.size;
1647 setform.area = addform.area;
1649 setform.size.width = 1234;
1651 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
1653 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
1655 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
1658 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1661 struct spoolss_EnumForms e;
1662 union spoolss_FormInfo *info;
1667 e.in.handle = handle;
1671 e.out.needed = &needed;
1672 e.out.count = &count;
1675 torture_comment(tctx, "Testing EnumForms level 1\n");
1677 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1678 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1680 if (print_server && W_ERROR_EQUAL(e.out.result, WERR_BADFID))
1681 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1683 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
1685 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1686 data_blob_clear(&blob);
1687 e.in.buffer = &blob;
1688 e.in.offered = needed;
1690 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1692 torture_assert(tctx, info, "No forms returned");
1694 for (j = 0; j < count; j++) {
1695 if (strequal(form_name, info[j].info1.form_name)) {
1701 torture_assert(tctx, found, "Newly added form not found in enum call");
1704 if (!test_DeleteForm(tctx, p, handle, form_name)) {
1711 static bool test_EnumPorts_old(struct torture_context *tctx,
1712 struct dcerpc_pipe *p)
1715 struct spoolss_EnumPorts r;
1718 union spoolss_PortInfo *info;
1720 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
1721 dcerpc_server_name(p));
1725 r.out.needed = &needed;
1726 r.out.count = &count;
1729 torture_comment(tctx, "Testing EnumPorts\n");
1731 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1733 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1735 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1736 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1737 data_blob_clear(&blob);
1738 r.in.buffer = &blob;
1739 r.in.offered = needed;
1741 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1742 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1743 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
1745 torture_assert(tctx, info, "No ports returned");
1748 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
1750 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
1755 static bool test_AddPort(struct torture_context *tctx,
1756 struct dcerpc_pipe *p)
1759 struct spoolss_AddPort r;
1761 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
1762 dcerpc_server_name(p));
1764 r.in.monitor_name = "foo";
1766 torture_comment(tctx, "Testing AddPort\n");
1768 status = dcerpc_spoolss_AddPort(p, tctx, &r);
1770 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
1772 /* win2k3 returns WERR_NOT_SUPPORTED */
1776 if (!W_ERROR_IS_OK(r.out.result)) {
1777 printf("AddPort failed - %s\n", win_errstr(r.out.result));
1786 static bool test_GetJob(struct torture_context *tctx,
1787 struct dcerpc_pipe *p,
1788 struct policy_handle *handle, uint32_t job_id)
1791 struct spoolss_GetJob r;
1792 union spoolss_JobInfo info;
1794 uint32_t levels[] = {1, 2 /* 3, 4 */};
1797 r.in.handle = handle;
1798 r.in.job_id = job_id;
1802 r.out.needed = &needed;
1805 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1807 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1808 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
1810 for (i = 0; i < ARRAY_SIZE(levels); i++) {
1812 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1816 r.in.level = levels[i];
1820 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1821 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1823 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1824 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1825 data_blob_clear(&blob);
1826 r.in.buffer = &blob;
1827 r.in.offered = needed;
1829 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1830 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1833 torture_assert(tctx, r.out.info, "No job info returned");
1834 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
1836 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
1842 static bool test_SetJob(struct torture_context *tctx,
1843 struct dcerpc_pipe *p,
1844 struct policy_handle *handle, uint32_t job_id,
1845 enum spoolss_JobControl command)
1848 struct spoolss_SetJob r;
1850 r.in.handle = handle;
1851 r.in.job_id = job_id;
1853 r.in.command = command;
1856 case SPOOLSS_JOB_CONTROL_PAUSE:
1857 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1859 case SPOOLSS_JOB_CONTROL_RESUME:
1860 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1862 case SPOOLSS_JOB_CONTROL_CANCEL:
1863 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1865 case SPOOLSS_JOB_CONTROL_RESTART:
1866 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1868 case SPOOLSS_JOB_CONTROL_DELETE:
1869 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1871 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
1872 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1874 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
1875 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1877 case SPOOLSS_JOB_CONTROL_RETAIN:
1878 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1880 case SPOOLSS_JOB_CONTROL_RELEASE:
1881 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1884 torture_comment(tctx, "Testing SetJob\n");
1888 status = dcerpc_spoolss_SetJob(p, tctx, &r);
1889 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
1890 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
1895 static bool test_AddJob(struct torture_context *tctx,
1896 struct dcerpc_pipe *p,
1897 struct policy_handle *handle)
1900 struct spoolss_AddJob r;
1904 r.in.handle = handle;
1906 r.out.needed = &needed;
1907 r.in.buffer = r.out.buffer = NULL;
1909 torture_comment(tctx, "Testing AddJob\n");
1911 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1912 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
1916 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1917 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
1923 static bool test_EnumJobs(struct torture_context *tctx,
1924 struct dcerpc_pipe *p,
1925 struct policy_handle *handle)
1928 struct spoolss_EnumJobs r;
1931 union spoolss_JobInfo *info;
1933 r.in.handle = handle;
1935 r.in.numjobs = 0xffffffff;
1939 r.out.needed = &needed;
1940 r.out.count = &count;
1943 torture_comment(tctx, "Testing EnumJobs\n");
1945 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1947 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1949 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1951 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1952 data_blob_clear(&blob);
1953 r.in.buffer = &blob;
1954 r.in.offered = needed;
1956 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1958 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1959 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1960 torture_assert(tctx, info, "No jobs returned");
1962 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
1964 for (j = 0; j < count; j++) {
1966 torture_assert(tctx, test_GetJob(tctx, p, handle, info[j].info1.job_id),
1967 "failed to call test_GetJob");
1970 if (!torture_setting_bool(tctx, "samba3", false)) {
1971 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
1972 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
1977 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1983 static bool test_DoPrintTest(struct torture_context *tctx,
1984 struct dcerpc_pipe *p,
1985 struct policy_handle *handle)
1989 struct spoolss_StartDocPrinter s;
1990 struct spoolss_DocumentInfo1 info1;
1991 struct spoolss_StartPagePrinter sp;
1992 struct spoolss_WritePrinter w;
1993 struct spoolss_EndPagePrinter ep;
1994 struct spoolss_EndDocPrinter e;
1997 uint32_t num_written;
1999 torture_comment(tctx, "Testing StartDocPrinter\n");
2001 s.in.handle = handle;
2003 s.in.info.info1 = &info1;
2004 s.out.job_id = &job_id;
2005 info1.document_name = "TorturePrintJob";
2006 info1.output_file = NULL;
2007 info1.datatype = "RAW";
2009 status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
2010 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
2011 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
2013 for (i=1; i < 4; i++) {
2014 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
2016 sp.in.handle = handle;
2018 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
2019 torture_assert_ntstatus_ok(tctx, status,
2020 "dcerpc_spoolss_StartPagePrinter failed");
2021 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
2023 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
2025 w.in.handle = handle;
2026 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
2027 w.out.num_written = &num_written;
2029 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
2030 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
2031 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
2033 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
2035 ep.in.handle = handle;
2037 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
2038 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
2039 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
2042 torture_comment(tctx, "Testing EndDocPrinter\n");
2044 e.in.handle = handle;
2046 status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
2047 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
2048 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
2050 ret &= test_AddJob(tctx, p, handle);
2051 ret &= test_EnumJobs(tctx, p, handle);
2053 ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
2058 static bool test_PausePrinter(struct torture_context *tctx,
2059 struct dcerpc_pipe *p,
2060 struct policy_handle *handle)
2063 struct spoolss_SetPrinter r;
2064 struct spoolss_SetPrinterInfoCtr info_ctr;
2065 struct spoolss_DevmodeContainer devmode_ctr;
2066 struct sec_desc_buf secdesc_ctr;
2069 info_ctr.info.info0 = NULL;
2071 ZERO_STRUCT(devmode_ctr);
2072 ZERO_STRUCT(secdesc_ctr);
2074 r.in.handle = handle;
2075 r.in.info_ctr = &info_ctr;
2076 r.in.devmode_ctr = &devmode_ctr;
2077 r.in.secdesc_ctr = &secdesc_ctr;
2078 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
2080 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
2082 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2084 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2086 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2091 static bool test_ResumePrinter(struct torture_context *tctx,
2092 struct dcerpc_pipe *p,
2093 struct policy_handle *handle)
2096 struct spoolss_SetPrinter r;
2097 struct spoolss_SetPrinterInfoCtr info_ctr;
2098 struct spoolss_DevmodeContainer devmode_ctr;
2099 struct sec_desc_buf secdesc_ctr;
2102 info_ctr.info.info0 = NULL;
2104 ZERO_STRUCT(devmode_ctr);
2105 ZERO_STRUCT(secdesc_ctr);
2107 r.in.handle = handle;
2108 r.in.info_ctr = &info_ctr;
2109 r.in.devmode_ctr = &devmode_ctr;
2110 r.in.secdesc_ctr = &secdesc_ctr;
2111 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
2113 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2115 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2117 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2119 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2124 static bool test_GetPrinterData(struct torture_context *tctx,
2125 struct dcerpc_pipe *p,
2126 struct policy_handle *handle,
2127 const char *value_name,
2128 enum winreg_Type *type_p,
2129 union spoolss_PrinterData *data_p)
2132 struct spoolss_GetPrinterData r;
2134 enum winreg_Type type;
2135 union spoolss_PrinterData data;
2137 r.in.handle = handle;
2138 r.in.value_name = value_name;
2140 r.out.needed = &needed;
2144 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
2146 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2147 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2149 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2150 r.in.offered = needed;
2152 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2153 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2156 torture_assert_werr_ok(tctx, r.out.result,
2157 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
2159 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2172 static bool test_GetPrinterDataEx(struct torture_context *tctx,
2173 struct dcerpc_pipe *p,
2174 struct policy_handle *handle,
2175 const char *key_name,
2176 const char *value_name,
2177 enum winreg_Type *type_p,
2178 union spoolss_PrinterData *data_p)
2181 struct spoolss_GetPrinterDataEx r;
2182 enum winreg_Type type;
2184 union spoolss_PrinterData data;
2186 r.in.handle = handle;
2187 r.in.key_name = key_name;
2188 r.in.value_name = value_name;
2191 r.out.needed = &needed;
2194 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
2195 r.in.key_name, r.in.value_name);
2197 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2198 if (!NT_STATUS_IS_OK(status)) {
2199 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
2200 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
2201 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
2203 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2206 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2207 r.in.offered = needed;
2208 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2209 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2212 torture_assert_werr_ok(tctx, r.out.result,
2213 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
2215 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2228 static bool test_GetPrinterData_list(struct torture_context *tctx,
2229 struct dcerpc_pipe *p,
2230 struct policy_handle *handle)
2232 const char *list[] = {
2236 /* "NetPopup", not on w2k8 */
2237 /* "NetPopupToComputer", not on w2k8 */
2240 "DefaultSpoolDirectory",
2244 /* "OSVersionEx", not on s3 */
2249 for (i=0; i < ARRAY_SIZE(list); i++) {
2250 enum winreg_Type type, type_ex;
2251 union spoolss_PrinterData data, data_ex;
2253 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, list[i], &type, &data),
2254 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
2255 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "random_string", list[i], &type_ex, &data_ex),
2256 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
2257 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
2260 torture_assert_str_equal(tctx, data.string, data_ex.string, "REG_SZ mismatch");
2263 torture_assert_int_equal(tctx, data.value, data_ex.value, "REG_DWORD mismatch");
2266 torture_assert_data_blob_equal(tctx, data.binary, data_ex.binary, "REG_BINARY mismatch");
2276 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
2277 struct policy_handle *handle)
2280 struct spoolss_EnumPrinterData r;
2283 r.in.handle = handle;
2284 r.in.enum_index = 0;
2287 uint32_t value_size = 0;
2288 uint32_t data_size = 0;
2289 enum winreg_Type type = 0;
2291 r.in.value_offered = value_size;
2292 r.out.value_needed = &value_size;
2293 r.in.data_offered = data_size;
2294 r.out.data_needed = &data_size;
2297 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
2299 torture_comment(tctx, "Testing EnumPrinterData\n");
2301 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2303 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2304 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
2307 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData");
2309 r.in.value_offered = value_size;
2310 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
2311 r.in.data_offered = data_size;
2312 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
2314 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2316 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2317 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
2321 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData failed");
2323 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, r.out.value_name, NULL, NULL),
2324 talloc_asprintf(tctx, "failed to call GetPrinterData for %s\n", r.out.value_name));
2326 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", r.out.value_name, NULL, NULL),
2327 talloc_asprintf(tctx, "failed to call GetPrinterDataEx on PrinterDriverData for %s\n", r.out.value_name));
2331 } while (W_ERROR_IS_OK(r.out.result));
2336 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
2337 struct dcerpc_pipe *p,
2338 struct policy_handle *handle,
2339 const char *key_name)
2341 struct spoolss_EnumPrinterDataEx r;
2342 struct spoolss_PrinterEnumValues *info;
2346 r.in.handle = handle;
2347 r.in.key_name = key_name;
2349 r.out.needed = &needed;
2350 r.out.count = &count;
2353 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
2355 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
2356 "EnumPrinterDataEx failed");
2357 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2358 r.in.offered = needed;
2359 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
2360 "EnumPrinterDataEx failed");
2363 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
2365 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2371 static bool test_DeletePrinterData(struct torture_context *tctx,
2372 struct dcerpc_pipe *p,
2373 struct policy_handle *handle,
2374 const char *value_name)
2377 struct spoolss_DeletePrinterData r;
2379 r.in.handle = handle;
2380 r.in.value_name = value_name;
2382 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
2385 status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
2387 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
2388 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
2393 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
2394 struct dcerpc_pipe *p,
2395 struct policy_handle *handle,
2396 const char *key_name,
2397 const char *value_name)
2399 struct spoolss_DeletePrinterDataEx r;
2401 r.in.handle = handle;
2402 r.in.key_name = key_name;
2403 r.in.value_name = value_name;
2405 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
2406 r.in.key_name, r.in.value_name);
2408 torture_assert_ntstatus_ok(tctx,
2409 dcerpc_spoolss_DeletePrinterDataEx(p, tctx, &r),
2410 "DeletePrinterDataEx failed");
2411 torture_assert_werr_ok(tctx, r.out.result,
2412 "DeletePrinterDataEx failed");
2417 static bool test_DeletePrinterKey(struct torture_context *tctx,
2418 struct dcerpc_pipe *p,
2419 struct policy_handle *handle,
2420 const char *key_name)
2422 struct spoolss_DeletePrinterKey r;
2424 r.in.handle = handle;
2425 r.in.key_name = key_name;
2427 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
2429 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
2430 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
2434 torture_assert_ntstatus_ok(tctx,
2435 dcerpc_spoolss_DeletePrinterKey(p, tctx, &r),
2436 "DeletePrinterKey failed");
2437 torture_assert_werr_ok(tctx, r.out.result,
2438 "DeletePrinterKey failed");
2443 static bool test_SetPrinterData(struct torture_context *tctx,
2444 struct dcerpc_pipe *p,
2445 struct policy_handle *handle)
2448 struct spoolss_SetPrinterData r;
2449 const char *values[] = {
2453 /* FIXME: not working with s3 atm. */
2459 /* FIXME: not working with s3 atm. */
2466 for (i=0; i < ARRAY_SIZE(values); i++) {
2468 enum winreg_Type type;
2469 union spoolss_PrinterData data;
2471 r.in.handle = handle;
2472 r.in.value_name = values[i];
2474 r.in.data.string = "dog";
2476 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
2479 status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
2481 torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
2482 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterData failed");
2484 if (!test_GetPrinterData(tctx, p, handle, r.in.value_name, &type, &data)) {
2488 torture_assert_int_equal(tctx, r.in.type, type, "type mismatch");
2489 torture_assert_str_equal(tctx, r.in.data.string, data.string, "data mismatch");
2491 if (!test_DeletePrinterData(tctx, p, handle, r.in.value_name)) {
2499 static bool test_EnumPrinterKey(struct torture_context *tctx,
2500 struct dcerpc_pipe *p,
2501 struct policy_handle *handle,
2502 const char *key_name,
2503 const char ***array);
2505 static bool test_SetPrinterDataEx(struct torture_context *tctx,
2506 struct dcerpc_pipe *p,
2507 struct policy_handle *handle)
2510 struct spoolss_SetPrinterDataEx r;
2511 const char *value_name = "dog";
2512 const char *keys[] = {
2516 /* FIXME: not working with s3 atm. */
2517 "torturedataex_with_subkey\\subkey",
2518 "torturedataex_with_subkey\\subkey:0",
2519 "torturedataex_with_subkey\\subkey:1",
2520 "torturedataex_with_subkey\\subkey\\subsubkey",
2521 "torturedataex_with_subkey\\subkey\\subsubkey:0",
2522 "torturedataex_with_subkey\\subkey\\subsubkey:1",
2526 /* FIXME: not working with s3 atm. */
2534 DATA_BLOB blob = data_blob_string_const("catfoobar");
2537 for (i=0; i < ARRAY_SIZE(keys); i++) {
2541 enum winreg_Type type;
2542 const char **subkeys;
2543 union spoolss_PrinterData data;
2545 r.in.handle = handle;
2546 r.in.key_name = keys[i];
2547 r.in.value_name = value_name;
2548 r.in.type = REG_BINARY;
2549 r.in.data.binary = blob;
2551 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s)\n", r.in.key_name, value_name);
2553 status = dcerpc_spoolss_SetPrinterDataEx(p, tctx, &r);
2555 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
2556 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
2558 key = talloc_strdup(tctx, r.in.key_name);
2560 if (!test_GetPrinterDataEx(tctx, p, handle, r.in.key_name, value_name, &type, &data)) {
2564 torture_assert_int_equal(tctx, r.in.type, type, "type mismatch");
2565 torture_assert_data_blob_equal(tctx, blob, data.binary, "data mismatch");
2567 if (!test_EnumPrinterDataEx(tctx, p, handle, r.in.key_name)) {
2571 if (!test_DeletePrinterDataEx(tctx, p, handle, r.in.key_name, value_name)) {
2575 c = strchr(key, '\\');
2579 /* we have subkeys */
2583 if (!test_EnumPrinterKey(tctx, p, handle, key, &subkeys)) {
2587 for (i=0; subkeys && subkeys[i]; i++) {
2589 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[i]);
2591 if (!test_DeletePrinterKey(tctx, p, handle, current_key)) {
2596 if (!test_DeletePrinterKey(tctx, p, handle, key)) {
2601 if (!test_DeletePrinterKey(tctx, p, handle, key)) {
2611 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
2612 struct dcerpc_pipe *p,
2613 struct policy_handle *handle)
2616 struct dcerpc_binding *b;
2617 struct dcerpc_pipe *p2;
2618 struct spoolss_ClosePrinter cp;
2620 /* only makes sense on SMB */
2621 if (p->conn->transport.transport != NCACN_NP) {
2625 torture_comment(tctx, "testing close on secondary pipe\n");
2627 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
2628 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
2630 status = dcerpc_secondary_connection(p, &p2, b);
2631 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
2633 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
2634 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
2636 cp.in.handle = handle;
2637 cp.out.handle = handle;
2639 status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
2640 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
2641 "ERROR: Allowed close on secondary connection");
2643 torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
2644 "Unexpected fault code");
2651 static bool test_OpenPrinter_badname(struct torture_context *tctx,
2652 struct dcerpc_pipe *p, const char *name)
2655 struct spoolss_OpenPrinter op;
2656 struct spoolss_OpenPrinterEx opEx;
2657 struct policy_handle handle;
2660 op.in.printername = name;
2661 op.in.datatype = NULL;
2662 op.in.devmode_ctr.devmode= NULL;
2663 op.in.access_mask = 0;
2664 op.out.handle = &handle;
2666 torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
2668 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
2669 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2670 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
2671 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
2672 name, win_errstr(op.out.result));
2675 if (W_ERROR_IS_OK(op.out.result)) {
2676 ret &=test_ClosePrinter(tctx, p, &handle);
2679 opEx.in.printername = name;
2680 opEx.in.datatype = NULL;
2681 opEx.in.devmode_ctr.devmode = NULL;
2682 opEx.in.access_mask = 0;
2684 opEx.in.userlevel.level1 = NULL;
2685 opEx.out.handle = &handle;
2687 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
2689 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
2690 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2691 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
2692 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
2693 name, win_errstr(opEx.out.result));
2696 if (W_ERROR_IS_OK(opEx.out.result)) {
2697 ret &=test_ClosePrinter(tctx, p, &handle);
2703 static bool test_OpenPrinter(struct torture_context *tctx,
2704 struct dcerpc_pipe *p,
2708 struct spoolss_OpenPrinter r;
2709 struct policy_handle handle;
2712 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
2713 r.in.datatype = NULL;
2714 r.in.devmode_ctr.devmode= NULL;
2715 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2716 r.out.handle = &handle;
2718 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
2720 status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
2722 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2724 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
2726 if (!test_GetPrinter(tctx, p, &handle)) {
2730 if (!torture_setting_bool(tctx, "samba3", false)) {
2731 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2736 if (!test_ClosePrinter(tctx, p, &handle)) {
2743 static bool call_OpenPrinterEx(struct torture_context *tctx,
2744 struct dcerpc_pipe *p,
2745 const char *name, struct policy_handle *handle)
2747 struct spoolss_OpenPrinterEx r;
2748 struct spoolss_UserLevel1 userlevel1;
2751 if (name && name[0]) {
2752 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
2753 dcerpc_server_name(p), name);
2755 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
2756 dcerpc_server_name(p));
2759 r.in.datatype = NULL;
2760 r.in.devmode_ctr.devmode= NULL;
2761 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2763 r.in.userlevel.level1 = &userlevel1;
2764 r.out.handle = handle;
2766 userlevel1.size = 1234;
2767 userlevel1.client = "hello";
2768 userlevel1.user = "spottyfoot!";
2769 userlevel1.build = 1;
2770 userlevel1.major = 2;
2771 userlevel1.minor = 3;
2772 userlevel1.processor = 4;
2774 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
2776 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
2778 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2780 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
2785 static bool test_OpenPrinterEx(struct torture_context *tctx,
2786 struct dcerpc_pipe *p,
2789 struct policy_handle handle;
2792 if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
2796 if (!test_GetPrinter(tctx, p, &handle)) {
2800 if (!test_EnumForms(tctx, p, &handle, false)) {
2804 if (!test_AddForm(tctx, p, &handle, false)) {
2808 if (!test_EnumPrinterData(tctx, p, &handle)) {
2812 if (!test_EnumPrinterDataEx(tctx, p, &handle, "PrinterDriverData")) {
2816 if (!test_printer_keys(tctx, p, &handle)) {
2820 if (!test_PausePrinter(tctx, p, &handle)) {
2824 if (!test_DoPrintTest(tctx, p, &handle)) {
2828 if (!test_ResumePrinter(tctx, p, &handle)) {
2832 if (!test_SetPrinterData(tctx, p, &handle)) {
2836 if (!test_SetPrinterDataEx(tctx, p, &handle)) {
2840 if (!torture_setting_bool(tctx, "samba3", false)) {
2841 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2846 if (!test_ClosePrinter(tctx, p, &handle)) {
2853 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
2855 struct spoolss_EnumPrinters r;
2857 uint16_t levels[] = {1, 2, 4, 5};
2861 for (i=0;i<ARRAY_SIZE(levels);i++) {
2862 union spoolss_PrinterInfo *info;
2867 r.in.flags = PRINTER_ENUM_LOCAL;
2869 r.in.level = levels[i];
2872 r.out.needed = &needed;
2873 r.out.count = &count;
2876 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
2878 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2879 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2881 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2882 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2883 data_blob_clear(&blob);
2884 r.in.buffer = &blob;
2885 r.in.offered = needed;
2886 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2889 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2891 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
2893 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2896 torture_comment(tctx, "No printers returned\n");
2900 for (j=0;j<count;j++) {
2901 if (r.in.level == 1) {
2902 char *unc = talloc_strdup(tctx, info[j].info1.name);
2905 if (unc[0] == '\\' && unc[1] == '\\') {
2908 slash = strchr(unc, '\\');
2913 if (!test_OpenPrinter(tctx, p, name)) {
2916 if (!test_OpenPrinterEx(tctx, p, name)) {
2926 static bool test_GetPrinterDriver(struct torture_context *tctx,
2927 struct dcerpc_pipe *p,
2928 struct policy_handle *handle,
2929 const char *driver_name)
2931 struct spoolss_GetPrinterDriver r;
2934 r.in.handle = handle;
2935 r.in.architecture = "W32X86";
2939 r.out.needed = &needed;
2941 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
2943 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
2944 "failed to call GetPrinterDriver");
2945 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2946 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2947 data_blob_clear(&blob);
2948 r.in.buffer = &blob;
2949 r.in.offered = needed;
2950 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
2951 "failed to call GetPrinterDriver");
2954 torture_assert_werr_ok(tctx, r.out.result,
2955 "failed to call GetPrinterDriver");
2957 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2962 static bool test_GetPrinterDriver2(struct torture_context *tctx,
2963 struct dcerpc_pipe *p,
2964 struct policy_handle *handle,
2965 const char *driver_name)
2967 struct spoolss_GetPrinterDriver2 r;
2969 uint32_t server_major_version;
2970 uint32_t server_minor_version;
2972 r.in.handle = handle;
2973 r.in.architecture = "W32X86";
2977 r.in.client_major_version = 0;
2978 r.in.client_minor_version = 0;
2979 r.out.needed = &needed;
2980 r.out.server_major_version = &server_major_version;
2981 r.out.server_minor_version = &server_minor_version;
2983 torture_comment(tctx, "Testing GetPrinterDriver2 level %d\n", r.in.level);
2985 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
2986 "failed to call GetPrinterDriver2");
2987 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2988 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2989 data_blob_clear(&blob);
2990 r.in.buffer = &blob;
2991 r.in.offered = needed;
2992 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
2993 "failed to call GetPrinterDriver2");
2996 torture_assert_werr_ok(tctx, r.out.result,
2997 "failed to call GetPrinterDriver2");
2999 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3004 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
3005 struct dcerpc_pipe *p)
3007 struct spoolss_EnumPrinterDrivers r;
3009 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
3012 for (i=0;i<ARRAY_SIZE(levels);i++) {
3016 union spoolss_DriverInfo *info;
3018 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
3019 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
3020 r.in.level = levels[i];
3023 r.out.needed = &needed;
3024 r.out.count = &count;
3027 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
3029 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
3031 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
3033 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3034 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
3035 data_blob_clear(&blob);
3036 r.in.buffer = &blob;
3037 r.in.offered = needed;
3038 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
3041 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
3043 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
3046 torture_comment(tctx, "No printer drivers returned\n");
3050 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
3056 static bool test_DeletePrinter(struct torture_context *tctx,
3057 struct dcerpc_pipe *p,
3058 struct policy_handle *handle)
3060 struct spoolss_DeletePrinter r;
3062 torture_comment(tctx, "Testing DeletePrinter\n");
3064 r.in.handle = handle;
3066 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter(p, tctx, &r),
3067 "failed to delete printer");
3068 torture_assert_werr_ok(tctx, r.out.result,
3069 "failed to delete printer");
3074 static bool test_EnumPrinters_findname(struct torture_context *tctx,
3075 struct dcerpc_pipe *p