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,
79 struct dcerpc_pipe *p,
80 struct policy_handle *server_handle)
83 struct spoolss_OpenPrinter op;
85 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
86 op.in.datatype = NULL;
87 op.in.devmode_ctr.devmode= NULL;
88 op.in.access_mask = 0;
89 op.out.handle = server_handle;
91 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
93 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
94 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
95 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
100 static bool test_EnumPorts(struct torture_context *tctx,
101 struct dcerpc_pipe *p,
102 struct test_spoolss_context *ctx)
105 struct spoolss_EnumPorts r;
106 uint16_t levels[] = { 1, 2 };
109 for (i=0;i<ARRAY_SIZE(levels);i++) {
110 int level = levels[i];
114 union spoolss_PortInfo *info;
116 r.in.servername = "";
120 r.out.needed = &needed;
121 r.out.count = &count;
124 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
126 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
127 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
128 if (W_ERROR_IS_OK(r.out.result)) {
129 /* TODO: do some more checks here */
132 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
133 "EnumPorts unexpected return code");
135 blob = data_blob_talloc(ctx, NULL, needed);
136 data_blob_clear(&blob);
138 r.in.offered = needed;
140 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
141 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
143 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
145 torture_assert(tctx, info, "EnumPorts returned no info");
147 ctx->port_count[level] = count;
148 ctx->ports[level] = info;
151 for (i=1;i<ARRAY_SIZE(levels);i++) {
152 int level = levels[i];
153 int old_level = levels[i-1];
154 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
155 "EnumPorts invalid value");
157 /* if the array sizes are not the same we would maybe segfault in the following code */
159 for (i=0;i<ARRAY_SIZE(levels);i++) {
160 int level = levels[i];
161 for (j=0;j<ctx->port_count[level];j++) {
162 union spoolss_PortInfo *cur = &ctx->ports[level][j];
163 union spoolss_PortInfo *ref = &ctx->ports[2][j];
166 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
169 /* level 2 is our reference, and it makes no sense to compare it to itself */
178 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
179 struct dcerpc_pipe *p,
180 struct test_spoolss_context *ctx)
183 struct spoolss_GetPrintProcessorDirectory r;
198 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
201 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
207 for (i=0;i<ARRAY_SIZE(levels);i++) {
208 int level = levels[i].level;
211 r.in.server = levels[i].server;
212 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
216 r.out.needed = &needed;
218 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
220 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
221 torture_assert_ntstatus_ok(tctx, status,
222 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
223 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
224 "GetPrintProcessorDirectory unexpected return code");
226 blob = data_blob_talloc(ctx, NULL, needed);
227 data_blob_clear(&blob);
229 r.in.offered = needed;
231 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
232 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
234 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
241 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
242 struct dcerpc_pipe *p,
243 struct test_spoolss_context *ctx)
246 struct spoolss_GetPrinterDriverDirectory r;
261 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
264 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
270 for (i=0;i<ARRAY_SIZE(levels);i++) {
271 int level = levels[i].level;
274 r.in.server = levels[i].server;
275 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
279 r.out.needed = &needed;
281 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
283 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
284 torture_assert_ntstatus_ok(tctx, status,
285 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
286 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
287 "GetPrinterDriverDirectory unexpected return code");
289 blob = data_blob_talloc(ctx, NULL, needed);
290 data_blob_clear(&blob);
292 r.in.offered = needed;
294 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
295 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
297 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
303 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
304 struct dcerpc_pipe *p,
305 struct test_spoolss_context *ctx)
308 struct spoolss_EnumPrinterDrivers r;
309 uint16_t levels[] = { 1, 2, 3, 4, 5, 6 };
311 const char *architectures[] = {
312 SPOOLSS_ARCHITECTURE_NT_X86,
313 SPOOLSS_ARCHITECTURE_ALL
316 for (i=0;i<ARRAY_SIZE(levels);i++) {
317 for (a=0;a<ARRAY_SIZE(architectures);a++) {
318 int level = levels[i];
322 union spoolss_DriverInfo *info;
324 /* FIXME: gd, come back and fix "" as server, and handle
325 * priority of returned error codes in torture test and samba 3
328 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
329 r.in.environment = architectures[a];
333 r.out.needed = &needed;
334 r.out.count = &count;
337 torture_comment(tctx, "Testing EnumPrinterDrivers level %u (%s)\n", r.in.level, r.in.environment);
339 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
340 torture_assert_ntstatus_ok(tctx, status,
341 "dcerpc_spoolss_EnumPrinterDrivers failed");
342 if (W_ERROR_IS_OK(r.out.result)) {
343 /* TODO: do some more checks here */
346 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
347 blob = data_blob_talloc(ctx, NULL, needed);
348 data_blob_clear(&blob);
350 r.in.offered = needed;
352 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
353 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
356 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
358 /* don't do cross-architecture comparison */
359 if (strequal(r.in.environment, SPOOLSS_ARCHITECTURE_ALL)) {
363 ctx->driver_count[level] = count;
364 ctx->drivers[level] = info;
368 for (i=1;i<ARRAY_SIZE(levels);i++) {
369 int level = levels[i];
370 int old_level = levels[i-1];
372 /* don't do cross-architecture comparison */
373 if (strequal(r.in.environment, SPOOLSS_ARCHITECTURE_ALL)) {
377 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
378 "EnumPrinterDrivers invalid value");
381 for (i=0;i<ARRAY_SIZE(levels);i++) {
382 int level = levels[i];
384 /* don't do cross-architecture comparison */
385 if (strequal(r.in.environment, SPOOLSS_ARCHITECTURE_ALL)) {
389 for (j=0;j<ctx->driver_count[level];j++) {
390 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
391 union spoolss_DriverInfo *ref = &ctx->drivers[6][j];
394 COMPARE_STRING(tctx, cur->info1, ref->info6, driver_name);
397 COMPARE_UINT32(tctx, cur->info2, ref->info6, version);
398 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_name);
399 COMPARE_STRING(tctx, cur->info2, ref->info6, architecture);
400 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_path);
401 COMPARE_STRING(tctx, cur->info2, ref->info6, data_file);
402 COMPARE_STRING(tctx, cur->info2, ref->info6, config_file);
405 COMPARE_UINT32(tctx, cur->info3, ref->info6, version);
406 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_name);
407 COMPARE_STRING(tctx, cur->info3, ref->info6, architecture);
408 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_path);
409 COMPARE_STRING(tctx, cur->info3, ref->info6, data_file);
410 COMPARE_STRING(tctx, cur->info3, ref->info6, config_file);
411 COMPARE_STRING(tctx, cur->info3, ref->info6, help_file);
412 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info6, dependent_files);
413 COMPARE_STRING(tctx, cur->info3, ref->info6, monitor_name);
414 COMPARE_STRING(tctx, cur->info3, ref->info6, default_datatype);
417 COMPARE_UINT32(tctx, cur->info4, ref->info6, version);
418 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_name);
419 COMPARE_STRING(tctx, cur->info4, ref->info6, architecture);
420 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_path);
421 COMPARE_STRING(tctx, cur->info4, ref->info6, data_file);
422 COMPARE_STRING(tctx, cur->info4, ref->info6, config_file);
423 COMPARE_STRING(tctx, cur->info4, ref->info6, help_file);
424 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, dependent_files);
425 COMPARE_STRING(tctx, cur->info4, ref->info6, monitor_name);
426 COMPARE_STRING(tctx, cur->info4, ref->info6, default_datatype);
427 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, previous_names);
430 COMPARE_UINT32(tctx, cur->info5, ref->info6, version);
431 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_name);
432 COMPARE_STRING(tctx, cur->info5, ref->info6, architecture);
433 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_path);
434 COMPARE_STRING(tctx, cur->info5, ref->info6, data_file);
435 COMPARE_STRING(tctx, cur->info5, ref->info6, config_file);
436 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_attributes);*/
437 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, config_version);*/
438 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_version); */
441 /* level 6 is our reference, and it makes no sense to compare it to itself */
450 static bool test_EnumMonitors(struct torture_context *tctx,
451 struct dcerpc_pipe *p,
452 struct test_spoolss_context *ctx)
455 struct spoolss_EnumMonitors r;
456 uint16_t levels[] = { 1, 2 };
459 for (i=0;i<ARRAY_SIZE(levels);i++) {
460 int level = levels[i];
464 union spoolss_MonitorInfo *info;
466 r.in.servername = "";
470 r.out.needed = &needed;
471 r.out.count = &count;
474 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
476 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
477 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
478 if (W_ERROR_IS_OK(r.out.result)) {
479 /* TODO: do some more checks here */
482 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
483 "EnumMonitors failed");
485 blob = data_blob_talloc(ctx, NULL, needed);
486 data_blob_clear(&blob);
488 r.in.offered = needed;
490 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
491 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
493 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
495 ctx->monitor_count[level] = count;
496 ctx->monitors[level] = info;
499 for (i=1;i<ARRAY_SIZE(levels);i++) {
500 int level = levels[i];
501 int old_level = levels[i-1];
502 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
503 "EnumMonitors invalid value");
506 for (i=0;i<ARRAY_SIZE(levels);i++) {
507 int level = levels[i];
508 for (j=0;j<ctx->monitor_count[level];j++) {
509 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
510 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
513 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
516 /* level 2 is our reference, and it makes no sense to compare it to itself */
525 static bool test_EnumPrintProcessors(struct torture_context *tctx,
526 struct dcerpc_pipe *p,
527 struct test_spoolss_context *ctx)
530 struct spoolss_EnumPrintProcessors r;
531 uint16_t levels[] = { 1 };
534 for (i=0;i<ARRAY_SIZE(levels);i++) {
535 int level = levels[i];
539 union spoolss_PrintProcessorInfo *info;
541 r.in.servername = "";
542 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
546 r.out.needed = &needed;
547 r.out.count = &count;
550 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
552 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
553 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
554 if (W_ERROR_IS_OK(r.out.result)) {
555 /* TODO: do some more checks here */
558 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
559 "EnumPrintProcessors unexpected return code");
561 blob = data_blob_talloc(ctx, NULL, needed);
562 data_blob_clear(&blob);
564 r.in.offered = needed;
566 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
567 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
569 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
571 ctx->print_processor_count[level] = count;
572 ctx->print_processors[level] = info;
575 for (i=1;i<ARRAY_SIZE(levels);i++) {
576 int level = levels[i];
577 int old_level = levels[i-1];
578 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
579 "EnumPrintProcessors failed");
582 for (i=0;i<ARRAY_SIZE(levels);i++) {
583 int level = levels[i];
584 for (j=0;j<ctx->print_processor_count[level];j++) {
586 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
587 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
591 /* level 1 is our reference, and it makes no sense to compare it to itself */
600 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
601 struct dcerpc_pipe *p,
602 struct test_spoolss_context *ctx)
605 struct spoolss_EnumPrintProcDataTypes r;
606 uint16_t levels[] = { 1 };
609 for (i=0;i<ARRAY_SIZE(levels);i++) {
610 int level = levels[i];
614 union spoolss_PrintProcDataTypesInfo *info;
616 r.in.servername = "";
617 r.in.print_processor_name = "winprint";
621 r.out.needed = &needed;
622 r.out.count = &count;
625 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
627 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
628 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
629 if (W_ERROR_IS_OK(r.out.result)) {
630 /* TODO: do some more checks here */
633 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
634 "EnumPrintProcDataTypes unexpected return code");
636 blob = data_blob_talloc(ctx, NULL, needed);
637 data_blob_clear(&blob);
639 r.in.offered = needed;
641 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
642 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
644 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
651 static bool test_EnumPrinters(struct torture_context *tctx,
652 struct dcerpc_pipe *p,
653 struct test_spoolss_context *ctx)
655 struct spoolss_EnumPrinters r;
657 uint16_t levels[] = { 0, 1, 2, 4, 5 };
660 for (i=0;i<ARRAY_SIZE(levels);i++) {
661 int level = levels[i];
665 union spoolss_PrinterInfo *info;
667 r.in.flags = PRINTER_ENUM_LOCAL;
672 r.out.needed = &needed;
673 r.out.count = &count;
676 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
678 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
679 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
680 if (W_ERROR_IS_OK(r.out.result)) {
681 /* TODO: do some more checks here */
684 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
685 "EnumPrinters unexpected return code");
687 blob = data_blob_talloc(ctx, NULL, needed);
688 data_blob_clear(&blob);
690 r.in.offered = needed;
692 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
693 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
695 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
697 ctx->printer_count[level] = count;
698 ctx->printers[level] = info;
701 for (i=1;i<ARRAY_SIZE(levels);i++) {
702 int level = levels[i];
703 int old_level = levels[i-1];
704 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
705 "EnumPrinters invalid value");
708 for (i=0;i<ARRAY_SIZE(levels);i++) {
709 int level = levels[i];
710 for (j=0;j<ctx->printer_count[level];j++) {
711 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
712 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
715 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
716 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
717 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
718 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
719 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
720 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
721 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
722 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
723 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
724 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
725 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
726 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
727 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
728 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
729 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
730 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
731 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
732 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
733 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
734 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
735 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
736 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
737 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
738 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
739 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
740 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
741 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
742 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
743 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
746 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
747 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
748 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
749 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
752 /* level 2 is our reference, and it makes no sense to compare it to itself */
755 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
756 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
757 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
760 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
761 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
762 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
763 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
764 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
771 * - verify that the port of a printer was in the list returned by EnumPorts
777 static bool test_GetPrinter(struct torture_context *tctx,
778 struct dcerpc_pipe *p,
779 struct policy_handle *handle)
782 struct spoolss_GetPrinter r;
783 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
787 for (i=0;i<ARRAY_SIZE(levels);i++) {
788 r.in.handle = handle;
789 r.in.level = levels[i];
792 r.out.needed = &needed;
794 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
796 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
797 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
799 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
800 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
801 data_blob_clear(&blob);
803 r.in.offered = needed;
804 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
807 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
809 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
815 static bool test_SetPrinter_errors(struct torture_context *tctx,
816 struct dcerpc_pipe *p,
817 struct policy_handle *handle)
819 struct spoolss_SetPrinter r;
820 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
823 struct spoolss_SetPrinterInfoCtr info_ctr;
824 struct spoolss_DevmodeContainer devmode_ctr;
825 struct sec_desc_buf secdesc_ctr;
828 info_ctr.info.info0 = NULL;
830 ZERO_STRUCT(devmode_ctr);
831 ZERO_STRUCT(secdesc_ctr);
833 r.in.handle = handle;
834 r.in.info_ctr = &info_ctr;
835 r.in.devmode_ctr = &devmode_ctr;
836 r.in.secdesc_ctr = &secdesc_ctr;
839 torture_comment(tctx, "Testing SetPrinter all zero\n");
841 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
842 "failed to call SetPrinter");
843 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
844 "failed to call SetPrinter");
847 for (i=0; i < ARRAY_SIZE(levels); i++) {
849 struct spoolss_SetPrinterInfo0 info0;
850 struct spoolss_SetPrinterInfo1 info1;
851 struct spoolss_SetPrinterInfo2 info2;
852 struct spoolss_SetPrinterInfo3 info3;
853 struct spoolss_SetPrinterInfo4 info4;
854 struct spoolss_SetPrinterInfo5 info5;
855 struct spoolss_SetPrinterInfo6 info6;
856 struct spoolss_SetPrinterInfo7 info7;
857 struct spoolss_DeviceModeInfo info8;
858 struct spoolss_DeviceModeInfo info9;
861 info_ctr.level = levels[i];
865 info_ctr.info.info0 = &info0;
869 info_ctr.info.info1 = &info1;
873 info_ctr.info.info2 = &info2;
877 info_ctr.info.info3 = &info3;
881 info_ctr.info.info4 = &info4;
885 info_ctr.info.info5 = &info5;
889 info_ctr.info.info6 = &info6;
893 info_ctr.info.info7 = &info7;
897 info_ctr.info.info8 = &info8;
901 info_ctr.info.info9 = &info9;
905 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
906 info_ctr.level, r.in.command);
908 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
909 "failed to call SetPrinter");
911 switch (r.in.command) {
912 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
913 /* is ignored for all levels other then 0 */
914 if (info_ctr.level > 0) {
918 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
919 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
920 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
921 if (info_ctr.level > 0) {
922 /* is invalid for all levels other then 0 */
923 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
924 "unexpected error code returned");
927 torture_assert_werr_ok(tctx, r.out.result,
928 "failed to call SetPrinter with non 0 command");
933 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
934 /* FIXME: gd needs further investigation */
936 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
937 "unexpected error code returned");
941 switch (info_ctr.level) {
943 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
944 "unexpected error code returned");
947 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
948 "unexpected error code returned");
954 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
955 "unexpected error code returned");
958 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
959 "unexpected error code returned");
962 torture_assert_werr_ok(tctx, r.out.result,
963 "failed to call SetPrinter");
968 if (r.in.command < 5) {
976 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
978 if ((r->level == 2) && (r->info.info2)) {
979 r->info.info2->secdesc = NULL;
980 r->info.info2->devmode = NULL;
984 static bool test_PrinterInfo(struct torture_context *tctx,
985 struct dcerpc_pipe *p,
986 struct policy_handle *handle)
989 struct spoolss_SetPrinter s;
990 struct spoolss_GetPrinter q;
991 struct spoolss_GetPrinter q0;
992 struct spoolss_SetPrinterInfoCtr info_ctr;
993 union spoolss_PrinterInfo info;
994 struct spoolss_DevmodeContainer devmode_ctr;
995 struct sec_desc_buf secdesc_ctr;
1000 uint32_t status_list[] = {
1001 /* these do not stick
1002 PRINTER_STATUS_PAUSED,
1003 PRINTER_STATUS_ERROR,
1004 PRINTER_STATUS_PENDING_DELETION, */
1005 PRINTER_STATUS_PAPER_JAM,
1006 PRINTER_STATUS_PAPER_OUT,
1007 PRINTER_STATUS_MANUAL_FEED,
1008 PRINTER_STATUS_PAPER_PROBLEM,
1009 PRINTER_STATUS_OFFLINE,
1010 PRINTER_STATUS_IO_ACTIVE,
1011 PRINTER_STATUS_BUSY,
1012 PRINTER_STATUS_PRINTING,
1013 PRINTER_STATUS_OUTPUT_BIN_FULL,
1014 PRINTER_STATUS_NOT_AVAILABLE,
1015 PRINTER_STATUS_WAITING,
1016 PRINTER_STATUS_PROCESSING,
1017 PRINTER_STATUS_INITIALIZING,
1018 PRINTER_STATUS_WARMING_UP,
1019 PRINTER_STATUS_TONER_LOW,
1020 PRINTER_STATUS_NO_TONER,
1021 PRINTER_STATUS_PAGE_PUNT,
1022 PRINTER_STATUS_USER_INTERVENTION,
1023 PRINTER_STATUS_OUT_OF_MEMORY,
1024 PRINTER_STATUS_DOOR_OPEN,
1025 PRINTER_STATUS_SERVER_UNKNOWN,
1026 PRINTER_STATUS_POWER_SAVE,
1027 /* these do not stick
1036 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1037 uint32_t attribute_list[] = {
1038 PRINTER_ATTRIBUTE_QUEUED,
1039 /* fails with WERR_INVALID_DATATYPE:
1040 PRINTER_ATTRIBUTE_DIRECT, */
1042 PRINTER_ATTRIBUTE_DEFAULT, */
1043 PRINTER_ATTRIBUTE_SHARED,
1045 PRINTER_ATTRIBUTE_NETWORK, */
1046 PRINTER_ATTRIBUTE_HIDDEN,
1047 PRINTER_ATTRIBUTE_LOCAL,
1048 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1049 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1050 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1051 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1053 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1054 /* fails with WERR_INVALID_DATATYPE:
1055 PRINTER_ATTRIBUTE_RAW_ONLY, */
1056 /* these do not stick
1057 PRINTER_ATTRIBUTE_PUBLISHED,
1058 PRINTER_ATTRIBUTE_FAX,
1059 PRINTER_ATTRIBUTE_TS,
1078 ZERO_STRUCT(devmode_ctr);
1079 ZERO_STRUCT(secdesc_ctr);
1081 s.in.handle = handle;
1083 s.in.info_ctr = &info_ctr;
1084 s.in.devmode_ctr = &devmode_ctr;
1085 s.in.secdesc_ctr = &secdesc_ctr;
1087 q.in.handle = handle;
1091 #define TESTGETCALL(call, r) \
1092 r.in.buffer = NULL; \
1094 r.out.needed = &needed; \
1095 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1096 if (!NT_STATUS_IS_OK(status)) { \
1097 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1098 r.in.level, nt_errstr(status), __location__); \
1102 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1103 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1104 data_blob_clear(&blob); \
1105 r.in.buffer = &blob; \
1106 r.in.offered = needed; \
1108 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1109 if (!NT_STATUS_IS_OK(status)) { \
1110 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1111 r.in.level, nt_errstr(status), __location__); \
1115 if (!W_ERROR_IS_OK(r.out.result)) { \
1116 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1117 r.in.level, win_errstr(r.out.result), __location__); \
1123 #define TESTSETCALL_EXP(call, r, err) \
1124 clear_info2(&info_ctr);\
1125 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1126 if (!NT_STATUS_IS_OK(status)) { \
1127 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1128 r.in.info_ctr->level, nt_errstr(status), __location__); \
1132 if (!W_ERROR_IS_OK(err)) { \
1133 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1134 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1135 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1140 if (!W_ERROR_IS_OK(r.out.result)) { \
1141 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1142 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1147 #define TESTSETCALL(call, r) \
1148 TESTSETCALL_EXP(call, r, WERR_OK)
1150 #define STRING_EQUAL(s1, s2, field) \
1151 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1152 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1153 #field, s2, __location__); \
1158 #define MEM_EQUAL(s1, s2, length, field) \
1159 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1160 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1161 #field, (const char *)s2, __location__); \
1166 #define INT_EQUAL(i1, i2, field) \
1168 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1169 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1174 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1175 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1176 q.in.level = lvl1; \
1177 TESTGETCALL(GetPrinter, q) \
1178 info_ctr.level = lvl1; \
1179 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1180 info_ctr.info.info ## lvl1->field1 = value;\
1181 TESTSETCALL_EXP(SetPrinter, s, err) \
1182 info_ctr.info.info ## lvl1->field1 = ""; \
1183 TESTGETCALL(GetPrinter, q) \
1184 info_ctr.info.info ## lvl1->field1 = value; \
1185 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1186 q.in.level = lvl2; \
1187 TESTGETCALL(GetPrinter, q) \
1188 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1189 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1192 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1193 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1196 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1197 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1198 q.in.level = lvl1; \
1199 TESTGETCALL(GetPrinter, q) \
1200 info_ctr.level = lvl1; \
1201 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1202 info_ctr.info.info ## lvl1->field1 = value; \
1203 TESTSETCALL(SetPrinter, s) \
1204 info_ctr.info.info ## lvl1->field1 = 0; \
1205 TESTGETCALL(GetPrinter, q) \
1206 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1207 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1208 q.in.level = lvl2; \
1209 TESTGETCALL(GetPrinter, q) \
1210 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1211 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1214 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1215 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1219 do { TESTGETCALL(GetPrinter, q0) } while (0);
1221 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1222 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1224 /* level 0 printername does not stick */
1225 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1226 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1227 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1228 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1229 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1230 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1231 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1232 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1233 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1234 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1235 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1236 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1237 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1238 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1239 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1241 /* servername can be set but does not stick
1242 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1243 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1244 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1247 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1248 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1249 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1250 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1251 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1253 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1254 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1255 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1256 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1257 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1258 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1259 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1260 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1261 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1262 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1264 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1265 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1267 (attribute_list[i] | default_attribute)
1269 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1271 (attribute_list[i] | default_attribute)
1273 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1275 (attribute_list[i] | default_attribute)
1277 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1279 (attribute_list[i] | default_attribute)
1281 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1283 (attribute_list[i] | default_attribute)
1285 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1287 (attribute_list[i] | default_attribute)
1289 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1291 (attribute_list[i] | default_attribute)
1293 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1295 (attribute_list[i] | default_attribute)
1297 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1299 (attribute_list[i] | default_attribute)
1301 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1303 (attribute_list[i] | default_attribute)
1305 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1307 (attribute_list[i] | default_attribute)
1309 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1311 (attribute_list[i] | default_attribute)
1315 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1316 /* level 2 sets do not stick
1317 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1318 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1319 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1320 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1321 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1322 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1325 /* priorities need to be between 0 and 99
1326 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1327 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1328 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1329 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1330 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1331 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1332 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1333 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1334 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1336 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1337 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1340 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1341 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1344 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1345 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1347 /* FIXME: gd also test devmode and secdesc behavior */
1350 /* verify composition of level 1 description field */
1351 const char *description;
1355 do { TESTGETCALL(GetPrinter, q0) } while (0);
1357 description = talloc_strdup(tctx, q0.out.info->info1.description);
1360 do { TESTGETCALL(GetPrinter, q0) } while (0);
1362 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1363 q0.out.info->info2.printername,
1364 q0.out.info->info2.drivername,
1365 q0.out.info->info2.location);
1367 do { STRING_EQUAL(description, tmp, "description")} while (0);
1374 static bool test_ClosePrinter(struct torture_context *tctx,
1375 struct dcerpc_pipe *p,
1376 struct policy_handle *handle)
1379 struct spoolss_ClosePrinter r;
1381 r.in.handle = handle;
1382 r.out.handle = handle;
1384 torture_comment(tctx, "Testing ClosePrinter\n");
1386 status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
1387 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
1392 static bool test_GetForm(struct torture_context *tctx,
1393 struct dcerpc_pipe *p,
1394 struct policy_handle *handle,
1395 const char *form_name,
1399 struct spoolss_GetForm r;
1402 r.in.handle = handle;
1403 r.in.form_name = form_name;
1407 r.out.needed = &needed;
1409 torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
1411 status = dcerpc_spoolss_GetForm(p, tctx, &r);
1412 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1414 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1415 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1416 data_blob_clear(&blob);
1417 r.in.buffer = &blob;
1418 r.in.offered = needed;
1419 status = dcerpc_spoolss_GetForm(p, tctx, &r);
1420 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1422 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1424 torture_assert(tctx, r.out.info, "No form info returned");
1427 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1432 static bool test_EnumForms(struct torture_context *tctx,
1433 struct dcerpc_pipe *p,
1434 struct policy_handle *handle, bool print_server)
1437 struct spoolss_EnumForms r;
1441 uint32_t levels[] = { 1, 2 };
1444 for (i=0; i<ARRAY_SIZE(levels); i++) {
1446 union spoolss_FormInfo *info;
1448 r.in.handle = handle;
1449 r.in.level = levels[i];
1452 r.out.needed = &needed;
1453 r.out.count = &count;
1456 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
1458 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1459 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1461 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
1465 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
1466 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1468 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1470 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1471 data_blob_clear(&blob);
1472 r.in.buffer = &blob;
1473 r.in.offered = needed;
1475 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1477 torture_assert(tctx, info, "No forms returned");
1479 for (j = 0; j < count; j++) {
1481 ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
1485 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1487 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
1493 static bool test_DeleteForm(struct torture_context *tctx,
1494 struct dcerpc_pipe *p,
1495 struct policy_handle *handle,
1496 const char *form_name)
1499 struct spoolss_DeleteForm r;
1501 r.in.handle = handle;
1502 r.in.form_name = form_name;
1504 status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
1506 torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
1508 torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
1513 static bool test_AddForm(struct torture_context *tctx,
1514 struct dcerpc_pipe *p,
1515 struct policy_handle *handle, bool print_server)
1517 struct spoolss_AddForm r;
1518 struct spoolss_AddFormInfo1 addform;
1519 const char *form_name = "testform3";
1523 r.in.handle = handle;
1525 r.in.info.info1 = &addform;
1526 addform.flags = SPOOLSS_FORM_USER;
1527 addform.form_name = form_name;
1528 addform.size.width = 50;
1529 addform.size.height = 25;
1530 addform.area.left = 5;
1531 addform.area.top = 10;
1532 addform.area.right = 45;
1533 addform.area.bottom = 15;
1535 status = dcerpc_spoolss_AddForm(p, tctx, &r);
1537 torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
1539 torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
1541 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1544 struct spoolss_SetForm sf;
1545 struct spoolss_AddFormInfo1 setform;
1547 sf.in.handle = handle;
1548 sf.in.form_name = form_name;
1550 sf.in.info.info1= &setform;
1551 setform.flags = addform.flags;
1552 setform.form_name = addform.form_name;
1553 setform.size = addform.size;
1554 setform.area = addform.area;
1556 setform.size.width = 1234;
1558 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
1560 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
1562 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
1565 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1568 struct spoolss_EnumForms e;
1569 union spoolss_FormInfo *info;
1574 e.in.handle = handle;
1578 e.out.needed = &needed;
1579 e.out.count = &count;
1582 torture_comment(tctx, "Testing EnumForms level 1\n");
1584 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1585 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1587 if (print_server && W_ERROR_EQUAL(e.out.result, WERR_BADFID))
1588 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1590 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
1592 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1593 data_blob_clear(&blob);
1594 e.in.buffer = &blob;
1595 e.in.offered = needed;
1597 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1599 torture_assert(tctx, info, "No forms returned");
1601 for (j = 0; j < count; j++) {
1602 if (strequal(form_name, info[j].info1.form_name)) {
1608 torture_assert(tctx, found, "Newly added form not found in enum call");
1611 if (!test_DeleteForm(tctx, p, handle, form_name)) {
1618 static bool test_EnumPorts_old(struct torture_context *tctx,
1619 struct dcerpc_pipe *p)
1622 struct spoolss_EnumPorts r;
1625 union spoolss_PortInfo *info;
1627 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
1628 dcerpc_server_name(p));
1632 r.out.needed = &needed;
1633 r.out.count = &count;
1636 torture_comment(tctx, "Testing EnumPorts\n");
1638 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1640 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1642 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1643 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1644 data_blob_clear(&blob);
1645 r.in.buffer = &blob;
1646 r.in.offered = needed;
1648 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1649 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1651 torture_assert(tctx, info, "No ports returned");
1657 static bool test_AddPort(struct torture_context *tctx,
1658 struct dcerpc_pipe *p)
1661 struct spoolss_AddPort r;
1663 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
1664 dcerpc_server_name(p));
1666 r.in.monitor_name = "foo";
1668 torture_comment(tctx, "Testing AddPort\n");
1670 status = dcerpc_spoolss_AddPort(p, tctx, &r);
1672 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
1674 /* win2k3 returns WERR_NOT_SUPPORTED */
1678 if (!W_ERROR_IS_OK(r.out.result)) {
1679 printf("AddPort failed - %s\n", win_errstr(r.out.result));
1688 static bool test_GetJob(struct torture_context *tctx,
1689 struct dcerpc_pipe *p,
1690 struct policy_handle *handle, uint32_t job_id)
1693 struct spoolss_GetJob r;
1694 union spoolss_JobInfo info;
1696 uint32_t levels[] = {1, 2 /* 3, 4 */};
1699 r.in.handle = handle;
1700 r.in.job_id = job_id;
1704 r.out.needed = &needed;
1707 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1709 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1710 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
1712 for (i = 0; i < ARRAY_SIZE(levels); i++) {
1714 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1718 r.in.level = levels[i];
1722 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1723 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1725 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1726 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1727 data_blob_clear(&blob);
1728 r.in.buffer = &blob;
1729 r.in.offered = needed;
1731 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1732 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1735 torture_assert(tctx, r.out.info, "No job info returned");
1736 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
1742 static bool test_SetJob(struct torture_context *tctx,
1743 struct dcerpc_pipe *p,
1744 struct policy_handle *handle, uint32_t job_id,
1745 enum spoolss_JobControl command)
1748 struct spoolss_SetJob r;
1750 r.in.handle = handle;
1751 r.in.job_id = job_id;
1753 r.in.command = command;
1756 case SPOOLSS_JOB_CONTROL_PAUSE:
1757 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1759 case SPOOLSS_JOB_CONTROL_RESUME:
1760 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1762 case SPOOLSS_JOB_CONTROL_CANCEL:
1763 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1765 case SPOOLSS_JOB_CONTROL_RESTART:
1766 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1768 case SPOOLSS_JOB_CONTROL_DELETE:
1769 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1771 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
1772 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1774 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
1775 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1777 case SPOOLSS_JOB_CONTROL_RETAIN:
1778 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1780 case SPOOLSS_JOB_CONTROL_RELEASE:
1781 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1784 torture_comment(tctx, "Testing SetJob\n");
1788 status = dcerpc_spoolss_SetJob(p, tctx, &r);
1789 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
1790 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
1795 static bool test_AddJob(struct torture_context *tctx,
1796 struct dcerpc_pipe *p,
1797 struct policy_handle *handle)
1800 struct spoolss_AddJob r;
1804 r.in.handle = handle;
1806 r.out.needed = &needed;
1807 r.in.buffer = r.out.buffer = NULL;
1809 torture_comment(tctx, "Testing AddJob\n");
1811 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1812 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
1816 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1817 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
1823 static bool test_EnumJobs(struct torture_context *tctx,
1824 struct dcerpc_pipe *p,
1825 struct policy_handle *handle)
1828 struct spoolss_EnumJobs r;
1831 union spoolss_JobInfo *info;
1833 r.in.handle = handle;
1835 r.in.numjobs = 0xffffffff;
1839 r.out.needed = &needed;
1840 r.out.count = &count;
1843 torture_comment(tctx, "Testing EnumJobs\n");
1845 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1847 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1849 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1851 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1852 data_blob_clear(&blob);
1853 r.in.buffer = &blob;
1854 r.in.offered = needed;
1856 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1858 torture_assert(tctx, info, "No jobs returned");
1860 for (j = 0; j < count; j++) {
1862 test_GetJob(tctx, p, handle, info[j].info1.job_id);
1865 if (!torture_setting_bool(tctx, "samba3", false)) {
1866 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
1867 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
1872 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1878 static bool test_DoPrintTest(struct torture_context *tctx,
1879 struct dcerpc_pipe *p,
1880 struct policy_handle *handle)
1884 struct spoolss_StartDocPrinter s;
1885 struct spoolss_DocumentInfo1 info1;
1886 struct spoolss_StartPagePrinter sp;
1887 struct spoolss_WritePrinter w;
1888 struct spoolss_EndPagePrinter ep;
1889 struct spoolss_EndDocPrinter e;
1892 uint32_t num_written;
1894 torture_comment(tctx, "Testing StartDocPrinter\n");
1896 s.in.handle = handle;
1898 s.in.info.info1 = &info1;
1899 s.out.job_id = &job_id;
1900 info1.document_name = "TorturePrintJob";
1901 info1.output_file = NULL;
1902 info1.datatype = "RAW";
1904 status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
1905 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
1906 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
1908 for (i=1; i < 4; i++) {
1909 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
1911 sp.in.handle = handle;
1913 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
1914 torture_assert_ntstatus_ok(tctx, status,
1915 "dcerpc_spoolss_StartPagePrinter failed");
1916 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
1918 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
1920 w.in.handle = handle;
1921 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
1922 w.out.num_written = &num_written;
1924 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
1925 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
1926 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
1928 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
1930 ep.in.handle = handle;
1932 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
1933 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
1934 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
1937 torture_comment(tctx, "Testing EndDocPrinter\n");
1939 e.in.handle = handle;
1941 status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
1942 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
1943 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
1945 ret &= test_AddJob(tctx, p, handle);
1946 ret &= test_EnumJobs(tctx, p, handle);
1948 ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
1953 static bool test_PausePrinter(struct torture_context *tctx,
1954 struct dcerpc_pipe *p,
1955 struct policy_handle *handle)
1958 struct spoolss_SetPrinter r;
1959 struct spoolss_SetPrinterInfoCtr info_ctr;
1960 struct spoolss_DevmodeContainer devmode_ctr;
1961 struct sec_desc_buf secdesc_ctr;
1964 info_ctr.info.info0 = NULL;
1966 ZERO_STRUCT(devmode_ctr);
1967 ZERO_STRUCT(secdesc_ctr);
1969 r.in.handle = handle;
1970 r.in.info_ctr = &info_ctr;
1971 r.in.devmode_ctr = &devmode_ctr;
1972 r.in.secdesc_ctr = &secdesc_ctr;
1973 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
1975 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1977 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1979 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1981 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1986 static bool test_ResumePrinter(struct torture_context *tctx,
1987 struct dcerpc_pipe *p,
1988 struct policy_handle *handle)
1991 struct spoolss_SetPrinter r;
1992 struct spoolss_SetPrinterInfoCtr info_ctr;
1993 struct spoolss_DevmodeContainer devmode_ctr;
1994 struct sec_desc_buf secdesc_ctr;
1997 info_ctr.info.info0 = NULL;
1999 ZERO_STRUCT(devmode_ctr);
2000 ZERO_STRUCT(secdesc_ctr);
2002 r.in.handle = handle;
2003 r.in.info_ctr = &info_ctr;
2004 r.in.devmode_ctr = &devmode_ctr;
2005 r.in.secdesc_ctr = &secdesc_ctr;
2006 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
2008 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2010 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2012 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2014 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2019 static bool test_GetPrinterData(struct torture_context *tctx,
2020 struct dcerpc_pipe *p,
2021 struct policy_handle *handle,
2022 const char *value_name)
2025 struct spoolss_GetPrinterData r;
2027 enum winreg_Type type;
2028 union spoolss_PrinterData data;
2030 r.in.handle = handle;
2031 r.in.value_name = value_name;
2033 r.out.needed = &needed;
2037 torture_comment(tctx, "Testing GetPrinterData\n");
2039 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2040 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2042 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2043 r.in.offered = needed;
2045 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2046 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2048 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterData failed");
2054 static bool test_GetPrinterDataEx(struct torture_context *tctx,
2055 struct dcerpc_pipe *p,
2056 struct policy_handle *handle,
2057 const char *key_name,
2058 const char *value_name)
2061 struct spoolss_GetPrinterDataEx r;
2062 enum winreg_Type type;
2065 r.in.handle = handle;
2066 r.in.key_name = key_name;
2067 r.in.value_name = value_name;
2070 r.out.needed = &needed;
2071 r.out.buffer = NULL;
2073 torture_comment(tctx, "Testing GetPrinterDataEx\n");
2075 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2076 if (!NT_STATUS_IS_OK(status)) {
2077 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
2078 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
2079 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
2081 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2084 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2085 r.in.offered = needed;
2086 r.out.buffer = talloc_array(tctx, uint8_t, needed);
2088 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2089 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2091 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDataEx failed");
2097 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
2098 struct policy_handle *handle)
2101 struct spoolss_EnumPrinterData r;
2104 r.in.handle = handle;
2105 r.in.enum_index = 0;
2108 uint32_t value_size = 0;
2109 uint32_t data_size = 0;
2110 enum winreg_Type type = 0;
2112 r.in.value_offered = value_size;
2113 r.out.value_needed = &value_size;
2114 r.in.data_offered = data_size;
2115 r.out.data_needed = &data_size;
2118 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
2120 torture_comment(tctx, "Testing EnumPrinterData\n");
2122 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2124 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2126 r.in.value_offered = value_size;
2127 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
2128 r.in.data_offered = data_size;
2129 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
2131 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2133 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2135 test_GetPrinterData(tctx, p, handle, r.out.value_name);
2137 test_GetPrinterDataEx(tctx,
2138 p, handle, "PrinterDriverData",
2143 } while (W_ERROR_IS_OK(r.out.result));
2148 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
2149 struct dcerpc_pipe *p,
2150 struct policy_handle *handle)
2153 struct spoolss_EnumPrinterDataEx r;
2154 struct spoolss_PrinterEnumValues *info;
2158 r.in.handle = handle;
2159 r.in.key_name = "PrinterDriverData";
2161 r.out.needed = &needed;
2162 r.out.count = &count;
2165 torture_comment(tctx, "Testing EnumPrinterDataEx\n");
2167 status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
2168 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
2170 r.in.offered = needed;
2172 status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
2174 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
2180 static bool test_DeletePrinterData(struct torture_context *tctx,
2181 struct dcerpc_pipe *p,
2182 struct policy_handle *handle,
2183 const char *value_name)
2186 struct spoolss_DeletePrinterData r;
2188 r.in.handle = handle;
2189 r.in.value_name = value_name;
2191 torture_comment(tctx, "Testing DeletePrinterData\n");
2193 status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
2195 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
2200 static bool test_SetPrinterData(struct torture_context *tctx,
2201 struct dcerpc_pipe *p,
2202 struct policy_handle *handle)
2205 struct spoolss_SetPrinterData r;
2206 const char *value_name = "spottyfoot";
2208 r.in.handle = handle;
2209 r.in.value_name = value_name;
2211 r.in.data.string = "dog";
2213 torture_comment(tctx, "Testing SetPrinterData\n");
2215 status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
2217 torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
2219 if (!test_GetPrinterData(tctx, p, handle, value_name)) {
2223 if (!test_DeletePrinterData(tctx, p, handle, value_name)) {
2230 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
2231 struct dcerpc_pipe *p,
2232 struct policy_handle *handle)
2235 struct dcerpc_binding *b;
2236 struct dcerpc_pipe *p2;
2237 struct spoolss_ClosePrinter cp;
2239 /* only makes sense on SMB */
2240 if (p->conn->transport.transport != NCACN_NP) {
2244 torture_comment(tctx, "testing close on secondary pipe\n");
2246 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
2247 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
2249 status = dcerpc_secondary_connection(p, &p2, b);
2250 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
2252 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
2253 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
2255 cp.in.handle = handle;
2256 cp.out.handle = handle;
2258 status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
2259 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
2260 "ERROR: Allowed close on secondary connection");
2262 torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
2263 "Unexpected fault code");
2270 static bool test_OpenPrinter_badname(struct torture_context *tctx,
2271 struct dcerpc_pipe *p, const char *name)
2274 struct spoolss_OpenPrinter op;
2275 struct spoolss_OpenPrinterEx opEx;
2276 struct policy_handle handle;
2279 op.in.printername = name;
2280 op.in.datatype = NULL;
2281 op.in.devmode_ctr.devmode= NULL;
2282 op.in.access_mask = 0;
2283 op.out.handle = &handle;
2285 torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
2287 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
2288 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2289 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
2290 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
2291 name, win_errstr(op.out.result));
2294 if (W_ERROR_IS_OK(op.out.result)) {
2295 ret &=test_ClosePrinter(tctx, p, &handle);
2298 opEx.in.printername = name;
2299 opEx.in.datatype = NULL;
2300 opEx.in.devmode_ctr.devmode = NULL;
2301 opEx.in.access_mask = 0;
2303 opEx.in.userlevel.level1 = NULL;
2304 opEx.out.handle = &handle;
2306 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
2308 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
2309 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2310 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
2311 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
2312 name, win_errstr(opEx.out.result));
2315 if (W_ERROR_IS_OK(opEx.out.result)) {
2316 ret &=test_ClosePrinter(tctx, p, &handle);
2322 static bool test_OpenPrinter(struct torture_context *tctx,
2323 struct dcerpc_pipe *p,
2327 struct spoolss_OpenPrinter r;
2328 struct policy_handle handle;
2331 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
2332 r.in.datatype = NULL;
2333 r.in.devmode_ctr.devmode= NULL;
2334 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2335 r.out.handle = &handle;
2337 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
2339 status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
2341 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2343 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
2345 if (!test_GetPrinter(tctx, p, &handle)) {
2349 if (!torture_setting_bool(tctx, "samba3", false)) {
2350 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2355 if (!test_ClosePrinter(tctx, p, &handle)) {
2362 static bool call_OpenPrinterEx(struct torture_context *tctx,
2363 struct dcerpc_pipe *p,
2364 const char *name, struct policy_handle *handle)
2366 struct spoolss_OpenPrinterEx r;
2367 struct spoolss_UserLevel1 userlevel1;
2370 if (name && name[0]) {
2371 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
2372 dcerpc_server_name(p), name);
2374 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
2375 dcerpc_server_name(p));
2378 r.in.datatype = NULL;
2379 r.in.devmode_ctr.devmode= NULL;
2380 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2382 r.in.userlevel.level1 = &userlevel1;
2383 r.out.handle = handle;
2385 userlevel1.size = 1234;
2386 userlevel1.client = "hello";
2387 userlevel1.user = "spottyfoot!";
2388 userlevel1.build = 1;
2389 userlevel1.major = 2;
2390 userlevel1.minor = 3;
2391 userlevel1.processor = 4;
2393 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
2395 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
2397 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2399 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
2404 static bool test_OpenPrinterEx(struct torture_context *tctx,
2405 struct dcerpc_pipe *p,
2408 struct policy_handle handle;
2411 if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
2415 if (!test_GetPrinter(tctx, p, &handle)) {
2419 if (!test_EnumForms(tctx, p, &handle, false)) {
2423 if (!test_AddForm(tctx, p, &handle, false)) {
2427 if (!test_EnumPrinterData(tctx, p, &handle)) {
2431 if (!test_EnumPrinterDataEx(tctx, p, &handle)) {
2435 if (!test_PausePrinter(tctx, p, &handle)) {
2439 if (!test_DoPrintTest(tctx, p, &handle)) {
2443 if (!test_ResumePrinter(tctx, p, &handle)) {
2447 if (!test_SetPrinterData(tctx, p, &handle)) {
2451 if (!torture_setting_bool(tctx, "samba3", false)) {
2452 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2457 if (!test_ClosePrinter(tctx, p, &handle)) {
2464 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
2466 struct spoolss_EnumPrinters r;
2468 uint16_t levels[] = {1, 2, 4, 5};
2472 for (i=0;i<ARRAY_SIZE(levels);i++) {
2473 union spoolss_PrinterInfo *info;
2478 r.in.flags = PRINTER_ENUM_LOCAL;
2480 r.in.level = levels[i];
2483 r.out.needed = &needed;
2484 r.out.count = &count;
2487 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
2489 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2490 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2492 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2493 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2494 data_blob_clear(&blob);
2495 r.in.buffer = &blob;
2496 r.in.offered = needed;
2497 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2500 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2502 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
2505 torture_comment(tctx, "No printers returned\n");
2509 for (j=0;j<count;j++) {
2510 if (r.in.level == 1) {
2511 char *unc = talloc_strdup(tctx, info[j].info1.name);
2514 if (unc[0] == '\\' && unc[1] == '\\') {
2517 slash = strchr(unc, '\\');
2522 if (!test_OpenPrinter(tctx, p, name)) {
2525 if (!test_OpenPrinterEx(tctx, p, name)) {
2536 static bool test_GetPrinterDriver2(struct dcerpc_pipe *p,
2537 struct policy_handle *handle,
2538 const char *driver_name)
2541 struct spoolss_GetPrinterDriver2 r;
2543 uint32_t server_major_version;
2544 uint32_t server_minor_version;
2546 r.in.handle = handle;
2547 r.in.architecture = "W32X86";
2551 r.in.client_major_version = 0;
2552 r.in.client_minor_version = 0;
2553 r.out.needed = &needed;
2554 r.out.server_major_version = &server_major_version;
2555 r.out.server_minor_version = &server_minor_version;
2557 printf("Testing GetPrinterDriver2\n");
2559 status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
2560 if (!NT_STATUS_IS_OK(status)) {
2561 printf("GetPrinterDriver2 failed - %s\n", nt_errstr(status));
2565 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2566 r.in.offered = needed;
2567 status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
2570 if (!NT_STATUS_IS_OK(status)) {
2571 printf("GetPrinterDriver2 failed - %s\n",
2576 if (!W_ERROR_IS_OK(r.out.result)) {
2577 printf("GetPrinterDriver2 failed - %s\n",
2578 win_errstr(r.out.result));
2586 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
2587 struct dcerpc_pipe *p)
2589 struct spoolss_EnumPrinterDrivers r;
2591 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
2594 for (i=0;i<ARRAY_SIZE(levels);i++) {
2598 union spoolss_DriverInfo *info;
2600 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2601 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
2602 r.in.level = levels[i];
2605 r.out.needed = &needed;
2606 r.out.count = &count;
2609 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
2611 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2613 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2615 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2616 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2617 data_blob_clear(&blob);
2618 r.in.buffer = &blob;
2619 r.in.offered = needed;
2620 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2623 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2625 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
2628 torture_comment(tctx, "No printer drivers returned\n");
2636 bool torture_rpc_spoolss(struct torture_context *torture)
2639 struct dcerpc_pipe *p;
2641 struct test_spoolss_context *ctx;
2643 status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
2644 if (!NT_STATUS_IS_OK(status)) {
2648 ctx = talloc_zero(torture, struct test_spoolss_context);
2650 ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
2652 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "W3SvcInstalled");
2653 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "BeepEnabled");
2654 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "EventLog");
2655 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopup");
2656 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopupToComputer");
2657 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MajorVersion");
2658 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MinorVersion");
2659 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DefaultSpoolDirectory");
2660 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "Architecture");
2661 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DsPresent");
2662 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersion");
2663 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersionEx");
2664 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DNSMachineName");
2665 ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
2666 ret &= test_AddForm(torture, p, &ctx->server_handle, true);
2667 ret &= test_EnumPorts(torture, p, ctx);
2668 ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
2669 ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
2670 ret &= test_EnumPrinterDrivers(torture, p, ctx);
2671 ret &= test_EnumMonitors(torture, p, ctx);
2672 ret &= test_EnumPrintProcessors(torture, p, ctx);
2673 ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
2674 ret &= test_EnumPrinters(torture, p, ctx);
2675 ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
2676 ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
2677 ret &= test_OpenPrinter_badname(torture, p, "");
2678 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
2679 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
2680 ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
2681 ret &= test_OpenPrinter_badname(torture, p,
2682 talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
2685 ret &= test_AddPort(torture, p);
2686 ret &= test_EnumPorts_old(torture, p);
2687 ret &= test_EnumPrinters_old(torture, p);
2688 ret &= test_EnumPrinterDrivers_old(torture, p);