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 struct test_spoolss_context {
30 /* print server handle */
31 struct policy_handle server_handle;
34 uint32_t port_count[3];
35 union spoolss_PortInfo *ports[3];
37 /* for EnumPrinterDrivers */
38 uint32_t driver_count[7];
39 union spoolss_DriverInfo *drivers[7];
41 /* for EnumMonitors */
42 uint32_t monitor_count[3];
43 union spoolss_MonitorInfo *monitors[3];
45 /* for EnumPrintProcessors */
46 uint32_t print_processor_count[2];
47 union spoolss_PrintProcessorInfo *print_processors[2];
49 /* for EnumPrinters */
50 uint32_t printer_count[6];
51 union spoolss_PrinterInfo *printers[6];
54 #define COMPARE_STRING(tctx, c,r,e) \
55 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
57 /* not every compiler supports __typeof__() */
59 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
60 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
61 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
63 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
64 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
68 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
71 #define COMPARE_UINT32(tctx, c, r, e) do {\
72 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
73 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
76 #define COMPARE_STRING_ARRAY(tctx, c,r,e)
78 static bool test_OpenPrinter_server(struct torture_context *tctx, struct dcerpc_pipe *p, struct test_spoolss_context *ctx)
81 struct spoolss_OpenPrinter op;
83 op.in.printername = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p));
84 op.in.datatype = NULL;
85 op.in.devmode_ctr.devmode= NULL;
86 op.in.access_mask = 0;
87 op.out.handle = &ctx->server_handle;
89 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
91 status = dcerpc_spoolss_OpenPrinter(p, ctx, &op);
92 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
93 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
98 static bool test_EnumPorts(struct torture_context *tctx,
99 struct dcerpc_pipe *p,
100 struct test_spoolss_context *ctx)
103 struct spoolss_EnumPorts r;
104 uint16_t levels[] = { 1, 2 };
107 for (i=0;i<ARRAY_SIZE(levels);i++) {
108 int level = levels[i];
112 union spoolss_PortInfo *info;
114 r.in.servername = "";
118 r.out.needed = &needed;
119 r.out.count = &count;
122 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
124 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
125 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
126 if (W_ERROR_IS_OK(r.out.result)) {
127 /* TODO: do some more checks here */
130 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
131 "EnumPorts unexpected return code");
133 blob = data_blob_talloc(ctx, NULL, needed);
134 data_blob_clear(&blob);
136 r.in.offered = needed;
138 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
139 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
141 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
143 torture_assert(tctx, info, "EnumPorts returned no info");
145 ctx->port_count[level] = count;
146 ctx->ports[level] = info;
149 for (i=1;i<ARRAY_SIZE(levels);i++) {
150 int level = levels[i];
151 int old_level = levels[i-1];
152 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
153 "EnumPorts invalid value");
155 /* if the array sizes are not the same we would maybe segfault in the following code */
157 for (i=0;i<ARRAY_SIZE(levels);i++) {
158 int level = levels[i];
159 for (j=0;j<ctx->port_count[level];j++) {
160 union spoolss_PortInfo *cur = &ctx->ports[level][j];
161 union spoolss_PortInfo *ref = &ctx->ports[2][j];
164 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
167 /* level 2 is our reference, and it makes no sense to compare it to itself */
176 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
177 struct dcerpc_pipe *p,
178 struct test_spoolss_context *ctx)
181 struct spoolss_GetPrintProcessorDirectory r;
196 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
199 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
205 for (i=0;i<ARRAY_SIZE(levels);i++) {
206 int level = levels[i].level;
209 r.in.server = levels[i].server;
210 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
214 r.out.needed = &needed;
216 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
218 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
219 torture_assert_ntstatus_ok(tctx, status,
220 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
221 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
222 "GetPrintProcessorDirectory unexpected return code");
224 blob = data_blob_talloc(ctx, NULL, needed);
225 data_blob_clear(&blob);
227 r.in.offered = needed;
229 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
230 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
232 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
239 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
240 struct dcerpc_pipe *p,
241 struct test_spoolss_context *ctx)
244 struct spoolss_GetPrinterDriverDirectory r;
259 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
262 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
268 for (i=0;i<ARRAY_SIZE(levels);i++) {
269 int level = levels[i].level;
272 r.in.server = levels[i].server;
273 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
277 r.out.needed = &needed;
279 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
281 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
282 torture_assert_ntstatus_ok(tctx, status,
283 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
284 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
285 "GetPrinterDriverDirectory unexpected return code");
287 blob = data_blob_talloc(ctx, NULL, needed);
288 data_blob_clear(&blob);
290 r.in.offered = needed;
292 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
293 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
295 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
301 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
302 struct dcerpc_pipe *p,
303 struct test_spoolss_context *ctx)
306 struct spoolss_EnumPrinterDrivers r;
307 uint16_t levels[] = { 1, 2, 3, 4, 5, 6 };
309 const char *architectures[] = {
310 SPOOLSS_ARCHITECTURE_NT_X86,
311 SPOOLSS_ARCHITECTURE_ALL
314 for (i=0;i<ARRAY_SIZE(levels);i++) {
315 for (a=0;a<ARRAY_SIZE(architectures);a++) {
316 int level = levels[i];
320 union spoolss_DriverInfo *info;
322 /* FIXME: gd, come back and fix "" as server, and handle
323 * priority of returned error codes in torture test and samba 3
326 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
327 r.in.environment = architectures[a];
331 r.out.needed = &needed;
332 r.out.count = &count;
335 torture_comment(tctx, "Testing EnumPrinterDrivers level %u (%s)\n", r.in.level, r.in.environment);
337 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
338 torture_assert_ntstatus_ok(tctx, status,
339 "dcerpc_spoolss_EnumPrinterDrivers failed");
340 if (W_ERROR_IS_OK(r.out.result)) {
341 /* TODO: do some more checks here */
344 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
345 blob = data_blob_talloc(ctx, NULL, needed);
346 data_blob_clear(&blob);
348 r.in.offered = needed;
350 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
351 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
354 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
356 /* don't do cross-architecture comparison */
357 if (strequal(r.in.environment, SPOOLSS_ARCHITECTURE_ALL)) {
361 ctx->driver_count[level] = count;
362 ctx->drivers[level] = info;
366 for (i=1;i<ARRAY_SIZE(levels);i++) {
367 int level = levels[i];
368 int old_level = levels[i-1];
370 /* don't do cross-architecture comparison */
371 if (strequal(r.in.environment, SPOOLSS_ARCHITECTURE_ALL)) {
375 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
376 "EnumPrinterDrivers invalid value");
379 for (i=0;i<ARRAY_SIZE(levels);i++) {
380 int level = levels[i];
382 /* don't do cross-architecture comparison */
383 if (strequal(r.in.environment, SPOOLSS_ARCHITECTURE_ALL)) {
387 for (j=0;j<ctx->driver_count[level];j++) {
388 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
389 union spoolss_DriverInfo *ref = &ctx->drivers[6][j];
392 COMPARE_STRING(tctx, cur->info1, ref->info6, driver_name);
395 COMPARE_UINT32(tctx, cur->info2, ref->info6, version);
396 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_name);
397 COMPARE_STRING(tctx, cur->info2, ref->info6, architecture);
398 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_path);
399 COMPARE_STRING(tctx, cur->info2, ref->info6, data_file);
400 COMPARE_STRING(tctx, cur->info2, ref->info6, config_file);
403 COMPARE_UINT32(tctx, cur->info3, ref->info6, version);
404 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_name);
405 COMPARE_STRING(tctx, cur->info3, ref->info6, architecture);
406 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_path);
407 COMPARE_STRING(tctx, cur->info3, ref->info6, data_file);
408 COMPARE_STRING(tctx, cur->info3, ref->info6, config_file);
409 COMPARE_STRING(tctx, cur->info3, ref->info6, help_file);
410 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info6, dependent_files);
411 COMPARE_STRING(tctx, cur->info3, ref->info6, monitor_name);
412 COMPARE_STRING(tctx, cur->info3, ref->info6, default_datatype);
415 COMPARE_UINT32(tctx, cur->info4, ref->info6, version);
416 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_name);
417 COMPARE_STRING(tctx, cur->info4, ref->info6, architecture);
418 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_path);
419 COMPARE_STRING(tctx, cur->info4, ref->info6, data_file);
420 COMPARE_STRING(tctx, cur->info4, ref->info6, config_file);
421 COMPARE_STRING(tctx, cur->info4, ref->info6, help_file);
422 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, dependent_files);
423 COMPARE_STRING(tctx, cur->info4, ref->info6, monitor_name);
424 COMPARE_STRING(tctx, cur->info4, ref->info6, default_datatype);
425 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, previous_names);
428 COMPARE_UINT32(tctx, cur->info5, ref->info6, version);
429 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_name);
430 COMPARE_STRING(tctx, cur->info5, ref->info6, architecture);
431 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_path);
432 COMPARE_STRING(tctx, cur->info5, ref->info6, data_file);
433 COMPARE_STRING(tctx, cur->info5, ref->info6, config_file);
434 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_attributes);*/
435 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, config_version);*/
436 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_version); */
439 /* level 6 is our reference, and it makes no sense to compare it to itself */
448 static bool test_EnumMonitors(struct torture_context *tctx,
449 struct dcerpc_pipe *p,
450 struct test_spoolss_context *ctx)
453 struct spoolss_EnumMonitors r;
454 uint16_t levels[] = { 1, 2 };
457 for (i=0;i<ARRAY_SIZE(levels);i++) {
458 int level = levels[i];
462 union spoolss_MonitorInfo *info;
464 r.in.servername = "";
468 r.out.needed = &needed;
469 r.out.count = &count;
472 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
474 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
475 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
476 if (W_ERROR_IS_OK(r.out.result)) {
477 /* TODO: do some more checks here */
480 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
481 "EnumMonitors failed");
483 blob = data_blob_talloc(ctx, NULL, needed);
484 data_blob_clear(&blob);
486 r.in.offered = needed;
488 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
489 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
491 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
493 ctx->monitor_count[level] = count;
494 ctx->monitors[level] = info;
497 for (i=1;i<ARRAY_SIZE(levels);i++) {
498 int level = levels[i];
499 int old_level = levels[i-1];
500 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
501 "EnumMonitors invalid value");
504 for (i=0;i<ARRAY_SIZE(levels);i++) {
505 int level = levels[i];
506 for (j=0;j<ctx->monitor_count[level];j++) {
507 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
508 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
511 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
514 /* level 2 is our reference, and it makes no sense to compare it to itself */
523 static bool test_EnumPrintProcessors(struct torture_context *tctx,
524 struct dcerpc_pipe *p,
525 struct test_spoolss_context *ctx)
528 struct spoolss_EnumPrintProcessors r;
529 uint16_t levels[] = { 1 };
532 for (i=0;i<ARRAY_SIZE(levels);i++) {
533 int level = levels[i];
537 union spoolss_PrintProcessorInfo *info;
539 r.in.servername = "";
540 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
544 r.out.needed = &needed;
545 r.out.count = &count;
548 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
550 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
551 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
552 if (W_ERROR_IS_OK(r.out.result)) {
553 /* TODO: do some more checks here */
556 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
557 "EnumPrintProcessors unexpected return code");
559 blob = data_blob_talloc(ctx, NULL, needed);
560 data_blob_clear(&blob);
562 r.in.offered = needed;
564 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
565 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
567 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
569 ctx->print_processor_count[level] = count;
570 ctx->print_processors[level] = info;
573 for (i=1;i<ARRAY_SIZE(levels);i++) {
574 int level = levels[i];
575 int old_level = levels[i-1];
576 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
577 "EnumPrintProcessors failed");
580 for (i=0;i<ARRAY_SIZE(levels);i++) {
581 int level = levels[i];
582 for (j=0;j<ctx->print_processor_count[level];j++) {
584 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
585 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
589 /* level 1 is our reference, and it makes no sense to compare it to itself */
598 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
599 struct dcerpc_pipe *p,
600 struct test_spoolss_context *ctx)
603 struct spoolss_EnumPrintProcDataTypes r;
604 uint16_t levels[] = { 1 };
607 for (i=0;i<ARRAY_SIZE(levels);i++) {
608 int level = levels[i];
612 union spoolss_PrintProcDataTypesInfo *info;
614 r.in.servername = "";
615 r.in.print_processor_name = "winprint";
619 r.out.needed = &needed;
620 r.out.count = &count;
623 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
625 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
626 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
627 if (W_ERROR_IS_OK(r.out.result)) {
628 /* TODO: do some more checks here */
631 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
632 "EnumPrintProcDataTypes unexpected return code");
634 blob = data_blob_talloc(ctx, NULL, needed);
635 data_blob_clear(&blob);
637 r.in.offered = needed;
639 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
640 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
642 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
649 static bool test_EnumPrinters(struct torture_context *tctx,
650 struct dcerpc_pipe *p,
651 struct test_spoolss_context *ctx)
653 struct spoolss_EnumPrinters r;
655 uint16_t levels[] = { 0, 1, 2, 4, 5 };
658 for (i=0;i<ARRAY_SIZE(levels);i++) {
659 int level = levels[i];
663 union spoolss_PrinterInfo *info;
665 r.in.flags = PRINTER_ENUM_LOCAL;
670 r.out.needed = &needed;
671 r.out.count = &count;
674 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
676 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
677 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
678 if (W_ERROR_IS_OK(r.out.result)) {
679 /* TODO: do some more checks here */
682 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
683 "EnumPrinters unexpected return code");
685 blob = data_blob_talloc(ctx, NULL, needed);
686 data_blob_clear(&blob);
688 r.in.offered = needed;
690 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
691 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
693 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
695 ctx->printer_count[level] = count;
696 ctx->printers[level] = info;
699 for (i=1;i<ARRAY_SIZE(levels);i++) {
700 int level = levels[i];
701 int old_level = levels[i-1];
702 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
703 "EnumPrinters invalid value");
706 for (i=0;i<ARRAY_SIZE(levels);i++) {
707 int level = levels[i];
708 for (j=0;j<ctx->printer_count[level];j++) {
709 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
710 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
713 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
714 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
715 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
716 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
717 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
718 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
719 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
720 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
721 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
722 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
723 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
724 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
725 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
726 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
727 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
728 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
729 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
730 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
731 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
732 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
733 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
734 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
735 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
736 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
737 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
738 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
739 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
740 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
741 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
744 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
745 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
746 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
747 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
750 /* level 2 is our reference, and it makes no sense to compare it to itself */
753 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
754 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
755 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
758 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
759 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
760 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
761 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
762 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
769 * - verify that the port of a printer was in the list returned by EnumPorts
775 static bool test_GetPrinter(struct torture_context *tctx,
776 struct dcerpc_pipe *p,
777 struct policy_handle *handle)
780 struct spoolss_GetPrinter r;
781 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
785 for (i=0;i<ARRAY_SIZE(levels);i++) {
786 r.in.handle = handle;
787 r.in.level = levels[i];
790 r.out.needed = &needed;
792 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
794 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
795 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
797 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
798 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
799 data_blob_clear(&blob);
801 r.in.offered = needed;
802 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
805 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
807 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
814 static bool test_ClosePrinter(struct torture_context *tctx,
815 struct dcerpc_pipe *p,
816 struct policy_handle *handle)
819 struct spoolss_ClosePrinter r;
821 r.in.handle = handle;
822 r.out.handle = handle;
824 torture_comment(tctx, "Testing ClosePrinter\n");
826 status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
827 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
832 static bool test_GetForm(struct torture_context *tctx,
833 struct dcerpc_pipe *p,
834 struct policy_handle *handle,
835 const char *form_name,
839 struct spoolss_GetForm r;
842 r.in.handle = handle;
843 r.in.form_name = form_name;
847 r.out.needed = &needed;
849 torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
851 status = dcerpc_spoolss_GetForm(p, tctx, &r);
852 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
854 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
855 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
856 data_blob_clear(&blob);
858 r.in.offered = needed;
859 status = dcerpc_spoolss_GetForm(p, tctx, &r);
860 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
862 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
864 torture_assert(tctx, r.out.info, "No form info returned");
867 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
872 static bool test_EnumForms(struct torture_context *tctx,
873 struct dcerpc_pipe *p,
874 struct policy_handle *handle, bool print_server)
877 struct spoolss_EnumForms r;
881 uint32_t levels[] = { 1, 2 };
884 for (i=0; i<ARRAY_SIZE(levels); i++) {
886 union spoolss_FormInfo *info;
888 r.in.handle = handle;
889 r.in.level = levels[i];
892 r.out.needed = &needed;
893 r.out.count = &count;
896 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
898 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
899 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
901 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
905 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
906 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
908 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
910 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
911 data_blob_clear(&blob);
913 r.in.offered = needed;
915 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
917 torture_assert(tctx, info, "No forms returned");
919 for (j = 0; j < count; j++) {
921 ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
925 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
927 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
933 static bool test_DeleteForm(struct torture_context *tctx,
934 struct dcerpc_pipe *p,
935 struct policy_handle *handle,
936 const char *form_name)
939 struct spoolss_DeleteForm r;
941 r.in.handle = handle;
942 r.in.form_name = form_name;
944 status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
946 torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
948 torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
953 static bool test_AddForm(struct torture_context *tctx,
954 struct dcerpc_pipe *p,
955 struct policy_handle *handle, bool print_server)
957 struct spoolss_AddForm r;
958 struct spoolss_AddFormInfo1 addform;
959 const char *form_name = "testform3";
963 r.in.handle = handle;
965 r.in.info.info1 = &addform;
966 addform.flags = SPOOLSS_FORM_USER;
967 addform.form_name = form_name;
968 addform.size.width = 50;
969 addform.size.height = 25;
970 addform.area.left = 5;
971 addform.area.top = 10;
972 addform.area.right = 45;
973 addform.area.bottom = 15;
975 status = dcerpc_spoolss_AddForm(p, tctx, &r);
977 torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
979 torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
981 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
984 struct spoolss_SetForm sf;
985 struct spoolss_AddFormInfo1 setform;
987 sf.in.handle = handle;
988 sf.in.form_name = form_name;
990 sf.in.info.info1= &setform;
991 setform.flags = addform.flags;
992 setform.form_name = addform.form_name;
993 setform.size = addform.size;
994 setform.area = addform.area;
996 setform.size.width = 1234;
998 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
1000 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
1002 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
1005 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1008 struct spoolss_EnumForms e;
1009 union spoolss_FormInfo *info;
1014 e.in.handle = handle;
1018 e.out.needed = &needed;
1019 e.out.count = &count;
1022 torture_comment(tctx, "Testing EnumForms level 1\n");
1024 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1025 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1027 if (print_server && W_ERROR_EQUAL(e.out.result, WERR_BADFID))
1028 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1030 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
1032 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1033 data_blob_clear(&blob);
1034 e.in.buffer = &blob;
1035 e.in.offered = needed;
1037 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1039 torture_assert(tctx, info, "No forms returned");
1041 for (j = 0; j < count; j++) {
1042 if (strequal(form_name, info[j].info1.form_name)) {
1048 torture_assert(tctx, found, "Newly added form not found in enum call");
1051 if (!test_DeleteForm(tctx, p, handle, form_name)) {
1058 static bool test_EnumPorts_old(struct torture_context *tctx,
1059 struct dcerpc_pipe *p)
1062 struct spoolss_EnumPorts r;
1065 union spoolss_PortInfo *info;
1067 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
1068 dcerpc_server_name(p));
1072 r.out.needed = &needed;
1073 r.out.count = &count;
1076 torture_comment(tctx, "Testing EnumPorts\n");
1078 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1080 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1082 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1083 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1084 data_blob_clear(&blob);
1085 r.in.buffer = &blob;
1086 r.in.offered = needed;
1088 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1089 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1091 torture_assert(tctx, info, "No ports returned");
1097 static bool test_AddPort(struct torture_context *tctx,
1098 struct dcerpc_pipe *p)
1101 struct spoolss_AddPort r;
1103 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
1104 dcerpc_server_name(p));
1106 r.in.monitor_name = "foo";
1108 torture_comment(tctx, "Testing AddPort\n");
1110 status = dcerpc_spoolss_AddPort(p, tctx, &r);
1112 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
1114 /* win2k3 returns WERR_NOT_SUPPORTED */
1118 if (!W_ERROR_IS_OK(r.out.result)) {
1119 printf("AddPort failed - %s\n", win_errstr(r.out.result));
1128 static bool test_GetJob(struct torture_context *tctx,
1129 struct dcerpc_pipe *p,
1130 struct policy_handle *handle, uint32_t job_id)
1133 struct spoolss_GetJob r;
1134 union spoolss_JobInfo info;
1136 uint32_t levels[] = {1, 2 /* 3, 4 */};
1139 r.in.handle = handle;
1140 r.in.job_id = job_id;
1144 r.out.needed = &needed;
1147 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1149 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1150 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
1152 for (i = 0; i < ARRAY_SIZE(levels); i++) {
1154 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1158 r.in.level = levels[i];
1162 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1163 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1165 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1166 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1167 data_blob_clear(&blob);
1168 r.in.buffer = &blob;
1169 r.in.offered = needed;
1171 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1172 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1175 torture_assert(tctx, r.out.info, "No job info returned");
1176 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
1182 static bool test_SetJob(struct torture_context *tctx,
1183 struct dcerpc_pipe *p,
1184 struct policy_handle *handle, uint32_t job_id,
1185 enum spoolss_JobControl command)
1188 struct spoolss_SetJob r;
1190 r.in.handle = handle;
1191 r.in.job_id = job_id;
1193 r.in.command = command;
1196 case SPOOLSS_JOB_CONTROL_PAUSE:
1197 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1199 case SPOOLSS_JOB_CONTROL_RESUME:
1200 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1202 case SPOOLSS_JOB_CONTROL_CANCEL:
1203 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1205 case SPOOLSS_JOB_CONTROL_RESTART:
1206 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1208 case SPOOLSS_JOB_CONTROL_DELETE:
1209 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1211 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
1212 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1214 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
1215 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1217 case SPOOLSS_JOB_CONTROL_RETAIN:
1218 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1220 case SPOOLSS_JOB_CONTROL_RELEASE:
1221 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1224 torture_comment(tctx, "Testing SetJob\n");
1228 status = dcerpc_spoolss_SetJob(p, tctx, &r);
1229 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
1230 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
1235 static bool test_AddJob(struct torture_context *tctx,
1236 struct dcerpc_pipe *p,
1237 struct policy_handle *handle)
1240 struct spoolss_AddJob r;
1244 r.in.handle = handle;
1246 r.out.needed = &needed;
1247 r.in.buffer = r.out.buffer = NULL;
1249 torture_comment(tctx, "Testing AddJob\n");
1251 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1252 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
1256 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1257 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
1263 static bool test_EnumJobs(struct torture_context *tctx,
1264 struct dcerpc_pipe *p,
1265 struct policy_handle *handle)
1268 struct spoolss_EnumJobs r;
1271 union spoolss_JobInfo *info;
1273 r.in.handle = handle;
1275 r.in.numjobs = 0xffffffff;
1279 r.out.needed = &needed;
1280 r.out.count = &count;
1283 torture_comment(tctx, "Testing EnumJobs\n");
1285 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1287 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1289 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1291 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1292 data_blob_clear(&blob);
1293 r.in.buffer = &blob;
1294 r.in.offered = needed;
1296 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1298 torture_assert(tctx, info, "No jobs returned");
1300 for (j = 0; j < count; j++) {
1302 test_GetJob(tctx, p, handle, info[j].info1.job_id);
1305 if (!torture_setting_bool(tctx, "samba3", false)) {
1306 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
1307 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
1312 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1318 static bool test_DoPrintTest(struct torture_context *tctx,
1319 struct dcerpc_pipe *p,
1320 struct policy_handle *handle)
1324 struct spoolss_StartDocPrinter s;
1325 struct spoolss_DocumentInfo1 info1;
1326 struct spoolss_StartPagePrinter sp;
1327 struct spoolss_WritePrinter w;
1328 struct spoolss_EndPagePrinter ep;
1329 struct spoolss_EndDocPrinter e;
1332 uint32_t num_written;
1334 torture_comment(tctx, "Testing StartDocPrinter\n");
1336 s.in.handle = handle;
1338 s.in.info.info1 = &info1;
1339 s.out.job_id = &job_id;
1340 info1.document_name = "TorturePrintJob";
1341 info1.output_file = NULL;
1342 info1.datatype = "RAW";
1344 status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
1345 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
1346 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
1348 for (i=1; i < 4; i++) {
1349 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
1351 sp.in.handle = handle;
1353 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
1354 torture_assert_ntstatus_ok(tctx, status,
1355 "dcerpc_spoolss_StartPagePrinter failed");
1356 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
1358 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
1360 w.in.handle = handle;
1361 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
1362 w.out.num_written = &num_written;
1364 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
1365 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
1366 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
1368 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
1370 ep.in.handle = handle;
1372 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
1373 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
1374 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
1377 torture_comment(tctx, "Testing EndDocPrinter\n");
1379 e.in.handle = handle;
1381 status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
1382 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
1383 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
1385 ret &= test_AddJob(tctx, p, handle);
1386 ret &= test_EnumJobs(tctx, p, handle);
1388 ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
1393 static bool test_PausePrinter(struct torture_context *tctx,
1394 struct dcerpc_pipe *p,
1395 struct policy_handle *handle)
1398 struct spoolss_SetPrinter r;
1399 struct spoolss_SetPrinterInfoCtr info_ctr;
1400 struct spoolss_DevmodeContainer devmode_ctr;
1401 struct sec_desc_buf secdesc_ctr;
1404 info_ctr.info.info0 = NULL;
1406 ZERO_STRUCT(devmode_ctr);
1407 ZERO_STRUCT(secdesc_ctr);
1409 r.in.handle = handle;
1410 r.in.info_ctr = &info_ctr;
1411 r.in.devmode_ctr = &devmode_ctr;
1412 r.in.secdesc_ctr = &secdesc_ctr;
1413 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
1415 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1417 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1419 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1421 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1426 static bool test_ResumePrinter(struct torture_context *tctx,
1427 struct dcerpc_pipe *p,
1428 struct policy_handle *handle)
1431 struct spoolss_SetPrinter r;
1432 struct spoolss_SetPrinterInfoCtr info_ctr;
1433 struct spoolss_DevmodeContainer devmode_ctr;
1434 struct sec_desc_buf secdesc_ctr;
1437 info_ctr.info.info0 = NULL;
1439 ZERO_STRUCT(devmode_ctr);
1440 ZERO_STRUCT(secdesc_ctr);
1442 r.in.handle = handle;
1443 r.in.info_ctr = &info_ctr;
1444 r.in.devmode_ctr = &devmode_ctr;
1445 r.in.secdesc_ctr = &secdesc_ctr;
1446 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
1448 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
1450 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1452 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1454 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1459 static bool test_GetPrinterData(struct torture_context *tctx,
1460 struct dcerpc_pipe *p,
1461 struct policy_handle *handle,
1462 const char *value_name)
1465 struct spoolss_GetPrinterData r;
1467 enum winreg_Type type;
1468 union spoolss_PrinterData data;
1470 r.in.handle = handle;
1471 r.in.value_name = value_name;
1473 r.out.needed = &needed;
1477 torture_comment(tctx, "Testing GetPrinterData\n");
1479 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
1480 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
1482 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1483 r.in.offered = needed;
1485 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
1486 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
1488 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterData failed");
1494 static bool test_GetPrinterDataEx(struct torture_context *tctx,
1495 struct dcerpc_pipe *p,
1496 struct policy_handle *handle,
1497 const char *key_name,
1498 const char *value_name)
1501 struct spoolss_GetPrinterDataEx r;
1502 enum winreg_Type type;
1505 r.in.handle = handle;
1506 r.in.key_name = key_name;
1507 r.in.value_name = value_name;
1510 r.out.needed = &needed;
1511 r.out.buffer = NULL;
1513 torture_comment(tctx, "Testing GetPrinterDataEx\n");
1515 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
1516 if (!NT_STATUS_IS_OK(status)) {
1517 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
1518 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1519 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
1521 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
1524 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1525 r.in.offered = needed;
1526 r.out.buffer = talloc_array(tctx, uint8_t, needed);
1528 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
1529 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
1531 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDataEx failed");
1537 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
1538 struct policy_handle *handle)
1541 struct spoolss_EnumPrinterData r;
1544 r.in.handle = handle;
1545 r.in.enum_index = 0;
1548 uint32_t value_size = 0;
1549 uint32_t data_size = 0;
1550 enum winreg_Type type = 0;
1552 r.in.value_offered = value_size;
1553 r.out.value_needed = &value_size;
1554 r.in.data_offered = data_size;
1555 r.out.data_needed = &data_size;
1558 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
1560 torture_comment(tctx, "Testing EnumPrinterData\n");
1562 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
1564 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
1566 r.in.value_offered = value_size;
1567 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
1568 r.in.data_offered = data_size;
1569 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
1571 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
1573 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
1575 test_GetPrinterData(tctx, p, handle, r.out.value_name);
1577 test_GetPrinterDataEx(tctx,
1578 p, handle, "PrinterDriverData",
1583 } while (W_ERROR_IS_OK(r.out.result));
1588 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
1589 struct dcerpc_pipe *p,
1590 struct policy_handle *handle)
1593 struct spoolss_EnumPrinterDataEx r;
1594 struct spoolss_PrinterEnumValues *info;
1598 r.in.handle = handle;
1599 r.in.key_name = "PrinterDriverData";
1601 r.out.needed = &needed;
1602 r.out.count = &count;
1605 torture_comment(tctx, "Testing EnumPrinterDataEx\n");
1607 status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
1608 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
1610 r.in.offered = needed;
1612 status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
1614 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
1620 static bool test_DeletePrinterData(struct torture_context *tctx,
1621 struct dcerpc_pipe *p,
1622 struct policy_handle *handle,
1623 const char *value_name)
1626 struct spoolss_DeletePrinterData r;
1628 r.in.handle = handle;
1629 r.in.value_name = value_name;
1631 torture_comment(tctx, "Testing DeletePrinterData\n");
1633 status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
1635 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
1640 static bool test_SetPrinterData(struct torture_context *tctx,
1641 struct dcerpc_pipe *p,
1642 struct policy_handle *handle)
1645 struct spoolss_SetPrinterData r;
1646 const char *value_name = "spottyfoot";
1648 r.in.handle = handle;
1649 r.in.value_name = value_name;
1651 r.in.data.string = "dog";
1653 torture_comment(tctx, "Testing SetPrinterData\n");
1655 status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
1657 torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
1659 if (!test_GetPrinterData(tctx, p, handle, value_name)) {
1663 if (!test_DeletePrinterData(tctx, p, handle, value_name)) {
1670 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
1671 struct dcerpc_pipe *p,
1672 struct policy_handle *handle)
1675 struct dcerpc_binding *b;
1676 struct dcerpc_pipe *p2;
1677 struct spoolss_ClosePrinter cp;
1679 /* only makes sense on SMB */
1680 if (p->conn->transport.transport != NCACN_NP) {
1684 torture_comment(tctx, "testing close on secondary pipe\n");
1686 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
1687 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
1689 status = dcerpc_secondary_connection(p, &p2, b);
1690 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
1692 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
1693 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
1695 cp.in.handle = handle;
1696 cp.out.handle = handle;
1698 status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
1699 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
1700 "ERROR: Allowed close on secondary connection");
1702 torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
1703 "Unexpected fault code");
1710 static bool test_OpenPrinter_badname(struct torture_context *tctx,
1711 struct dcerpc_pipe *p, const char *name)
1714 struct spoolss_OpenPrinter op;
1715 struct spoolss_OpenPrinterEx opEx;
1716 struct policy_handle handle;
1719 op.in.printername = name;
1720 op.in.datatype = NULL;
1721 op.in.devmode_ctr.devmode= NULL;
1722 op.in.access_mask = 0;
1723 op.out.handle = &handle;
1725 torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
1727 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
1728 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
1729 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
1730 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
1731 name, win_errstr(op.out.result));
1734 if (W_ERROR_IS_OK(op.out.result)) {
1735 ret &=test_ClosePrinter(tctx, p, &handle);
1738 opEx.in.printername = name;
1739 opEx.in.datatype = NULL;
1740 opEx.in.devmode_ctr.devmode = NULL;
1741 opEx.in.access_mask = 0;
1743 opEx.in.userlevel.level1 = NULL;
1744 opEx.out.handle = &handle;
1746 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
1748 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
1749 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
1750 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
1751 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
1752 name, win_errstr(opEx.out.result));
1755 if (W_ERROR_IS_OK(opEx.out.result)) {
1756 ret &=test_ClosePrinter(tctx, p, &handle);
1762 static bool test_OpenPrinter(struct torture_context *tctx,
1763 struct dcerpc_pipe *p,
1767 struct spoolss_OpenPrinter r;
1768 struct policy_handle handle;
1771 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
1772 r.in.datatype = NULL;
1773 r.in.devmode_ctr.devmode= NULL;
1774 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1775 r.out.handle = &handle;
1777 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
1779 status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
1781 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
1783 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
1785 if (!test_GetPrinter(tctx, p, &handle)) {
1789 if (!torture_setting_bool(tctx, "samba3", false)) {
1790 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
1795 if (!test_ClosePrinter(tctx, p, &handle)) {
1802 static bool call_OpenPrinterEx(struct torture_context *tctx,
1803 struct dcerpc_pipe *p,
1804 const char *name, struct policy_handle *handle)
1806 struct spoolss_OpenPrinterEx r;
1807 struct spoolss_UserLevel1 userlevel1;
1810 if (name && name[0]) {
1811 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
1812 dcerpc_server_name(p), name);
1814 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
1815 dcerpc_server_name(p));
1818 r.in.datatype = NULL;
1819 r.in.devmode_ctr.devmode= NULL;
1820 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1822 r.in.userlevel.level1 = &userlevel1;
1823 r.out.handle = handle;
1825 userlevel1.size = 1234;
1826 userlevel1.client = "hello";
1827 userlevel1.user = "spottyfoot!";
1828 userlevel1.build = 1;
1829 userlevel1.major = 2;
1830 userlevel1.minor = 3;
1831 userlevel1.processor = 4;
1833 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
1835 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
1837 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
1839 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
1844 static bool test_OpenPrinterEx(struct torture_context *tctx,
1845 struct dcerpc_pipe *p,
1848 struct policy_handle handle;
1851 if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
1855 if (!test_GetPrinter(tctx, p, &handle)) {
1859 if (!test_EnumForms(tctx, p, &handle, false)) {
1863 if (!test_AddForm(tctx, p, &handle, false)) {
1867 if (!test_EnumPrinterData(tctx, p, &handle)) {
1871 if (!test_EnumPrinterDataEx(tctx, p, &handle)) {
1875 if (!test_PausePrinter(tctx, p, &handle)) {
1879 if (!test_DoPrintTest(tctx, p, &handle)) {
1883 if (!test_ResumePrinter(tctx, p, &handle)) {
1887 if (!test_SetPrinterData(tctx, p, &handle)) {
1891 if (!torture_setting_bool(tctx, "samba3", false)) {
1892 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
1897 if (!test_ClosePrinter(tctx, p, &handle)) {
1904 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
1906 struct spoolss_EnumPrinters r;
1908 uint16_t levels[] = {1, 2, 4, 5};
1912 for (i=0;i<ARRAY_SIZE(levels);i++) {
1913 union spoolss_PrinterInfo *info;
1918 r.in.flags = PRINTER_ENUM_LOCAL;
1920 r.in.level = levels[i];
1923 r.out.needed = &needed;
1924 r.out.count = &count;
1927 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1929 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
1930 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
1932 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1933 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1934 data_blob_clear(&blob);
1935 r.in.buffer = &blob;
1936 r.in.offered = needed;
1937 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
1940 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
1942 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1945 torture_comment(tctx, "No printers returned\n");
1949 for (j=0;j<count;j++) {
1950 if (r.in.level == 1) {
1951 char *unc = talloc_strdup(tctx, info[j].info1.name);
1954 if (unc[0] == '\\' && unc[1] == '\\') {
1957 slash = strchr(unc, '\\');
1962 if (!test_OpenPrinter(tctx, p, name)) {
1965 if (!test_OpenPrinterEx(tctx, p, name)) {
1976 static bool test_GetPrinterDriver2(struct dcerpc_pipe *p,
1977 struct policy_handle *handle,
1978 const char *driver_name)
1981 struct spoolss_GetPrinterDriver2 r;
1983 uint32_t server_major_version;
1984 uint32_t server_minor_version;
1986 r.in.handle = handle;
1987 r.in.architecture = "W32X86";
1991 r.in.client_major_version = 0;
1992 r.in.client_minor_version = 0;
1993 r.out.needed = &needed;
1994 r.out.server_major_version = &server_major_version;
1995 r.out.server_minor_version = &server_minor_version;
1997 printf("Testing GetPrinterDriver2\n");
1999 status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
2000 if (!NT_STATUS_IS_OK(status)) {
2001 printf("GetPrinterDriver2 failed - %s\n", nt_errstr(status));
2005 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2006 r.in.offered = needed;
2007 status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
2010 if (!NT_STATUS_IS_OK(status)) {
2011 printf("GetPrinterDriver2 failed - %s\n",
2016 if (!W_ERROR_IS_OK(r.out.result)) {
2017 printf("GetPrinterDriver2 failed - %s\n",
2018 win_errstr(r.out.result));
2026 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
2027 struct dcerpc_pipe *p)
2029 struct spoolss_EnumPrinterDrivers r;
2031 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
2034 for (i=0;i<ARRAY_SIZE(levels);i++) {
2038 union spoolss_DriverInfo *info;
2040 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2041 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
2042 r.in.level = levels[i];
2045 r.out.needed = &needed;
2046 r.out.count = &count;
2049 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
2051 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2053 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2055 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2056 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2057 data_blob_clear(&blob);
2058 r.in.buffer = &blob;
2059 r.in.offered = needed;
2060 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2063 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2065 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
2068 torture_comment(tctx, "No printer drivers returned\n");
2076 bool torture_rpc_spoolss(struct torture_context *torture)
2079 struct dcerpc_pipe *p;
2081 struct test_spoolss_context *ctx;
2083 status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
2084 if (!NT_STATUS_IS_OK(status)) {
2088 ctx = talloc_zero(torture, struct test_spoolss_context);
2090 ret &= test_OpenPrinter_server(torture, p, ctx);
2092 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "W3SvcInstalled");
2093 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "BeepEnabled");
2094 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "EventLog");
2095 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopup");
2096 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopupToComputer");
2097 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MajorVersion");
2098 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MinorVersion");
2099 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DefaultSpoolDirectory");
2100 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "Architecture");
2101 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DsPresent");
2102 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersion");
2103 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersionEx");
2104 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DNSMachineName");
2105 ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
2106 ret &= test_AddForm(torture, p, &ctx->server_handle, true);
2107 ret &= test_EnumPorts(torture, p, ctx);
2108 ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
2109 ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
2110 ret &= test_EnumPrinterDrivers(torture, p, ctx);
2111 ret &= test_EnumMonitors(torture, p, ctx);
2112 ret &= test_EnumPrintProcessors(torture, p, ctx);
2113 ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
2114 ret &= test_EnumPrinters(torture, p, ctx);
2115 ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
2116 ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
2117 ret &= test_OpenPrinter_badname(torture, p, "");
2118 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
2119 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
2120 ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
2121 ret &= test_OpenPrinter_badname(torture, p,
2122 talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
2125 ret &= test_AddPort(torture, p);
2126 ret &= test_EnumPorts_old(torture, p);
2127 ret &= test_EnumPrinters_old(torture, p);
2128 ret &= test_EnumPrinterDrivers_old(torture, p);