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_spoolss_c.h"
29 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
30 #define TORTURE_PRINTER "torture_printer"
31 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
32 #define TORTURE_PRINTER_EX "torture_printer_ex"
34 struct test_spoolss_context {
35 /* print server handle */
36 struct policy_handle server_handle;
39 uint32_t port_count[3];
40 union spoolss_PortInfo *ports[3];
42 /* for EnumPrinterDrivers */
43 uint32_t driver_count[7];
44 union spoolss_DriverInfo *drivers[7];
46 /* for EnumMonitors */
47 uint32_t monitor_count[3];
48 union spoolss_MonitorInfo *monitors[3];
50 /* for EnumPrintProcessors */
51 uint32_t print_processor_count[2];
52 union spoolss_PrintProcessorInfo *print_processors[2];
54 /* for EnumPrinters */
55 uint32_t printer_count[6];
56 union spoolss_PrinterInfo *printers[6];
59 #define COMPARE_STRING(tctx, c,r,e) \
60 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
62 /* not every compiler supports __typeof__() */
64 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
65 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
66 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
68 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
69 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
73 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
76 #define COMPARE_UINT32(tctx, c, r, e) do {\
77 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
78 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
81 #define COMPARE_STRING_ARRAY(tctx, c,r,e)
83 static bool test_OpenPrinter_server(struct torture_context *tctx,
84 struct dcerpc_pipe *p,
85 struct policy_handle *server_handle)
88 struct spoolss_OpenPrinter op;
90 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
91 op.in.datatype = NULL;
92 op.in.devmode_ctr.devmode= NULL;
93 op.in.access_mask = 0;
94 op.out.handle = server_handle;
96 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
98 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
99 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
100 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
105 static bool test_EnumPorts(struct torture_context *tctx,
106 struct dcerpc_pipe *p,
107 struct test_spoolss_context *ctx)
110 struct spoolss_EnumPorts r;
111 uint16_t levels[] = { 1, 2 };
114 for (i=0;i<ARRAY_SIZE(levels);i++) {
115 int level = levels[i];
119 union spoolss_PortInfo *info;
121 r.in.servername = "";
125 r.out.needed = &needed;
126 r.out.count = &count;
129 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
131 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
132 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
133 if (W_ERROR_IS_OK(r.out.result)) {
134 /* TODO: do some more checks here */
137 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
138 "EnumPorts unexpected return code");
140 blob = data_blob_talloc(ctx, NULL, needed);
141 data_blob_clear(&blob);
143 r.in.offered = needed;
145 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
146 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
148 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
150 torture_assert(tctx, info, "EnumPorts returned no info");
152 ctx->port_count[level] = count;
153 ctx->ports[level] = info;
156 for (i=1;i<ARRAY_SIZE(levels);i++) {
157 int level = levels[i];
158 int old_level = levels[i-1];
159 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
160 "EnumPorts invalid value");
162 /* if the array sizes are not the same we would maybe segfault in the following code */
164 for (i=0;i<ARRAY_SIZE(levels);i++) {
165 int level = levels[i];
166 for (j=0;j<ctx->port_count[level];j++) {
167 union spoolss_PortInfo *cur = &ctx->ports[level][j];
168 union spoolss_PortInfo *ref = &ctx->ports[2][j];
171 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
174 /* level 2 is our reference, and it makes no sense to compare it to itself */
183 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
184 struct dcerpc_pipe *p,
185 struct test_spoolss_context *ctx)
188 struct spoolss_GetPrintProcessorDirectory r;
203 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
206 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
212 for (i=0;i<ARRAY_SIZE(levels);i++) {
213 int level = levels[i].level;
216 r.in.server = levels[i].server;
217 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
221 r.out.needed = &needed;
223 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
225 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
226 torture_assert_ntstatus_ok(tctx, status,
227 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
228 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
229 "GetPrintProcessorDirectory unexpected return code");
231 blob = data_blob_talloc(ctx, NULL, needed);
232 data_blob_clear(&blob);
234 r.in.offered = needed;
236 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
237 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
239 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
246 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
247 struct dcerpc_pipe *p,
248 struct test_spoolss_context *ctx)
251 struct spoolss_GetPrinterDriverDirectory r;
266 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
269 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
275 for (i=0;i<ARRAY_SIZE(levels);i++) {
276 int level = levels[i].level;
279 r.in.server = levels[i].server;
280 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
284 r.out.needed = &needed;
286 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
288 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
289 torture_assert_ntstatus_ok(tctx, status,
290 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
291 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
292 "GetPrinterDriverDirectory unexpected return code");
294 blob = data_blob_talloc(ctx, NULL, needed);
295 data_blob_clear(&blob);
297 r.in.offered = needed;
299 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
300 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
302 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
308 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
309 struct dcerpc_pipe *p,
310 struct test_spoolss_context *ctx)
313 struct spoolss_EnumPrinterDrivers r;
314 uint16_t levels[] = { 1, 2, 3, 4, 5, 6 };
316 const char *architectures[] = {
317 SPOOLSS_ARCHITECTURE_NT_X86,
318 SPOOLSS_ARCHITECTURE_ALL
321 for (i=0;i<ARRAY_SIZE(levels);i++) {
322 for (a=0;a<ARRAY_SIZE(architectures);a++) {
323 int level = levels[i];
327 union spoolss_DriverInfo *info;
329 /* FIXME: gd, come back and fix "" as server, and handle
330 * priority of returned error codes in torture test and samba 3
333 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
334 r.in.environment = architectures[a];
338 r.out.needed = &needed;
339 r.out.count = &count;
342 torture_comment(tctx, "Testing EnumPrinterDrivers level %u (%s)\n", r.in.level, r.in.environment);
344 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
345 torture_assert_ntstatus_ok(tctx, status,
346 "dcerpc_spoolss_EnumPrinterDrivers failed");
347 if (W_ERROR_IS_OK(r.out.result)) {
348 /* TODO: do some more checks here */
351 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
352 blob = data_blob_talloc(ctx, NULL, needed);
353 data_blob_clear(&blob);
355 r.in.offered = needed;
357 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
358 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
361 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
363 /* don't do cross-architecture comparison */
364 if (strequal(r.in.environment, SPOOLSS_ARCHITECTURE_ALL)) {
368 ctx->driver_count[level] = count;
369 ctx->drivers[level] = info;
373 for (i=1;i<ARRAY_SIZE(levels);i++) {
374 int level = levels[i];
375 int old_level = levels[i-1];
377 /* don't do cross-architecture comparison */
378 if (strequal(r.in.environment, SPOOLSS_ARCHITECTURE_ALL)) {
382 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
383 "EnumPrinterDrivers invalid value");
386 for (i=0;i<ARRAY_SIZE(levels);i++) {
387 int level = levels[i];
389 /* don't do cross-architecture comparison */
390 if (strequal(r.in.environment, SPOOLSS_ARCHITECTURE_ALL)) {
394 for (j=0;j<ctx->driver_count[level];j++) {
395 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
396 union spoolss_DriverInfo *ref = &ctx->drivers[6][j];
399 COMPARE_STRING(tctx, cur->info1, ref->info6, driver_name);
402 COMPARE_UINT32(tctx, cur->info2, ref->info6, version);
403 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_name);
404 COMPARE_STRING(tctx, cur->info2, ref->info6, architecture);
405 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_path);
406 COMPARE_STRING(tctx, cur->info2, ref->info6, data_file);
407 COMPARE_STRING(tctx, cur->info2, ref->info6, config_file);
410 COMPARE_UINT32(tctx, cur->info3, ref->info6, version);
411 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_name);
412 COMPARE_STRING(tctx, cur->info3, ref->info6, architecture);
413 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_path);
414 COMPARE_STRING(tctx, cur->info3, ref->info6, data_file);
415 COMPARE_STRING(tctx, cur->info3, ref->info6, config_file);
416 COMPARE_STRING(tctx, cur->info3, ref->info6, help_file);
417 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info6, dependent_files);
418 COMPARE_STRING(tctx, cur->info3, ref->info6, monitor_name);
419 COMPARE_STRING(tctx, cur->info3, ref->info6, default_datatype);
422 COMPARE_UINT32(tctx, cur->info4, ref->info6, version);
423 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_name);
424 COMPARE_STRING(tctx, cur->info4, ref->info6, architecture);
425 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_path);
426 COMPARE_STRING(tctx, cur->info4, ref->info6, data_file);
427 COMPARE_STRING(tctx, cur->info4, ref->info6, config_file);
428 COMPARE_STRING(tctx, cur->info4, ref->info6, help_file);
429 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, dependent_files);
430 COMPARE_STRING(tctx, cur->info4, ref->info6, monitor_name);
431 COMPARE_STRING(tctx, cur->info4, ref->info6, default_datatype);
432 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, previous_names);
435 COMPARE_UINT32(tctx, cur->info5, ref->info6, version);
436 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_name);
437 COMPARE_STRING(tctx, cur->info5, ref->info6, architecture);
438 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_path);
439 COMPARE_STRING(tctx, cur->info5, ref->info6, data_file);
440 COMPARE_STRING(tctx, cur->info5, ref->info6, config_file);
441 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_attributes);*/
442 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, config_version);*/
443 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_version); */
446 /* level 6 is our reference, and it makes no sense to compare it to itself */
455 static bool test_EnumMonitors(struct torture_context *tctx,
456 struct dcerpc_pipe *p,
457 struct test_spoolss_context *ctx)
460 struct spoolss_EnumMonitors r;
461 uint16_t levels[] = { 1, 2 };
464 for (i=0;i<ARRAY_SIZE(levels);i++) {
465 int level = levels[i];
469 union spoolss_MonitorInfo *info;
471 r.in.servername = "";
475 r.out.needed = &needed;
476 r.out.count = &count;
479 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
481 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
482 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
483 if (W_ERROR_IS_OK(r.out.result)) {
484 /* TODO: do some more checks here */
487 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
488 "EnumMonitors failed");
490 blob = data_blob_talloc(ctx, NULL, needed);
491 data_blob_clear(&blob);
493 r.in.offered = needed;
495 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
496 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
498 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
500 ctx->monitor_count[level] = count;
501 ctx->monitors[level] = info;
504 for (i=1;i<ARRAY_SIZE(levels);i++) {
505 int level = levels[i];
506 int old_level = levels[i-1];
507 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
508 "EnumMonitors invalid value");
511 for (i=0;i<ARRAY_SIZE(levels);i++) {
512 int level = levels[i];
513 for (j=0;j<ctx->monitor_count[level];j++) {
514 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
515 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
518 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
521 /* level 2 is our reference, and it makes no sense to compare it to itself */
530 static bool test_EnumPrintProcessors(struct torture_context *tctx,
531 struct dcerpc_pipe *p,
532 struct test_spoolss_context *ctx)
535 struct spoolss_EnumPrintProcessors r;
536 uint16_t levels[] = { 1 };
539 for (i=0;i<ARRAY_SIZE(levels);i++) {
540 int level = levels[i];
544 union spoolss_PrintProcessorInfo *info;
546 r.in.servername = "";
547 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
551 r.out.needed = &needed;
552 r.out.count = &count;
555 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
557 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
558 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
559 if (W_ERROR_IS_OK(r.out.result)) {
560 /* TODO: do some more checks here */
563 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
564 "EnumPrintProcessors unexpected return code");
566 blob = data_blob_talloc(ctx, NULL, needed);
567 data_blob_clear(&blob);
569 r.in.offered = needed;
571 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
572 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
574 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
576 ctx->print_processor_count[level] = count;
577 ctx->print_processors[level] = info;
580 for (i=1;i<ARRAY_SIZE(levels);i++) {
581 int level = levels[i];
582 int old_level = levels[i-1];
583 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
584 "EnumPrintProcessors failed");
587 for (i=0;i<ARRAY_SIZE(levels);i++) {
588 int level = levels[i];
589 for (j=0;j<ctx->print_processor_count[level];j++) {
591 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
592 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
596 /* level 1 is our reference, and it makes no sense to compare it to itself */
605 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
606 struct dcerpc_pipe *p,
607 struct test_spoolss_context *ctx)
610 struct spoolss_EnumPrintProcDataTypes r;
611 uint16_t levels[] = { 1 };
614 for (i=0;i<ARRAY_SIZE(levels);i++) {
615 int level = levels[i];
619 union spoolss_PrintProcDataTypesInfo *info;
621 r.in.servername = "";
622 r.in.print_processor_name = "winprint";
626 r.out.needed = &needed;
627 r.out.count = &count;
630 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
632 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
633 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
634 if (W_ERROR_IS_OK(r.out.result)) {
635 /* TODO: do some more checks here */
638 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
639 "EnumPrintProcDataTypes unexpected return code");
641 blob = data_blob_talloc(ctx, NULL, needed);
642 data_blob_clear(&blob);
644 r.in.offered = needed;
646 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
647 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
649 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
656 static bool test_EnumPrinters(struct torture_context *tctx,
657 struct dcerpc_pipe *p,
658 struct test_spoolss_context *ctx)
660 struct spoolss_EnumPrinters r;
662 uint16_t levels[] = { 0, 1, 2, 4, 5 };
665 for (i=0;i<ARRAY_SIZE(levels);i++) {
666 int level = levels[i];
670 union spoolss_PrinterInfo *info;
672 r.in.flags = PRINTER_ENUM_LOCAL;
677 r.out.needed = &needed;
678 r.out.count = &count;
681 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
683 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
684 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
685 if (W_ERROR_IS_OK(r.out.result)) {
686 /* TODO: do some more checks here */
689 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
690 "EnumPrinters unexpected return code");
692 blob = data_blob_talloc(ctx, NULL, needed);
693 data_blob_clear(&blob);
695 r.in.offered = needed;
697 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
698 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
700 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
702 ctx->printer_count[level] = count;
703 ctx->printers[level] = info;
706 for (i=1;i<ARRAY_SIZE(levels);i++) {
707 int level = levels[i];
708 int old_level = levels[i-1];
709 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
710 "EnumPrinters invalid value");
713 for (i=0;i<ARRAY_SIZE(levels);i++) {
714 int level = levels[i];
715 for (j=0;j<ctx->printer_count[level];j++) {
716 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
717 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
720 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
721 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
722 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
723 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
724 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
725 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
726 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
727 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
728 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
729 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
730 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
731 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
732 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
733 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
734 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
735 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
736 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
737 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
738 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
739 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
740 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
741 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
742 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
743 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
744 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
745 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
746 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
747 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
748 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
751 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
752 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
753 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
754 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
757 /* level 2 is our reference, and it makes no sense to compare it to itself */
760 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
761 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
762 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
765 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
766 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
767 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
768 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
769 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
776 * - verify that the port of a printer was in the list returned by EnumPorts
782 static bool test_GetPrinter(struct torture_context *tctx,
783 struct dcerpc_pipe *p,
784 struct policy_handle *handle)
787 struct spoolss_GetPrinter r;
788 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
792 for (i=0;i<ARRAY_SIZE(levels);i++) {
793 r.in.handle = handle;
794 r.in.level = levels[i];
797 r.out.needed = &needed;
799 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
801 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
802 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
804 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
805 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
806 data_blob_clear(&blob);
808 r.in.offered = needed;
809 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
812 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
814 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
820 static bool test_SetPrinter_errors(struct torture_context *tctx,
821 struct dcerpc_pipe *p,
822 struct policy_handle *handle)
824 struct spoolss_SetPrinter r;
825 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
828 struct spoolss_SetPrinterInfoCtr info_ctr;
829 struct spoolss_DevmodeContainer devmode_ctr;
830 struct sec_desc_buf secdesc_ctr;
833 info_ctr.info.info0 = NULL;
835 ZERO_STRUCT(devmode_ctr);
836 ZERO_STRUCT(secdesc_ctr);
838 r.in.handle = handle;
839 r.in.info_ctr = &info_ctr;
840 r.in.devmode_ctr = &devmode_ctr;
841 r.in.secdesc_ctr = &secdesc_ctr;
844 torture_comment(tctx, "Testing SetPrinter all zero\n");
846 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
847 "failed to call SetPrinter");
848 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
849 "failed to call SetPrinter");
852 for (i=0; i < ARRAY_SIZE(levels); i++) {
854 struct spoolss_SetPrinterInfo0 info0;
855 struct spoolss_SetPrinterInfo1 info1;
856 struct spoolss_SetPrinterInfo2 info2;
857 struct spoolss_SetPrinterInfo3 info3;
858 struct spoolss_SetPrinterInfo4 info4;
859 struct spoolss_SetPrinterInfo5 info5;
860 struct spoolss_SetPrinterInfo6 info6;
861 struct spoolss_SetPrinterInfo7 info7;
862 struct spoolss_DeviceModeInfo info8;
863 struct spoolss_DeviceModeInfo info9;
866 info_ctr.level = levels[i];
870 info_ctr.info.info0 = &info0;
874 info_ctr.info.info1 = &info1;
878 info_ctr.info.info2 = &info2;
882 info_ctr.info.info3 = &info3;
886 info_ctr.info.info4 = &info4;
890 info_ctr.info.info5 = &info5;
894 info_ctr.info.info6 = &info6;
898 info_ctr.info.info7 = &info7;
902 info_ctr.info.info8 = &info8;
906 info_ctr.info.info9 = &info9;
910 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
911 info_ctr.level, r.in.command);
913 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
914 "failed to call SetPrinter");
916 switch (r.in.command) {
917 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
918 /* is ignored for all levels other then 0 */
919 if (info_ctr.level > 0) {
923 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
924 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
925 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
926 if (info_ctr.level > 0) {
927 /* is invalid for all levels other then 0 */
928 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
929 "unexpected error code returned");
932 torture_assert_werr_ok(tctx, r.out.result,
933 "failed to call SetPrinter with non 0 command");
938 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
939 /* FIXME: gd needs further investigation */
941 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
942 "unexpected error code returned");
946 switch (info_ctr.level) {
948 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
949 "unexpected error code returned");
952 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
953 "unexpected error code returned");
959 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
960 "unexpected error code returned");
963 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
964 "unexpected error code returned");
967 torture_assert_werr_ok(tctx, r.out.result,
968 "failed to call SetPrinter");
973 if (r.in.command < 5) {
981 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
983 if ((r->level == 2) && (r->info.info2)) {
984 r->info.info2->secdesc = NULL;
985 r->info.info2->devmode = NULL;
989 static bool test_PrinterInfo(struct torture_context *tctx,
990 struct dcerpc_pipe *p,
991 struct policy_handle *handle)
994 struct spoolss_SetPrinter s;
995 struct spoolss_GetPrinter q;
996 struct spoolss_GetPrinter q0;
997 struct spoolss_SetPrinterInfoCtr info_ctr;
998 union spoolss_PrinterInfo info;
999 struct spoolss_DevmodeContainer devmode_ctr;
1000 struct sec_desc_buf secdesc_ctr;
1005 uint32_t status_list[] = {
1006 /* these do not stick
1007 PRINTER_STATUS_PAUSED,
1008 PRINTER_STATUS_ERROR,
1009 PRINTER_STATUS_PENDING_DELETION, */
1010 PRINTER_STATUS_PAPER_JAM,
1011 PRINTER_STATUS_PAPER_OUT,
1012 PRINTER_STATUS_MANUAL_FEED,
1013 PRINTER_STATUS_PAPER_PROBLEM,
1014 PRINTER_STATUS_OFFLINE,
1015 PRINTER_STATUS_IO_ACTIVE,
1016 PRINTER_STATUS_BUSY,
1017 PRINTER_STATUS_PRINTING,
1018 PRINTER_STATUS_OUTPUT_BIN_FULL,
1019 PRINTER_STATUS_NOT_AVAILABLE,
1020 PRINTER_STATUS_WAITING,
1021 PRINTER_STATUS_PROCESSING,
1022 PRINTER_STATUS_INITIALIZING,
1023 PRINTER_STATUS_WARMING_UP,
1024 PRINTER_STATUS_TONER_LOW,
1025 PRINTER_STATUS_NO_TONER,
1026 PRINTER_STATUS_PAGE_PUNT,
1027 PRINTER_STATUS_USER_INTERVENTION,
1028 PRINTER_STATUS_OUT_OF_MEMORY,
1029 PRINTER_STATUS_DOOR_OPEN,
1030 PRINTER_STATUS_SERVER_UNKNOWN,
1031 PRINTER_STATUS_POWER_SAVE,
1032 /* these do not stick
1041 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1042 uint32_t attribute_list[] = {
1043 PRINTER_ATTRIBUTE_QUEUED,
1044 /* fails with WERR_INVALID_DATATYPE:
1045 PRINTER_ATTRIBUTE_DIRECT, */
1047 PRINTER_ATTRIBUTE_DEFAULT, */
1048 PRINTER_ATTRIBUTE_SHARED,
1050 PRINTER_ATTRIBUTE_NETWORK, */
1051 PRINTER_ATTRIBUTE_HIDDEN,
1052 PRINTER_ATTRIBUTE_LOCAL,
1053 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1054 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1055 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1056 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1058 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1059 /* fails with WERR_INVALID_DATATYPE:
1060 PRINTER_ATTRIBUTE_RAW_ONLY, */
1061 /* these do not stick
1062 PRINTER_ATTRIBUTE_PUBLISHED,
1063 PRINTER_ATTRIBUTE_FAX,
1064 PRINTER_ATTRIBUTE_TS,
1083 ZERO_STRUCT(devmode_ctr);
1084 ZERO_STRUCT(secdesc_ctr);
1086 s.in.handle = handle;
1088 s.in.info_ctr = &info_ctr;
1089 s.in.devmode_ctr = &devmode_ctr;
1090 s.in.secdesc_ctr = &secdesc_ctr;
1092 q.in.handle = handle;
1096 #define TESTGETCALL(call, r) \
1097 r.in.buffer = NULL; \
1099 r.out.needed = &needed; \
1100 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1101 if (!NT_STATUS_IS_OK(status)) { \
1102 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1103 r.in.level, nt_errstr(status), __location__); \
1107 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1108 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1109 data_blob_clear(&blob); \
1110 r.in.buffer = &blob; \
1111 r.in.offered = needed; \
1113 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1114 if (!NT_STATUS_IS_OK(status)) { \
1115 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1116 r.in.level, nt_errstr(status), __location__); \
1120 if (!W_ERROR_IS_OK(r.out.result)) { \
1121 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1122 r.in.level, win_errstr(r.out.result), __location__); \
1128 #define TESTSETCALL_EXP(call, r, err) \
1129 clear_info2(&info_ctr);\
1130 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1131 if (!NT_STATUS_IS_OK(status)) { \
1132 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1133 r.in.info_ctr->level, nt_errstr(status), __location__); \
1137 if (!W_ERROR_IS_OK(err)) { \
1138 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1139 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1140 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1145 if (!W_ERROR_IS_OK(r.out.result)) { \
1146 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1147 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1152 #define TESTSETCALL(call, r) \
1153 TESTSETCALL_EXP(call, r, WERR_OK)
1155 #define STRING_EQUAL(s1, s2, field) \
1156 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1157 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1158 #field, s2, __location__); \
1163 #define MEM_EQUAL(s1, s2, length, field) \
1164 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1165 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1166 #field, (const char *)s2, __location__); \
1171 #define INT_EQUAL(i1, i2, field) \
1173 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1174 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1179 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1180 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1181 q.in.level = lvl1; \
1182 TESTGETCALL(GetPrinter, q) \
1183 info_ctr.level = lvl1; \
1184 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1185 info_ctr.info.info ## lvl1->field1 = value;\
1186 TESTSETCALL_EXP(SetPrinter, s, err) \
1187 info_ctr.info.info ## lvl1->field1 = ""; \
1188 TESTGETCALL(GetPrinter, q) \
1189 info_ctr.info.info ## lvl1->field1 = value; \
1190 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1191 q.in.level = lvl2; \
1192 TESTGETCALL(GetPrinter, q) \
1193 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1194 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1197 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1198 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1201 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1202 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1203 q.in.level = lvl1; \
1204 TESTGETCALL(GetPrinter, q) \
1205 info_ctr.level = lvl1; \
1206 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1207 info_ctr.info.info ## lvl1->field1 = value; \
1208 TESTSETCALL(SetPrinter, s) \
1209 info_ctr.info.info ## lvl1->field1 = 0; \
1210 TESTGETCALL(GetPrinter, q) \
1211 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1212 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1213 q.in.level = lvl2; \
1214 TESTGETCALL(GetPrinter, q) \
1215 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1216 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1219 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1220 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1224 do { TESTGETCALL(GetPrinter, q0) } while (0);
1226 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1227 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1229 /* level 0 printername does not stick */
1230 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1231 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1232 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1233 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1234 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1235 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1236 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1237 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1238 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1239 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1240 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1241 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1242 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1243 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1244 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1246 /* servername can be set but does not stick
1247 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1248 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1249 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1252 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1253 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1254 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1255 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1256 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1258 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1259 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1260 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1261 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1262 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1263 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1264 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1265 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1266 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1267 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1269 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1270 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1272 (attribute_list[i] | default_attribute)
1274 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1276 (attribute_list[i] | default_attribute)
1278 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1280 (attribute_list[i] | default_attribute)
1282 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1284 (attribute_list[i] | default_attribute)
1286 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1288 (attribute_list[i] | default_attribute)
1290 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1292 (attribute_list[i] | default_attribute)
1294 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1296 (attribute_list[i] | default_attribute)
1298 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1300 (attribute_list[i] | default_attribute)
1302 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1304 (attribute_list[i] | default_attribute)
1306 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1308 (attribute_list[i] | default_attribute)
1310 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1312 (attribute_list[i] | default_attribute)
1314 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1316 (attribute_list[i] | default_attribute)
1320 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1321 /* level 2 sets do not stick
1322 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1323 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1324 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1325 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1326 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1327 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1330 /* priorities need to be between 0 and 99
1331 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1332 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1333 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1334 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1335 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1336 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1337 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1338 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1339 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1341 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1342 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1345 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1346 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1349 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1350 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1352 /* FIXME: gd also test devmode and secdesc behavior */
1355 /* verify composition of level 1 description field */
1356 const char *description;
1360 do { TESTGETCALL(GetPrinter, q0) } while (0);
1362 description = talloc_strdup(tctx, q0.out.info->info1.description);
1365 do { TESTGETCALL(GetPrinter, q0) } while (0);
1367 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1368 q0.out.info->info2.printername,
1369 q0.out.info->info2.drivername,
1370 q0.out.info->info2.location);
1372 do { STRING_EQUAL(description, tmp, "description")} while (0);
1379 static bool test_ClosePrinter(struct torture_context *tctx,
1380 struct dcerpc_pipe *p,
1381 struct policy_handle *handle)
1384 struct spoolss_ClosePrinter r;
1386 r.in.handle = handle;
1387 r.out.handle = handle;
1389 torture_comment(tctx, "Testing ClosePrinter\n");
1391 status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
1392 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
1397 static bool test_GetForm(struct torture_context *tctx,
1398 struct dcerpc_pipe *p,
1399 struct policy_handle *handle,
1400 const char *form_name,
1404 struct spoolss_GetForm r;
1407 r.in.handle = handle;
1408 r.in.form_name = form_name;
1412 r.out.needed = &needed;
1414 torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
1416 status = dcerpc_spoolss_GetForm(p, tctx, &r);
1417 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1419 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1420 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1421 data_blob_clear(&blob);
1422 r.in.buffer = &blob;
1423 r.in.offered = needed;
1424 status = dcerpc_spoolss_GetForm(p, tctx, &r);
1425 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1427 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1429 torture_assert(tctx, r.out.info, "No form info returned");
1432 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1437 static bool test_EnumForms(struct torture_context *tctx,
1438 struct dcerpc_pipe *p,
1439 struct policy_handle *handle, bool print_server)
1442 struct spoolss_EnumForms r;
1446 uint32_t levels[] = { 1, 2 };
1449 for (i=0; i<ARRAY_SIZE(levels); i++) {
1451 union spoolss_FormInfo *info;
1453 r.in.handle = handle;
1454 r.in.level = levels[i];
1457 r.out.needed = &needed;
1458 r.out.count = &count;
1461 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
1463 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1464 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1466 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
1470 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
1471 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1473 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1475 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1476 data_blob_clear(&blob);
1477 r.in.buffer = &blob;
1478 r.in.offered = needed;
1480 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1482 torture_assert(tctx, info, "No forms returned");
1484 for (j = 0; j < count; j++) {
1486 ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
1490 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1492 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
1498 static bool test_DeleteForm(struct torture_context *tctx,
1499 struct dcerpc_pipe *p,
1500 struct policy_handle *handle,
1501 const char *form_name)
1504 struct spoolss_DeleteForm r;
1506 r.in.handle = handle;
1507 r.in.form_name = form_name;
1509 status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
1511 torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
1513 torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
1518 static bool test_AddForm(struct torture_context *tctx,
1519 struct dcerpc_pipe *p,
1520 struct policy_handle *handle, bool print_server)
1522 struct spoolss_AddForm r;
1523 struct spoolss_AddFormInfo1 addform;
1524 const char *form_name = "testform3";
1528 r.in.handle = handle;
1530 r.in.info.info1 = &addform;
1531 addform.flags = SPOOLSS_FORM_USER;
1532 addform.form_name = form_name;
1533 addform.size.width = 50;
1534 addform.size.height = 25;
1535 addform.area.left = 5;
1536 addform.area.top = 10;
1537 addform.area.right = 45;
1538 addform.area.bottom = 15;
1540 status = dcerpc_spoolss_AddForm(p, tctx, &r);
1542 torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
1544 torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
1546 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1549 struct spoolss_SetForm sf;
1550 struct spoolss_AddFormInfo1 setform;
1552 sf.in.handle = handle;
1553 sf.in.form_name = form_name;
1555 sf.in.info.info1= &setform;
1556 setform.flags = addform.flags;
1557 setform.form_name = addform.form_name;
1558 setform.size = addform.size;
1559 setform.area = addform.area;
1561 setform.size.width = 1234;
1563 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
1565 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
1567 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
1570 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1573 struct spoolss_EnumForms e;
1574 union spoolss_FormInfo *info;
1579 e.in.handle = handle;
1583 e.out.needed = &needed;
1584 e.out.count = &count;
1587 torture_comment(tctx, "Testing EnumForms level 1\n");
1589 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1590 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1592 if (print_server && W_ERROR_EQUAL(e.out.result, WERR_BADFID))
1593 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1595 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
1597 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1598 data_blob_clear(&blob);
1599 e.in.buffer = &blob;
1600 e.in.offered = needed;
1602 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1604 torture_assert(tctx, info, "No forms returned");
1606 for (j = 0; j < count; j++) {
1607 if (strequal(form_name, info[j].info1.form_name)) {
1613 torture_assert(tctx, found, "Newly added form not found in enum call");
1616 if (!test_DeleteForm(tctx, p, handle, form_name)) {
1623 static bool test_EnumPorts_old(struct torture_context *tctx,
1624 struct dcerpc_pipe *p)
1627 struct spoolss_EnumPorts r;
1630 union spoolss_PortInfo *info;
1632 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
1633 dcerpc_server_name(p));
1637 r.out.needed = &needed;
1638 r.out.count = &count;
1641 torture_comment(tctx, "Testing EnumPorts\n");
1643 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1645 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1647 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1648 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1649 data_blob_clear(&blob);
1650 r.in.buffer = &blob;
1651 r.in.offered = needed;
1653 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1654 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1656 torture_assert(tctx, info, "No ports returned");
1662 static bool test_AddPort(struct torture_context *tctx,
1663 struct dcerpc_pipe *p)
1666 struct spoolss_AddPort r;
1668 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
1669 dcerpc_server_name(p));
1671 r.in.monitor_name = "foo";
1673 torture_comment(tctx, "Testing AddPort\n");
1675 status = dcerpc_spoolss_AddPort(p, tctx, &r);
1677 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
1679 /* win2k3 returns WERR_NOT_SUPPORTED */
1683 if (!W_ERROR_IS_OK(r.out.result)) {
1684 printf("AddPort failed - %s\n", win_errstr(r.out.result));
1693 static bool test_GetJob(struct torture_context *tctx,
1694 struct dcerpc_pipe *p,
1695 struct policy_handle *handle, uint32_t job_id)
1698 struct spoolss_GetJob r;
1699 union spoolss_JobInfo info;
1701 uint32_t levels[] = {1, 2 /* 3, 4 */};
1704 r.in.handle = handle;
1705 r.in.job_id = job_id;
1709 r.out.needed = &needed;
1712 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1714 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1715 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
1717 for (i = 0; i < ARRAY_SIZE(levels); i++) {
1719 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1723 r.in.level = levels[i];
1727 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1728 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1730 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1731 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1732 data_blob_clear(&blob);
1733 r.in.buffer = &blob;
1734 r.in.offered = needed;
1736 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1737 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1740 torture_assert(tctx, r.out.info, "No job info returned");
1741 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
1747 static bool test_SetJob(struct torture_context *tctx,
1748 struct dcerpc_pipe *p,
1749 struct policy_handle *handle, uint32_t job_id,
1750 enum spoolss_JobControl command)
1753 struct spoolss_SetJob r;
1755 r.in.handle = handle;
1756 r.in.job_id = job_id;
1758 r.in.command = command;
1761 case SPOOLSS_JOB_CONTROL_PAUSE:
1762 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1764 case SPOOLSS_JOB_CONTROL_RESUME:
1765 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1767 case SPOOLSS_JOB_CONTROL_CANCEL:
1768 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1770 case SPOOLSS_JOB_CONTROL_RESTART:
1771 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1773 case SPOOLSS_JOB_CONTROL_DELETE:
1774 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1776 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
1777 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1779 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
1780 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1782 case SPOOLSS_JOB_CONTROL_RETAIN:
1783 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1785 case SPOOLSS_JOB_CONTROL_RELEASE:
1786 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1789 torture_comment(tctx, "Testing SetJob\n");
1793 status = dcerpc_spoolss_SetJob(p, tctx, &r);
1794 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
1795 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
1800 static bool test_AddJob(struct torture_context *tctx,
1801 struct dcerpc_pipe *p,
1802 struct policy_handle *handle)
1805 struct spoolss_AddJob r;
1809 r.in.handle = handle;
1811 r.out.needed = &needed;
1812 r.in.buffer = r.out.buffer = NULL;
1814 torture_comment(tctx, "Testing AddJob\n");
1816 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1817 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
1821 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1822 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
1828 static bool test_EnumJobs(struct torture_context *tctx,
1829 struct dcerpc_pipe *p,
1830 struct policy_handle *handle)
1833 struct spoolss_EnumJobs r;
1836 union spoolss_JobInfo *info;
1838 r.in.handle = handle;
1840 r.in.numjobs = 0xffffffff;
1844 r.out.needed = &needed;
1845 r.out.count = &count;
1848 torture_comment(tctx, "Testing EnumJobs\n");
1850 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1852 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1854 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1856 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1857 data_blob_clear(&blob);
1858 r.in.buffer = &blob;
1859 r.in.offered = needed;
1861 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1863 torture_assert(tctx, info, "No jobs returned");
1865 for (j = 0; j < count; j++) {
1867 test_GetJob(tctx, p, handle, info[j].info1.job_id);
1870 if (!torture_setting_bool(tctx, "samba3", false)) {
1871 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
1872 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
1877 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1883 static bool test_DoPrintTest(struct torture_context *tctx,
1884 struct dcerpc_pipe *p,
1885 struct policy_handle *handle)
1889 struct spoolss_StartDocPrinter s;
1890 struct spoolss_DocumentInfo1 info1;
1891 struct spoolss_StartPagePrinter sp;
1892 struct spoolss_WritePrinter w;
1893 struct spoolss_EndPagePrinter ep;
1894 struct spoolss_EndDocPrinter e;
1897 uint32_t num_written;
1899 torture_comment(tctx, "Testing StartDocPrinter\n");
1901 s.in.handle = handle;
1903 s.in.info.info1 = &info1;
1904 s.out.job_id = &job_id;
1905 info1.document_name = "TorturePrintJob";
1906 info1.output_file = NULL;
1907 info1.datatype = "RAW";
1909 status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
1910 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
1911 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
1913 for (i=1; i < 4; i++) {
1914 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
1916 sp.in.handle = handle;
1918 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
1919 torture_assert_ntstatus_ok(tctx, status,
1920 "dcerpc_spoolss_StartPagePrinter failed");
1921 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
1923 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
1925 w.in.handle = handle;
1926 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
1927 w.out.num_written = &num_written;
1929 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
1930 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
1931 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
1933 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
1935 ep.in.handle = handle;
1937 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
1938 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
1939 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
1942 torture_comment(tctx, "Testing EndDocPrinter\n");
1944 e.in.handle = handle;
1946 status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
1947 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
1948 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
1950 ret &= test_AddJob(tctx, p, handle);
1951 ret &= test_EnumJobs(tctx, p, handle);
1953 ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
1958 static bool test_PausePrinter(struct torture_context *tctx,
1959 struct dcerpc_pipe *p,
1960 struct policy_handle *handle)
1963 struct spoolss_SetPrinter r;
1964 struct spoolss_SetPrinterInfoCtr info_ctr;
1965 struct spoolss_DevmodeContainer devmode_ctr;
1966 struct sec_desc_buf secdesc_ctr;
1969 info_ctr.info.info0 = NULL;
1971 ZERO_STRUCT(devmode_ctr);
1972 ZERO_STRUCT(secdesc_ctr);
1974 r.in.handle = handle;
1975 r.in.info_ctr = &info_ctr;
1976 r.in.devmode_ctr = &devmode_ctr;
1977 r.in.secdesc_ctr = &secdesc_ctr;
1978 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
1980 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1982 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1984 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1986 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1991 static bool test_ResumePrinter(struct torture_context *tctx,
1992 struct dcerpc_pipe *p,
1993 struct policy_handle *handle)
1996 struct spoolss_SetPrinter r;
1997 struct spoolss_SetPrinterInfoCtr info_ctr;
1998 struct spoolss_DevmodeContainer devmode_ctr;
1999 struct sec_desc_buf secdesc_ctr;
2002 info_ctr.info.info0 = NULL;
2004 ZERO_STRUCT(devmode_ctr);
2005 ZERO_STRUCT(secdesc_ctr);
2007 r.in.handle = handle;
2008 r.in.info_ctr = &info_ctr;
2009 r.in.devmode_ctr = &devmode_ctr;
2010 r.in.secdesc_ctr = &secdesc_ctr;
2011 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
2013 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2015 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2017 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2019 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2024 static bool test_GetPrinterData(struct torture_context *tctx,
2025 struct dcerpc_pipe *p,
2026 struct policy_handle *handle,
2027 const char *value_name)
2030 struct spoolss_GetPrinterData r;
2032 enum winreg_Type type;
2033 union spoolss_PrinterData data;
2035 r.in.handle = handle;
2036 r.in.value_name = value_name;
2038 r.out.needed = &needed;
2042 torture_comment(tctx, "Testing GetPrinterData\n");
2044 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2045 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2047 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2048 r.in.offered = needed;
2050 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2051 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2053 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterData failed");
2059 static bool test_GetPrinterDataEx(struct torture_context *tctx,
2060 struct dcerpc_pipe *p,
2061 struct policy_handle *handle,
2062 const char *key_name,
2063 const char *value_name)
2066 struct spoolss_GetPrinterDataEx r;
2067 enum winreg_Type type;
2070 r.in.handle = handle;
2071 r.in.key_name = key_name;
2072 r.in.value_name = value_name;
2075 r.out.needed = &needed;
2076 r.out.buffer = NULL;
2078 torture_comment(tctx, "Testing GetPrinterDataEx\n");
2080 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2081 if (!NT_STATUS_IS_OK(status)) {
2082 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
2083 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
2084 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
2086 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2089 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2090 r.in.offered = needed;
2091 r.out.buffer = talloc_array(tctx, uint8_t, needed);
2093 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2094 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2096 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDataEx failed");
2102 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
2103 struct policy_handle *handle)
2106 struct spoolss_EnumPrinterData r;
2109 r.in.handle = handle;
2110 r.in.enum_index = 0;
2113 uint32_t value_size = 0;
2114 uint32_t data_size = 0;
2115 enum winreg_Type type = 0;
2117 r.in.value_offered = value_size;
2118 r.out.value_needed = &value_size;
2119 r.in.data_offered = data_size;
2120 r.out.data_needed = &data_size;
2123 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
2125 torture_comment(tctx, "Testing EnumPrinterData\n");
2127 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2129 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2131 r.in.value_offered = value_size;
2132 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
2133 r.in.data_offered = data_size;
2134 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
2136 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2138 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2140 test_GetPrinterData(tctx, p, handle, r.out.value_name);
2142 test_GetPrinterDataEx(tctx,
2143 p, handle, "PrinterDriverData",
2148 } while (W_ERROR_IS_OK(r.out.result));
2153 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
2154 struct dcerpc_pipe *p,
2155 struct policy_handle *handle)
2158 struct spoolss_EnumPrinterDataEx r;
2159 struct spoolss_PrinterEnumValues *info;
2163 r.in.handle = handle;
2164 r.in.key_name = "PrinterDriverData";
2166 r.out.needed = &needed;
2167 r.out.count = &count;
2170 torture_comment(tctx, "Testing EnumPrinterDataEx\n");
2172 status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
2173 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
2175 r.in.offered = needed;
2177 status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
2179 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
2185 static bool test_DeletePrinterData(struct torture_context *tctx,
2186 struct dcerpc_pipe *p,
2187 struct policy_handle *handle,
2188 const char *value_name)
2191 struct spoolss_DeletePrinterData r;
2193 r.in.handle = handle;
2194 r.in.value_name = value_name;
2196 torture_comment(tctx, "Testing DeletePrinterData\n");
2198 status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
2200 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
2205 static bool test_SetPrinterData(struct torture_context *tctx,
2206 struct dcerpc_pipe *p,
2207 struct policy_handle *handle)
2210 struct spoolss_SetPrinterData r;
2211 const char *value_name = "spottyfoot";
2213 r.in.handle = handle;
2214 r.in.value_name = value_name;
2216 r.in.data.string = "dog";
2218 torture_comment(tctx, "Testing SetPrinterData\n");
2220 status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
2222 torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
2224 if (!test_GetPrinterData(tctx, p, handle, value_name)) {
2228 if (!test_DeletePrinterData(tctx, p, handle, value_name)) {
2235 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
2236 struct dcerpc_pipe *p,
2237 struct policy_handle *handle)
2240 struct dcerpc_binding *b;
2241 struct dcerpc_pipe *p2;
2242 struct spoolss_ClosePrinter cp;
2244 /* only makes sense on SMB */
2245 if (p->conn->transport.transport != NCACN_NP) {
2249 torture_comment(tctx, "testing close on secondary pipe\n");
2251 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
2252 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
2254 status = dcerpc_secondary_connection(p, &p2, b);
2255 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
2257 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
2258 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
2260 cp.in.handle = handle;
2261 cp.out.handle = handle;
2263 status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
2264 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
2265 "ERROR: Allowed close on secondary connection");
2267 torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
2268 "Unexpected fault code");
2275 static bool test_OpenPrinter_badname(struct torture_context *tctx,
2276 struct dcerpc_pipe *p, const char *name)
2279 struct spoolss_OpenPrinter op;
2280 struct spoolss_OpenPrinterEx opEx;
2281 struct policy_handle handle;
2284 op.in.printername = name;
2285 op.in.datatype = NULL;
2286 op.in.devmode_ctr.devmode= NULL;
2287 op.in.access_mask = 0;
2288 op.out.handle = &handle;
2290 torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
2292 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
2293 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2294 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
2295 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
2296 name, win_errstr(op.out.result));
2299 if (W_ERROR_IS_OK(op.out.result)) {
2300 ret &=test_ClosePrinter(tctx, p, &handle);
2303 opEx.in.printername = name;
2304 opEx.in.datatype = NULL;
2305 opEx.in.devmode_ctr.devmode = NULL;
2306 opEx.in.access_mask = 0;
2308 opEx.in.userlevel.level1 = NULL;
2309 opEx.out.handle = &handle;
2311 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
2313 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
2314 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2315 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
2316 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
2317 name, win_errstr(opEx.out.result));
2320 if (W_ERROR_IS_OK(opEx.out.result)) {
2321 ret &=test_ClosePrinter(tctx, p, &handle);
2327 static bool test_OpenPrinter(struct torture_context *tctx,
2328 struct dcerpc_pipe *p,
2332 struct spoolss_OpenPrinter r;
2333 struct policy_handle handle;
2336 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
2337 r.in.datatype = NULL;
2338 r.in.devmode_ctr.devmode= NULL;
2339 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2340 r.out.handle = &handle;
2342 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
2344 status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
2346 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2348 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
2350 if (!test_GetPrinter(tctx, p, &handle)) {
2354 if (!torture_setting_bool(tctx, "samba3", false)) {
2355 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2360 if (!test_ClosePrinter(tctx, p, &handle)) {
2367 static bool call_OpenPrinterEx(struct torture_context *tctx,
2368 struct dcerpc_pipe *p,
2369 const char *name, struct policy_handle *handle)
2371 struct spoolss_OpenPrinterEx r;
2372 struct spoolss_UserLevel1 userlevel1;
2375 if (name && name[0]) {
2376 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
2377 dcerpc_server_name(p), name);
2379 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
2380 dcerpc_server_name(p));
2383 r.in.datatype = NULL;
2384 r.in.devmode_ctr.devmode= NULL;
2385 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2387 r.in.userlevel.level1 = &userlevel1;
2388 r.out.handle = handle;
2390 userlevel1.size = 1234;
2391 userlevel1.client = "hello";
2392 userlevel1.user = "spottyfoot!";
2393 userlevel1.build = 1;
2394 userlevel1.major = 2;
2395 userlevel1.minor = 3;
2396 userlevel1.processor = 4;
2398 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
2400 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
2402 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2404 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
2409 static bool test_OpenPrinterEx(struct torture_context *tctx,
2410 struct dcerpc_pipe *p,
2413 struct policy_handle handle;
2416 if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
2420 if (!test_GetPrinter(tctx, p, &handle)) {
2424 if (!test_EnumForms(tctx, p, &handle, false)) {
2428 if (!test_AddForm(tctx, p, &handle, false)) {
2432 if (!test_EnumPrinterData(tctx, p, &handle)) {
2436 if (!test_EnumPrinterDataEx(tctx, p, &handle)) {
2440 if (!test_PausePrinter(tctx, p, &handle)) {
2444 if (!test_DoPrintTest(tctx, p, &handle)) {
2448 if (!test_ResumePrinter(tctx, p, &handle)) {
2452 if (!test_SetPrinterData(tctx, p, &handle)) {
2456 if (!torture_setting_bool(tctx, "samba3", false)) {
2457 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2462 if (!test_ClosePrinter(tctx, p, &handle)) {
2469 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
2471 struct spoolss_EnumPrinters r;
2473 uint16_t levels[] = {1, 2, 4, 5};
2477 for (i=0;i<ARRAY_SIZE(levels);i++) {
2478 union spoolss_PrinterInfo *info;
2483 r.in.flags = PRINTER_ENUM_LOCAL;
2485 r.in.level = levels[i];
2488 r.out.needed = &needed;
2489 r.out.count = &count;
2492 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
2494 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2495 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2497 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2498 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2499 data_blob_clear(&blob);
2500 r.in.buffer = &blob;
2501 r.in.offered = needed;
2502 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2505 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2507 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
2510 torture_comment(tctx, "No printers returned\n");
2514 for (j=0;j<count;j++) {
2515 if (r.in.level == 1) {
2516 char *unc = talloc_strdup(tctx, info[j].info1.name);
2519 if (unc[0] == '\\' && unc[1] == '\\') {
2522 slash = strchr(unc, '\\');
2527 if (!test_OpenPrinter(tctx, p, name)) {
2530 if (!test_OpenPrinterEx(tctx, p, name)) {
2541 static bool test_GetPrinterDriver2(struct dcerpc_pipe *p,
2542 struct policy_handle *handle,
2543 const char *driver_name)
2546 struct spoolss_GetPrinterDriver2 r;
2548 uint32_t server_major_version;
2549 uint32_t server_minor_version;
2551 r.in.handle = handle;
2552 r.in.architecture = "W32X86";
2556 r.in.client_major_version = 0;
2557 r.in.client_minor_version = 0;
2558 r.out.needed = &needed;
2559 r.out.server_major_version = &server_major_version;
2560 r.out.server_minor_version = &server_minor_version;
2562 printf("Testing GetPrinterDriver2\n");
2564 status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
2565 if (!NT_STATUS_IS_OK(status)) {
2566 printf("GetPrinterDriver2 failed - %s\n", nt_errstr(status));
2570 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2571 r.in.offered = needed;
2572 status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
2575 if (!NT_STATUS_IS_OK(status)) {
2576 printf("GetPrinterDriver2 failed - %s\n",
2581 if (!W_ERROR_IS_OK(r.out.result)) {
2582 printf("GetPrinterDriver2 failed - %s\n",
2583 win_errstr(r.out.result));
2591 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
2592 struct dcerpc_pipe *p)
2594 struct spoolss_EnumPrinterDrivers r;
2596 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
2599 for (i=0;i<ARRAY_SIZE(levels);i++) {
2603 union spoolss_DriverInfo *info;
2605 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2606 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
2607 r.in.level = levels[i];
2610 r.out.needed = &needed;
2611 r.out.count = &count;
2614 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
2616 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2618 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2620 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2621 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2622 data_blob_clear(&blob);
2623 r.in.buffer = &blob;
2624 r.in.offered = needed;
2625 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2628 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2630 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
2633 torture_comment(tctx, "No printer drivers returned\n");
2641 static bool test_DeletePrinter(struct torture_context *tctx,
2642 struct dcerpc_pipe *p,
2643 struct policy_handle *handle)
2645 struct spoolss_DeletePrinter r;
2647 torture_comment(tctx, "Testing DeletePrinter\n");
2649 r.in.handle = handle;
2651 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter(p, tctx, &r),
2652 "failed to delete printer");
2653 torture_assert_werr_ok(tctx, r.out.result,
2654 "failed to delete printer");
2659 static bool test_EnumPrinters_findname(struct torture_context *tctx,
2660 struct dcerpc_pipe *p,
2666 struct spoolss_EnumPrinters e;
2668 union spoolss_PrinterInfo *info;
2679 e.out.count = &count;
2681 e.out.needed = &needed;
2683 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
2684 "failed to enum printers");
2686 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
2687 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2688 data_blob_clear(&blob);
2689 e.in.buffer = &blob;
2690 e.in.offered = needed;
2692 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
2693 "failed to enum printers");
2696 torture_assert_werr_ok(tctx, e.out.result,
2697 "failed to enum printers");
2699 for (i=0; i < count; i++) {
2701 const char *current = NULL;
2705 current = info[i].info1.name;
2709 if (strequal(current, name)) {
2718 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
2719 struct dcerpc_pipe *p,
2720 const char *printername,
2724 struct spoolss_AddPrinter r;
2725 struct spoolss_AddPrinterEx rex;
2726 struct spoolss_SetPrinterInfoCtr info_ctr;
2727 struct spoolss_SetPrinterInfo1 info1;
2728 struct spoolss_DevmodeContainer devmode_ctr;
2729 struct sec_desc_buf secdesc_ctr;
2730 struct spoolss_UserLevelCtr userlevel_ctr;
2731 struct policy_handle handle;
2734 ZERO_STRUCT(devmode_ctr);
2735 ZERO_STRUCT(secdesc_ctr);
2736 ZERO_STRUCT(userlevel_ctr);
2739 torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
2741 /* try to add printer to wellknown printer list (level 1) */
2743 userlevel_ctr.level = 1;
2745 info_ctr.info.info1 = &info1;
2748 rex.in.server = NULL;
2749 rex.in.info_ctr = &info_ctr;
2750 rex.in.devmode_ctr = &devmode_ctr;
2751 rex.in.secdesc_ctr = &secdesc_ctr;
2752 rex.in.userlevel_ctr = &userlevel_ctr;
2753 rex.out.handle = &handle;
2756 r.in.info_ctr = &info_ctr;
2757 r.in.devmode_ctr = &devmode_ctr;
2758 r.in.secdesc_ctr = &secdesc_ctr;
2759 r.out.handle = &handle;
2761 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2762 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2763 "failed to add printer");
2764 result = ex ? rex.out.result : r.out.result;
2765 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
2766 "unexpected result code");
2768 info1.name = printername;
2769 info1.flags = PRINTER_ATTRIBUTE_SHARED;
2771 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2772 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2773 "failed to add printer");
2774 result = ex ? rex.out.result : r.out.result;
2775 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
2776 "unexpected result code");
2778 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
2779 better do a real check to see the printer is really there */
2781 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
2782 PRINTER_ENUM_NETWORK, 1,
2785 "failed to enum printers");
2787 torture_assert(tctx, found, "failed to find newly added printer");
2791 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2792 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2793 "failed to add printer");
2794 result = ex ? rex.out.result : r.out.result;
2795 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
2796 "unexpected result code");
2798 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
2799 better do a real check to see the printer has really been removed
2800 from the well known printer list */
2804 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
2805 PRINTER_ENUM_NETWORK, 1,
2808 "failed to enum printers");
2810 torture_assert(tctx, !found, "printer still in well known printer list");
2815 static bool test_AddPrinter_normal(struct torture_context *tctx,
2816 struct dcerpc_pipe *p,
2817 struct policy_handle *handle_p,
2818 const char *printername,
2819 const char *drivername,
2820 const char *portname,
2824 struct spoolss_AddPrinter r;
2825 struct spoolss_AddPrinterEx rex;
2826 struct spoolss_SetPrinterInfoCtr info_ctr;
2827 struct spoolss_SetPrinterInfo2 info2;
2828 struct spoolss_DevmodeContainer devmode_ctr;
2829 struct sec_desc_buf secdesc_ctr;
2830 struct spoolss_UserLevelCtr userlevel_ctr;
2831 struct policy_handle handle;
2834 ZERO_STRUCT(devmode_ctr);
2835 ZERO_STRUCT(secdesc_ctr);
2836 ZERO_STRUCT(userlevel_ctr);
2838 torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
2840 userlevel_ctr.level = 1;
2842 rex.in.server = NULL;
2843 rex.in.info_ctr = &info_ctr;
2844 rex.in.devmode_ctr = &devmode_ctr;
2845 rex.in.secdesc_ctr = &secdesc_ctr;
2846 rex.in.userlevel_ctr = &userlevel_ctr;
2847 rex.out.handle = &handle;
2850 r.in.info_ctr = &info_ctr;
2851 r.in.devmode_ctr = &devmode_ctr;
2852 r.in.secdesc_ctr = &secdesc_ctr;
2853 r.out.handle = &handle;
2857 /* try to add printer to printer list (level 2) */
2861 info_ctr.info.info2 = &info2;
2864 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2865 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2866 "failed to add printer");
2867 result = ex ? rex.out.result : r.out.result;
2868 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
2869 "unexpected result code");
2871 info2.printername = printername;
2873 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2874 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2875 "failed to add printer");
2876 result = ex ? rex.out.result : r.out.result;
2878 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
2879 struct policy_handle printer_handle;
2881 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, &printer_handle),
2882 "failed to open printer handle");
2884 torture_assert(tctx, test_DeletePrinter(tctx, p, &printer_handle),
2885 "failed to delete printer");
2887 torture_assert(tctx, test_ClosePrinter(tctx, p, &printer_handle),
2888 "failed to close server handle");
2893 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
2894 "unexpected result code");
2896 info2.portname = portname;
2898 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2899 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2900 "failed to add printer");
2901 result = ex ? rex.out.result : r.out.result;
2902 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
2903 "unexpected result code");
2905 info2.drivername = drivername;
2907 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2908 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2909 "failed to add printer");
2910 result = ex ? rex.out.result : r.out.result;
2911 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
2912 "unexpected result code");
2914 info2.printprocessor = "winprint";
2916 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2917 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2918 "failed to add printer");
2919 result = ex ? rex.out.result : r.out.result;
2920 torture_assert_werr_ok(tctx, result,
2921 "failed to add printer");
2925 /* we are paranoid, really check if the printer is there now */
2927 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
2928 PRINTER_ENUM_LOCAL, 1,
2931 "failed to enum printers");
2932 torture_assert(tctx, found, "failed to find newly added printer");
2934 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2935 dcerpc_spoolss_AddPrinter(p, tctx, &r),
2936 "failed to add printer");
2937 result = ex ? rex.out.result : r.out.result;
2938 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
2939 "unexpected result code");
2944 static bool test_AddPrinterEx(struct torture_context *tctx,
2945 struct dcerpc_pipe *p,
2946 struct policy_handle *handle_p,
2947 const char *printername,
2948 const char *drivername,
2949 const char *portname)
2953 if (!torture_setting_bool(tctx, "samba3", false)) {
2954 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
2955 torture_comment(tctx, "failed to add printer to well known list\n");
2960 if (!test_AddPrinter_normal(tctx, p, handle_p,
2961 printername, drivername, portname,
2963 torture_comment(tctx, "failed to add printer to printer list\n");
2970 static bool test_AddPrinter(struct torture_context *tctx,
2971 struct dcerpc_pipe *p,
2972 struct policy_handle *handle_p,
2973 const char *printername,
2974 const char *drivername,
2975 const char *portname)
2979 if (!torture_setting_bool(tctx, "samba3", false)) {
2980 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
2981 torture_comment(tctx, "failed to add printer to well known list\n");
2986 if (!test_AddPrinter_normal(tctx, p, handle_p,
2987 printername, drivername, portname,
2989 torture_comment(tctx, "failed to add printer to printer list\n");
2996 static bool test_printer_info(struct torture_context *tctx,
2997 struct dcerpc_pipe *p,
2998 struct policy_handle *handle)
3002 if (!test_PrinterInfo(tctx, p, handle)) {
3006 if (!test_SetPrinter_errors(tctx, p, handle)) {
3013 static bool test_printer(struct torture_context *tctx,
3014 struct dcerpc_pipe *p)
3017 struct policy_handle handle[2];
3019 const char *drivername = "Microsoft XPS Document Writer";
3020 const char *portname = "LPT1:";
3022 /* test printer created via AddPrinter */
3024 if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
3028 if (!test_printer_info(tctx, p, &handle[0])) {
3032 if (!test_DeletePrinter(tctx, p, &handle[0])) {
3036 if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3037 TORTURE_PRINTER, &found)) {
3041 torture_assert(tctx, !found, "deleted printer still there");
3043 /* test printer created via AddPrinterEx */
3045 if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
3049 if (!test_printer_info(tctx, p, &handle[1])) {
3053 if (!test_DeletePrinter(tctx, p, &handle[1])) {
3057 if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3058 TORTURE_PRINTER_EX, &found)) {
3062 torture_assert(tctx, !found, "deleted printer still there");
3067 bool torture_rpc_spoolss(struct torture_context *torture)
3070 struct dcerpc_pipe *p;
3072 struct test_spoolss_context *ctx;
3074 status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
3075 if (!NT_STATUS_IS_OK(status)) {
3079 ctx = talloc_zero(torture, struct test_spoolss_context);
3081 ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
3083 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "W3SvcInstalled");
3084 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "BeepEnabled");
3085 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "EventLog");
3086 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopup");
3087 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopupToComputer");
3088 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MajorVersion");
3089 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MinorVersion");
3090 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DefaultSpoolDirectory");
3091 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "Architecture");
3092 ret &= test_GetPrinterData(torture