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
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "torture/torture.h"
25 #include "torture/rpc/rpc.h"
26 #include "librpc/gen_ndr/ndr_spoolss_c.h"
28 struct test_spoolss_context {
29 /* print server handle */
30 struct policy_handle server_handle;
33 uint32_t port_count[3];
34 union spoolss_PortInfo *ports[3];
36 /* for EnumPrinterDrivers */
37 uint32_t driver_count[7];
38 union spoolss_DriverInfo *drivers[7];
40 /* for EnumMonitors */
41 uint32_t monitor_count[3];
42 union spoolss_MonitorInfo *monitors[3];
44 /* for EnumPrintProcessors */
45 uint32_t print_processor_count[2];
46 union spoolss_PrintProcessorInfo *print_processors[2];
48 /* for EnumPrinters */
49 uint32_t printer_count[6];
50 union spoolss_PrinterInfo *printers[6];
53 #define COMPARE_STRING(tctx, c,r,e) \
54 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
56 /* not every compiler supports __typeof__() */
58 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
59 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
60 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
62 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
63 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
67 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
70 #define COMPARE_UINT32(tctx, c, r, e) do {\
71 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
72 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
75 #define COMPARE_STRING_ARRAY(tctx, c,r,e)
77 static bool test_OpenPrinter_server(struct torture_context *tctx, struct dcerpc_pipe *p, struct test_spoolss_context *ctx)
80 struct spoolss_OpenPrinter op;
82 op.in.printername = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p));
83 op.in.datatype = NULL;
84 op.in.devmode_ctr.devmode= NULL;
85 op.in.access_mask = 0;
86 op.out.handle = &ctx->server_handle;
88 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
90 status = dcerpc_spoolss_OpenPrinter(p, ctx, &op);
91 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
92 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
97 static bool test_EnumPorts(struct torture_context *tctx,
98 struct dcerpc_pipe *p,
99 struct test_spoolss_context *ctx)
102 struct spoolss_EnumPorts r;
103 uint16_t levels[] = { 1, 2 };
106 for (i=0;i<ARRAY_SIZE(levels);i++) {
107 int level = levels[i];
111 union spoolss_PortInfo *info;
113 r.in.servername = "";
117 r.out.needed = &needed;
118 r.out.count = &count;
121 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
123 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
124 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
125 if (W_ERROR_IS_OK(r.out.result)) {
126 /* TODO: do some more checks here */
129 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
130 "EnumPorts unexpected return code");
132 blob = data_blob_talloc(ctx, NULL, needed);
133 data_blob_clear(&blob);
135 r.in.offered = needed;
137 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
138 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
140 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
142 torture_assert(tctx, info, "EnumPorts returned no info");
144 ctx->port_count[level] = count;
145 ctx->ports[level] = info;
148 for (i=1;i<ARRAY_SIZE(levels);i++) {
149 int level = levels[i];
150 int old_level = levels[i-1];
151 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
152 "EnumPorts invalid value");
154 /* if the array sizes are not the same we would maybe segfault in the following code */
156 for (i=0;i<ARRAY_SIZE(levels);i++) {
157 int level = levels[i];
158 for (j=0;j<ctx->port_count[level];j++) {
159 union spoolss_PortInfo *cur = &ctx->ports[level][j];
160 union spoolss_PortInfo *ref = &ctx->ports[2][j];
163 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
166 /* level 2 is our reference, and it makes no sense to compare it to itself */
175 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
176 struct dcerpc_pipe *p,
177 struct test_spoolss_context *ctx)
180 struct spoolss_GetPrintProcessorDirectory r;
195 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
198 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
204 for (i=0;i<ARRAY_SIZE(levels);i++) {
205 int level = levels[i].level;
208 r.in.server = levels[i].server;
209 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
213 r.out.needed = &needed;
215 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
217 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
218 torture_assert_ntstatus_ok(tctx, status,
219 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
220 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
221 "GetPrintProcessorDirectory unexpected return code");
223 blob = data_blob_talloc(ctx, NULL, needed);
224 data_blob_clear(&blob);
226 r.in.offered = needed;
228 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
229 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
231 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
238 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
239 struct dcerpc_pipe *p,
240 struct test_spoolss_context *ctx)
243 struct spoolss_GetPrinterDriverDirectory r;
258 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
261 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
267 for (i=0;i<ARRAY_SIZE(levels);i++) {
268 int level = levels[i].level;
271 r.in.server = levels[i].server;
272 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
276 r.out.needed = &needed;
278 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
280 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
281 torture_assert_ntstatus_ok(tctx, status,
282 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
283 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
284 "GetPrinterDriverDirectory unexpected return code");
286 blob = data_blob_talloc(ctx, NULL, needed);
287 data_blob_clear(&blob);
289 r.in.offered = needed;
291 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
292 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
294 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
300 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
301 struct dcerpc_pipe *p,
302 struct test_spoolss_context *ctx)
305 struct spoolss_EnumPrinterDrivers r;
306 uint16_t levels[] = { 1, 2, 3, 4, 5, 6 };
309 for (i=0;i<ARRAY_SIZE(levels);i++) {
310 int level = levels[i];
314 union spoolss_DriverInfo *info;
316 /* FIXME: gd, come back and fix "" as server, and handle
317 * priority of returned error codes in torture test and samba 3
320 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
321 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
325 r.out.needed = &needed;
326 r.out.count = &count;
329 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
331 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
332 torture_assert_ntstatus_ok(tctx, status,
333 "dcerpc_spoolss_EnumPrinterDrivers failed");
334 if (W_ERROR_IS_OK(r.out.result)) {
335 /* TODO: do some more checks here */
338 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
339 blob = data_blob_talloc(ctx, NULL, needed);
340 data_blob_clear(&blob);
342 r.in.offered = needed;
344 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
345 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
348 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
350 ctx->driver_count[level] = count;
351 ctx->drivers[level] = info;
354 for (i=1;i<ARRAY_SIZE(levels);i++) {
355 int level = levels[i];
356 int old_level = levels[i-1];
357 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
358 "EnumPrinterDrivers invalid value");
361 for (i=0;i<ARRAY_SIZE(levels);i++) {
362 int level = levels[i];
363 for (j=0;j<ctx->driver_count[level];j++) {
364 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
365 union spoolss_DriverInfo *ref = &ctx->drivers[6][j];
368 COMPARE_STRING(tctx, cur->info1, ref->info6, driver_name);
371 COMPARE_UINT32(tctx, cur->info2, ref->info6, version);
372 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_name);
373 COMPARE_STRING(tctx, cur->info2, ref->info6, architecture);
374 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_path);
375 COMPARE_STRING(tctx, cur->info2, ref->info6, data_file);
376 COMPARE_STRING(tctx, cur->info2, ref->info6, config_file);
379 COMPARE_UINT32(tctx, cur->info3, ref->info6, version);
380 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_name);
381 COMPARE_STRING(tctx, cur->info3, ref->info6, architecture);
382 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_path);
383 COMPARE_STRING(tctx, cur->info3, ref->info6, data_file);
384 COMPARE_STRING(tctx, cur->info3, ref->info6, config_file);
385 COMPARE_STRING(tctx, cur->info3, ref->info6, help_file);
386 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info6, dependent_files);
387 COMPARE_STRING(tctx, cur->info3, ref->info6, monitor_name);
388 COMPARE_STRING(tctx, cur->info3, ref->info6, default_datatype);
391 COMPARE_UINT32(tctx, cur->info4, ref->info6, version);
392 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_name);
393 COMPARE_STRING(tctx, cur->info4, ref->info6, architecture);
394 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_path);
395 COMPARE_STRING(tctx, cur->info4, ref->info6, data_file);
396 COMPARE_STRING(tctx, cur->info4, ref->info6, config_file);
397 COMPARE_STRING(tctx, cur->info4, ref->info6, help_file);
398 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, dependent_files);
399 COMPARE_STRING(tctx, cur->info4, ref->info6, monitor_name);
400 COMPARE_STRING(tctx, cur->info4, ref->info6, default_datatype);
401 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, previous_names);
404 COMPARE_UINT32(tctx, cur->info5, ref->info6, version);
405 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_name);
406 COMPARE_STRING(tctx, cur->info5, ref->info6, architecture);
407 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_path);
408 COMPARE_STRING(tctx, cur->info5, ref->info6, data_file);
409 COMPARE_STRING(tctx, cur->info5, ref->info6, config_file);
410 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_attributes);*/
411 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, config_version);*/
412 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_version); */
415 /* level 6 is our reference, and it makes no sense to compare it to itself */
424 static bool test_EnumMonitors(struct torture_context *tctx,
425 struct dcerpc_pipe *p,
426 struct test_spoolss_context *ctx)
429 struct spoolss_EnumMonitors r;
430 uint16_t levels[] = { 1, 2 };
433 for (i=0;i<ARRAY_SIZE(levels);i++) {
434 int level = levels[i];
438 union spoolss_MonitorInfo *info;
440 r.in.servername = "";
444 r.out.needed = &needed;
445 r.out.count = &count;
448 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
450 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
451 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
452 if (W_ERROR_IS_OK(r.out.result)) {
453 /* TODO: do some more checks here */
456 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
457 "EnumMonitors failed");
459 blob = data_blob_talloc(ctx, NULL, needed);
460 data_blob_clear(&blob);
462 r.in.offered = needed;
464 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
465 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
467 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
469 ctx->monitor_count[level] = count;
470 ctx->monitors[level] = info;
473 for (i=1;i<ARRAY_SIZE(levels);i++) {
474 int level = levels[i];
475 int old_level = levels[i-1];
476 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
477 "EnumMonitors invalid value");
480 for (i=0;i<ARRAY_SIZE(levels);i++) {
481 int level = levels[i];
482 for (j=0;j<ctx->monitor_count[level];j++) {
483 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
484 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
487 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
490 /* level 2 is our reference, and it makes no sense to compare it to itself */
499 static bool test_EnumPrintProcessors(struct torture_context *tctx,
500 struct dcerpc_pipe *p,
501 struct test_spoolss_context *ctx)
504 struct spoolss_EnumPrintProcessors r;
505 uint16_t levels[] = { 1 };
508 for (i=0;i<ARRAY_SIZE(levels);i++) {
509 int level = levels[i];
513 union spoolss_PrintProcessorInfo *info;
515 r.in.servername = "";
516 r.in.environment = "Windows NT x86";
520 r.out.needed = &needed;
521 r.out.count = &count;
524 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
526 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
527 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
528 if (W_ERROR_IS_OK(r.out.result)) {
529 /* TODO: do some more checks here */
532 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
533 "EnumPrintProcessors unexpected return code");
535 blob = data_blob_talloc(ctx, NULL, needed);
536 data_blob_clear(&blob);
538 r.in.offered = needed;
540 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
541 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
543 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
545 ctx->print_processor_count[level] = count;
546 ctx->print_processors[level] = info;
549 for (i=1;i<ARRAY_SIZE(levels);i++) {
550 int level = levels[i];
551 int old_level = levels[i-1];
552 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
553 "EnumPrintProcessors failed");
556 for (i=0;i<ARRAY_SIZE(levels);i++) {
557 int level = levels[i];
558 for (j=0;j<ctx->print_processor_count[level];j++) {
560 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
561 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
565 /* level 1 is our reference, and it makes no sense to compare it to itself */
574 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
575 struct dcerpc_pipe *p,
576 struct test_spoolss_context *ctx)
579 struct spoolss_EnumPrintProcDataTypes r;
580 uint16_t levels[] = { 1 };
583 for (i=0;i<ARRAY_SIZE(levels);i++) {
584 int level = levels[i];
588 union spoolss_PrintProcDataTypesInfo *info;
590 r.in.servername = "";
591 r.in.print_processor_name = "winprint";
595 r.out.needed = &needed;
596 r.out.count = &count;
599 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
601 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
602 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
603 if (W_ERROR_IS_OK(r.out.result)) {
604 /* TODO: do some more checks here */
607 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
608 "EnumPrintProcDataTypes unexpected return code");
610 blob = data_blob_talloc(ctx, NULL, needed);
611 data_blob_clear(&blob);
613 r.in.offered = needed;
615 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
616 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
618 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
625 static bool test_EnumPrinters(struct torture_context *tctx,
626 struct dcerpc_pipe *p,
627 struct test_spoolss_context *ctx)
629 struct spoolss_EnumPrinters r;
631 uint16_t levels[] = { 0, 1, 2, 4, 5 };
634 for (i=0;i<ARRAY_SIZE(levels);i++) {
635 int level = levels[i];
639 union spoolss_PrinterInfo *info;
641 r.in.flags = PRINTER_ENUM_LOCAL;
646 r.out.needed = &needed;
647 r.out.count = &count;
650 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
652 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
653 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
654 if (W_ERROR_IS_OK(r.out.result)) {
655 /* TODO: do some more checks here */
658 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
659 "EnumPrinters unexpected return code");
661 blob = data_blob_talloc(ctx, NULL, needed);
662 data_blob_clear(&blob);
664 r.in.offered = needed;
666 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
667 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
669 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
671 ctx->printer_count[level] = count;
672 ctx->printers[level] = info;
675 for (i=1;i<ARRAY_SIZE(levels);i++) {
676 int level = levels[i];
677 int old_level = levels[i-1];
678 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
679 "EnumPrinters invalid value");
682 for (i=0;i<ARRAY_SIZE(levels);i++) {
683 int level = levels[i];
684 for (j=0;j<ctx->printer_count[level];j++) {
685 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
686 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
689 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
690 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
691 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
692 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
693 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
694 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
695 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
696 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
697 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
698 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
699 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
700 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
701 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
702 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
703 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
704 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
705 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
706 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
707 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
708 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
709 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
710 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
711 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
712 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
713 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
714 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
715 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
716 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
717 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
720 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
721 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
722 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
723 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
726 /* level 2 is our reference, and it makes no sense to compare it to itself */
729 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
730 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
731 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
734 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
735 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
736 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
737 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
738 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
745 * - verify that the port of a printer was in the list returned by EnumPorts
751 static bool test_GetPrinter(struct torture_context *tctx,
752 struct dcerpc_pipe *p,
753 struct policy_handle *handle)
756 struct spoolss_GetPrinter r;
757 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
761 for (i=0;i<ARRAY_SIZE(levels);i++) {
762 r.in.handle = handle;
763 r.in.level = levels[i];
766 r.out.needed = &needed;
768 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
770 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
771 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
773 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
774 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
775 data_blob_clear(&blob);
777 r.in.offered = needed;
778 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
781 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
783 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
790 static bool test_ClosePrinter(struct torture_context *tctx,
791 struct dcerpc_pipe *p,
792 struct policy_handle *handle)
795 struct spoolss_ClosePrinter r;
797 r.in.handle = handle;
798 r.out.handle = handle;
800 torture_comment(tctx, "Testing ClosePrinter\n");
802 status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
803 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
808 static bool test_GetForm(struct torture_context *tctx,
809 struct dcerpc_pipe *p,
810 struct policy_handle *handle,
811 const char *form_name,
815 struct spoolss_GetForm r;
818 r.in.handle = handle;
819 r.in.form_name = form_name;
823 r.out.needed = &needed;
825 torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
827 status = dcerpc_spoolss_GetForm(p, tctx, &r);
828 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
830 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
831 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
832 data_blob_clear(&blob);
834 r.in.offered = needed;
835 status = dcerpc_spoolss_GetForm(p, tctx, &r);
836 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
838 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
840 torture_assert(tctx, r.out.info, "No form info returned");
843 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
848 static bool test_EnumForms(struct torture_context *tctx,
849 struct dcerpc_pipe *p,
850 struct policy_handle *handle, bool print_server)
853 struct spoolss_EnumForms r;
857 uint32_t levels[] = { 1, 2 };
860 for (i=0; i<ARRAY_SIZE(levels); i++) {
862 union spoolss_FormInfo *info;
864 r.in.handle = handle;
865 r.in.level = levels[i];
868 r.out.needed = &needed;
869 r.out.count = &count;
872 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
874 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
875 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
877 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
881 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
882 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
884 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
886 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
887 data_blob_clear(&blob);
889 r.in.offered = needed;
891 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
893 torture_assert(tctx, info, "No forms returned");
895 for (j = 0; j < count; j++) {
897 ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
901 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
903 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
909 static bool test_DeleteForm(struct torture_context *tctx,
910 struct dcerpc_pipe *p,
911 struct policy_handle *handle,
912 const char *form_name)
915 struct spoolss_DeleteForm r;
917 r.in.handle = handle;
918 r.in.form_name = form_name;
920 status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
922 torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
924 torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
929 static bool test_AddForm(struct torture_context *tctx,
930 struct dcerpc_pipe *p,
931 struct policy_handle *handle, bool print_server)
933 struct spoolss_AddForm r;
934 struct spoolss_AddFormInfo1 addform;
935 const char *form_name = "testform3";
939 r.in.handle = handle;
941 r.in.info.info1 = &addform;
942 addform.flags = SPOOLSS_FORM_USER;
943 addform.form_name = form_name;
944 addform.size.width = 50;
945 addform.size.height = 25;
946 addform.area.left = 5;
947 addform.area.top = 10;
948 addform.area.right = 45;
949 addform.area.bottom = 15;
951 status = dcerpc_spoolss_AddForm(p, tctx, &r);
953 torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
955 torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
957 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
960 struct spoolss_SetForm sf;
961 struct spoolss_AddFormInfo1 setform;
963 sf.in.handle = handle;
964 sf.in.form_name = form_name;
966 sf.in.info.info1= &setform;
967 setform.flags = addform.flags;
968 setform.form_name = addform.form_name;
969 setform.size = addform.size;
970 setform.area = addform.area;
972 setform.size.width = 1234;
974 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
976 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
978 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
981 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
983 if (!test_DeleteForm(tctx, p, handle, form_name)) {
990 static bool test_EnumPorts_old(struct torture_context *tctx,
991 struct dcerpc_pipe *p)
994 struct spoolss_EnumPorts r;
997 union spoolss_PortInfo *info;
999 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
1000 dcerpc_server_name(p));
1004 r.out.needed = &needed;
1005 r.out.count = &count;
1008 torture_comment(tctx, "Testing EnumPorts\n");
1010 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1012 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1014 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1015 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1016 data_blob_clear(&blob);
1017 r.in.buffer = &blob;
1018 r.in.offered = needed;
1020 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1021 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1023 torture_assert(tctx, info, "No ports returned");
1029 static bool test_AddPort(struct torture_context *tctx,
1030 struct dcerpc_pipe *p)
1033 struct spoolss_AddPort r;
1035 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
1036 dcerpc_server_name(p));
1038 r.in.monitor_name = "foo";
1040 torture_comment(tctx, "Testing AddPort\n");
1042 status = dcerpc_spoolss_AddPort(p, tctx, &r);
1044 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
1046 /* win2k3 returns WERR_NOT_SUPPORTED */
1050 if (!W_ERROR_IS_OK(r.out.result)) {
1051 printf("AddPort failed - %s\n", win_errstr(r.out.result));
1060 static bool test_GetJob(struct torture_context *tctx,
1061 struct dcerpc_pipe *p,
1062 struct policy_handle *handle, uint32_t job_id)
1065 struct spoolss_GetJob r;
1068 r.in.handle = handle;
1069 r.in.job_id = job_id;
1073 r.out.needed = &needed;
1075 torture_comment(tctx, "Testing GetJob\n");
1077 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1078 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1080 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1081 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1082 data_blob_clear(&blob);
1083 r.in.buffer = &blob;
1084 r.in.offered = needed;
1086 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1088 torture_assert(tctx, r.out.info, "No job info returned");
1094 static bool test_SetJob(struct torture_context *tctx,
1095 struct dcerpc_pipe *p,
1096 struct policy_handle *handle, uint32_t job_id,
1097 enum spoolss_JobControl command)
1100 struct spoolss_SetJob r;
1102 r.in.handle = handle;
1103 r.in.job_id = job_id;
1105 r.in.command = command;
1108 case SPOOLSS_JOB_CONTROL_PAUSE:
1109 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1111 case SPOOLSS_JOB_CONTROL_RESUME:
1112 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1114 case SPOOLSS_JOB_CONTROL_CANCEL:
1115 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1117 case SPOOLSS_JOB_CONTROL_RESTART:
1118 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1120 case SPOOLSS_JOB_CONTROL_DELETE:
1121 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1123 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
1124 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1126 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
1127 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1129 case SPOOLSS_JOB_CONTROL_RETAIN:
1130 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1132 case SPOOLSS_JOB_CONTROL_RELEASE:
1133 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1136 torture_comment(tctx, "Testing SetJob\n");
1140 status = dcerpc_spoolss_SetJob(p, tctx, &r);
1141 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
1142 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
1147 static bool test_AddJob(struct torture_context *tctx,
1148 struct dcerpc_pipe *p,
1149 struct policy_handle *handle)
1152 struct spoolss_AddJob r;
1156 r.in.handle = handle;
1158 r.out.needed = &needed;
1159 r.in.buffer = r.out.buffer = NULL;
1161 torture_comment(tctx, "Testing AddJob\n");
1163 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1164 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
1168 status = dcerpc_spoolss_AddJob(p, tctx, &r);
1169 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
1175 static bool test_EnumJobs(struct torture_context *tctx,
1176 struct dcerpc_pipe *p,
1177 struct policy_handle *handle)
1180 struct spoolss_EnumJobs r;
1183 union spoolss_JobInfo *info;
1185 r.in.handle = handle;
1187 r.in.numjobs = 0xffffffff;
1191 r.out.needed = &needed;
1192 r.out.count = &count;
1195 torture_comment(tctx, "Testing EnumJobs\n");
1197 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1199 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1201 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1203 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1204 data_blob_clear(&blob);
1205 r.in.buffer = &blob;
1206 r.in.offered = needed;
1208 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1210 torture_assert(tctx, info, "No jobs returned");
1212 for (j = 0; j < count; j++) {
1214 test_GetJob(tctx, p, handle, info[j].info1.job_id);
1215 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
1216 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
1220 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1226 static bool test_DoPrintTest(struct torture_context *tctx,
1227 struct dcerpc_pipe *p,
1228 struct policy_handle *handle)
1232 struct spoolss_StartDocPrinter s;
1233 struct spoolss_DocumentInfo1 info1;
1234 struct spoolss_StartPagePrinter sp;
1235 struct spoolss_WritePrinter w;
1236 struct spoolss_EndPagePrinter ep;
1237 struct spoolss_EndDocPrinter e;
1240 uint32_t num_written;
1242 torture_comment(tctx, "Testing StartDocPrinter\n");
1244 s.in.handle = handle;
1246 s.in.info.info1 = &info1;
1247 s.out.job_id = &job_id;
1248 info1.document_name = "TorturePrintJob";
1249 info1.output_file = NULL;
1250 info1.datatype = "RAW";
1252 status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
1253 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
1254 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
1256 for (i=1; i < 4; i++) {
1257 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
1259 sp.in.handle = handle;
1261 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
1262 torture_assert_ntstatus_ok(tctx, status,
1263 "dcerpc_spoolss_StartPagePrinter failed");
1264 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
1266 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
1268 w.in.handle = handle;
1269 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
1270 w.out.num_written = &num_written;
1272 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
1273 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
1274 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
1276 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
1278 ep.in.handle = handle;
1280 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
1281 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
1282 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
1285 torture_comment(tctx, "Testing EndDocPrinter\n");
1287 e.in.handle = handle;
1289 status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
1290 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
1291 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
1293 ret &= test_AddJob(tctx, p, handle);
1294 ret &= test_EnumJobs(tctx, p, handle);
1296 ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
1301 static bool test_PausePrinter(struct torture_context *tctx,
1302 struct dcerpc_pipe *p,
1303 struct policy_handle *handle)
1306 struct spoolss_SetPrinter r;
1307 struct spoolss_SetPrinterInfoCtr info_ctr;
1308 struct spoolss_DevmodeContainer devmode_ctr;
1309 struct sec_desc_buf secdesc_ctr;
1312 info_ctr.info.info0 = NULL;
1314 ZERO_STRUCT(devmode_ctr);
1315 ZERO_STRUCT(secdesc_ctr);
1317 r.in.handle = handle;
1318 r.in.info_ctr = &info_ctr;
1319 r.in.devmode_ctr = &devmode_ctr;
1320 r.in.secdesc_ctr = &secdesc_ctr;
1321 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
1323 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1325 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1327 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1329 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1334 static bool test_ResumePrinter(struct torture_context *tctx,
1335 struct dcerpc_pipe *p,
1336 struct policy_handle *handle)
1339 struct spoolss_SetPrinter r;
1340 struct spoolss_SetPrinterInfoCtr info_ctr;
1341 struct spoolss_DevmodeContainer devmode_ctr;
1342 struct sec_desc_buf secdesc_ctr;
1345 info_ctr.info.info0 = NULL;
1347 ZERO_STRUCT(devmode_ctr);
1348 ZERO_STRUCT(secdesc_ctr);
1350 r.in.handle = handle;
1351 r.in.info_ctr = &info_ctr;
1352 r.in.devmode_ctr = &devmode_ctr;
1353 r.in.secdesc_ctr = &secdesc_ctr;
1354 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
1356 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
1358 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1360 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1362 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1367 static bool test_GetPrinterData(struct torture_context *tctx,
1368 struct dcerpc_pipe *p,
1369 struct policy_handle *handle,
1370 const char *value_name)
1373 struct spoolss_GetPrinterData r;
1375 enum winreg_Type type;
1376 union spoolss_PrinterData data;
1378 r.in.handle = handle;
1379 r.in.value_name = value_name;
1381 r.out.needed = &needed;
1385 torture_comment(tctx, "Testing GetPrinterData\n");
1387 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
1388 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
1390 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1391 r.in.offered = needed;
1393 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
1394 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
1396 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterData failed");
1402 static bool test_GetPrinterDataEx(struct torture_context *tctx,
1403 struct dcerpc_pipe *p,
1404 struct policy_handle *handle,
1405 const char *key_name,
1406 const char *value_name)
1409 struct spoolss_GetPrinterDataEx r;
1410 enum winreg_Type type;
1413 r.in.handle = handle;
1414 r.in.key_name = key_name;
1415 r.in.value_name = value_name;
1418 r.out.needed = &needed;
1419 r.out.buffer = NULL;
1421 torture_comment(tctx, "Testing GetPrinterDataEx\n");
1423 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
1424 if (!NT_STATUS_IS_OK(status)) {
1425 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
1426 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1427 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
1429 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
1432 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1433 r.in.offered = needed;
1434 r.out.buffer = talloc_array(tctx, uint8_t, needed);
1436 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
1437 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
1439 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDataEx failed");
1445 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
1446 struct policy_handle *handle)
1449 struct spoolss_EnumPrinterData r;
1452 r.in.handle = handle;
1453 r.in.enum_index = 0;
1456 uint32_t value_size = 0;
1457 uint32_t data_size = 0;
1458 enum winreg_Type type = 0;
1460 r.in.value_offered = value_size;
1461 r.out.value_needed = &value_size;
1462 r.in.data_offered = data_size;
1463 r.out.data_needed = &data_size;
1466 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
1468 torture_comment(tctx, "Testing EnumPrinterData\n");
1470 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
1472 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
1474 r.in.value_offered = value_size;
1475 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
1476 r.in.data_offered = data_size;
1477 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
1479 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
1481 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
1483 test_GetPrinterData(tctx, p, handle, r.out.value_name);
1485 test_GetPrinterDataEx(tctx,
1486 p, handle, "PrinterDriverData",
1491 } while (W_ERROR_IS_OK(r.out.result));
1496 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
1497 struct dcerpc_pipe *p,
1498 struct policy_handle *handle)
1501 struct spoolss_EnumPrinterDataEx r;
1502 struct spoolss_PrinterEnumValues *info;
1506 r.in.handle = handle;
1507 r.in.key_name = "PrinterDriverData";
1509 r.out.needed = &needed;
1510 r.out.count = &count;
1513 torture_comment(tctx, "Testing EnumPrinterDataEx\n");
1515 status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
1516 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
1518 r.in.offered = needed;
1520 status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
1522 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
1528 static bool test_DeletePrinterData(struct torture_context *tctx,
1529 struct dcerpc_pipe *p,
1530 struct policy_handle *handle,
1531 const char *value_name)
1534 struct spoolss_DeletePrinterData r;
1536 r.in.handle = handle;
1537 r.in.value_name = value_name;
1539 torture_comment(tctx, "Testing DeletePrinterData\n");
1541 status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
1543 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
1548 static bool test_SetPrinterData(struct torture_context *tctx,
1549 struct dcerpc_pipe *p,
1550 struct policy_handle *handle)
1553 struct spoolss_SetPrinterData r;
1554 const char *value_name = "spottyfoot";
1556 r.in.handle = handle;
1557 r.in.value_name = value_name;
1559 r.in.data.string = "dog";
1561 torture_comment(tctx, "Testing SetPrinterData\n");
1563 status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
1565 torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
1567 if (!test_GetPrinterData(tctx, p, handle, value_name)) {
1571 if (!test_DeletePrinterData(tctx, p, handle, value_name)) {
1578 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
1579 struct dcerpc_pipe *p,
1580 struct policy_handle *handle)
1583 struct dcerpc_binding *b;
1584 struct dcerpc_pipe *p2;
1585 struct spoolss_ClosePrinter cp;
1587 /* only makes sense on SMB */
1588 if (p->conn->transport.transport != NCACN_NP) {
1592 torture_comment(tctx, "testing close on secondary pipe\n");
1594 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
1595 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
1597 status = dcerpc_secondary_connection(p, &p2, b);
1598 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
1600 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
1601 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
1603 cp.in.handle = handle;
1604 cp.out.handle = handle;
1606 status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
1607 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
1608 "ERROR: Allowed close on secondary connection");
1610 torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
1611 "Unexpected fault code");
1618 static bool test_OpenPrinter_badname(struct torture_context *tctx,
1619 struct dcerpc_pipe *p, const char *name)
1622 struct spoolss_OpenPrinter op;
1623 struct spoolss_OpenPrinterEx opEx;
1624 struct policy_handle handle;
1627 op.in.printername = name;
1628 op.in.datatype = NULL;
1629 op.in.devmode_ctr.devmode= NULL;
1630 op.in.access_mask = 0;
1631 op.out.handle = &handle;
1633 torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
1635 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
1636 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
1637 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
1638 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
1639 name, win_errstr(op.out.result));
1642 if (W_ERROR_IS_OK(op.out.result)) {
1643 ret &=test_ClosePrinter(tctx, p, &handle);
1646 opEx.in.printername = name;
1647 opEx.in.datatype = NULL;
1648 opEx.in.devmode_ctr.devmode = NULL;
1649 opEx.in.access_mask = 0;
1651 opEx.in.userlevel.level1 = NULL;
1652 opEx.out.handle = &handle;
1654 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
1656 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
1657 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
1658 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
1659 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
1660 name, win_errstr(opEx.out.result));
1663 if (W_ERROR_IS_OK(opEx.out.result)) {
1664 ret &=test_ClosePrinter(tctx, p, &handle);
1670 static bool test_OpenPrinter(struct torture_context *tctx,
1671 struct dcerpc_pipe *p,
1675 struct spoolss_OpenPrinter r;
1676 struct policy_handle handle;
1679 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
1680 r.in.datatype = NULL;
1681 r.in.devmode_ctr.devmode= NULL;
1682 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1683 r.out.handle = &handle;
1685 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
1687 status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
1689 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
1691 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
1693 if (!test_GetPrinter(tctx, p, &handle)) {
1697 if (!torture_setting_bool(tctx, "samba3", false)) {
1698 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
1703 if (!test_ClosePrinter(tctx, p, &handle)) {
1710 static bool call_OpenPrinterEx(struct torture_context *tctx,
1711 struct dcerpc_pipe *p,
1712 const char *name, struct policy_handle *handle)
1714 struct spoolss_OpenPrinterEx r;
1715 struct spoolss_UserLevel1 userlevel1;
1718 if (name && name[0]) {
1719 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
1720 dcerpc_server_name(p), name);
1722 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
1723 dcerpc_server_name(p));
1726 r.in.datatype = NULL;
1727 r.in.devmode_ctr.devmode= NULL;
1728 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1730 r.in.userlevel.level1 = &userlevel1;
1731 r.out.handle = handle;
1733 userlevel1.size = 1234;
1734 userlevel1.client = "hello";
1735 userlevel1.user = "spottyfoot!";
1736 userlevel1.build = 1;
1737 userlevel1.major = 2;
1738 userlevel1.minor = 3;
1739 userlevel1.processor = 4;
1741 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
1743 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
1745 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
1747 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
1752 static bool test_OpenPrinterEx(struct torture_context *tctx,
1753 struct dcerpc_pipe *p,
1756 struct policy_handle handle;
1759 if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
1763 if (!test_GetPrinter(tctx, p, &handle)) {
1767 if (!test_EnumForms(tctx, p, &handle, false)) {
1771 if (!test_AddForm(tctx, p, &handle, false)) {
1775 if (!test_EnumPrinterData(tctx, p, &handle)) {
1779 if (!test_EnumPrinterDataEx(tctx, p, &handle)) {
1783 if (!test_PausePrinter(tctx, p, &handle)) {
1787 if (!test_DoPrintTest(tctx, p, &handle)) {
1791 if (!test_ResumePrinter(tctx, p, &handle)) {
1795 if (!test_SetPrinterData(tctx, p, &handle)) {
1799 if (!torture_setting_bool(tctx, "samba3", false)) {
1800 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
1805 if (!test_ClosePrinter(tctx, p, &handle)) {
1812 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
1814 struct spoolss_EnumPrinters r;
1816 uint16_t levels[] = {1, 2, 4, 5};
1820 for (i=0;i<ARRAY_SIZE(levels);i++) {
1821 union spoolss_PrinterInfo *info;
1826 r.in.flags = PRINTER_ENUM_LOCAL;
1828 r.in.level = levels[i];
1831 r.out.needed = &needed;
1832 r.out.count = &count;
1835 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1837 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
1838 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
1840 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1841 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1842 data_blob_clear(&blob);
1843 r.in.buffer = &blob;
1844 r.in.offered = needed;
1845 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
1848 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
1850 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1853 torture_comment(tctx, "No printers returned\n");
1857 for (j=0;j<count;j++) {
1858 if (r.in.level == 1) {
1859 char *unc = talloc_strdup(tctx, info[j].info1.name);
1862 if (unc[0] == '\\' && unc[1] == '\\') {
1865 slash = strchr(unc, '\\');
1870 if (!test_OpenPrinter(tctx, p, name)) {
1873 if (!test_OpenPrinterEx(tctx, p, name)) {
1884 static bool test_GetPrinterDriver2(struct dcerpc_pipe *p,
1885 struct policy_handle *handle,
1886 const char *driver_name)
1889 struct spoolss_GetPrinterDriver2 r;
1891 uint32_t server_major_version;
1892 uint32_t server_minor_version;
1894 r.in.handle = handle;
1895 r.in.architecture = "W32X86";
1899 r.in.client_major_version = 0;
1900 r.in.client_minor_version = 0;
1901 r.out.needed = &needed;
1902 r.out.server_major_version = &server_major_version;
1903 r.out.server_minor_version = &server_minor_version;
1905 printf("Testing GetPrinterDriver2\n");
1907 status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
1908 if (!NT_STATUS_IS_OK(status)) {
1909 printf("GetPrinterDriver2 failed - %s\n", nt_errstr(status));
1913 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1914 r.in.offered = needed;
1915 status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
1918 if (!NT_STATUS_IS_OK(status)) {
1919 printf("GetPrinterDriver2 failed - %s\n",
1924 if (!W_ERROR_IS_OK(r.out.result)) {
1925 printf("GetPrinterDriver2 failed - %s\n",
1926 win_errstr(r.out.result));
1934 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
1935 struct dcerpc_pipe *p)
1937 struct spoolss_EnumPrinterDrivers r;
1939 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
1942 for (i=0;i<ARRAY_SIZE(levels);i++) {
1946 union spoolss_DriverInfo *info;
1948 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1949 r.in.environment = "Windows NT x86";
1950 r.in.level = levels[i];
1953 r.out.needed = &needed;
1954 r.out.count = &count;
1957 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
1959 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
1961 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
1963 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1964 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1965 data_blob_clear(&blob);
1966 r.in.buffer = &blob;
1967 r.in.offered = needed;
1968 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
1971 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
1973 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
1976 torture_comment(tctx, "No printer drivers returned\n");
1984 bool torture_rpc_spoolss(struct torture_context *torture)
1987 struct dcerpc_pipe *p;
1989 struct test_spoolss_context *ctx;
1991 status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
1992 if (!NT_STATUS_IS_OK(status)) {
1996 ctx = talloc_zero(torture, struct test_spoolss_context);
1998 ret &= test_OpenPrinter_server(torture, p, ctx);
2000 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "W3SvcInstalled");
2001 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "BeepEnabled");
2002 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "EventLog");
2003 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopup");
2004 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopupToComputer");
2005 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MajorVersion");
2006 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MinorVersion");
2007 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DefaultSpoolDirectory");
2008 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "Architecture");
2009 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DsPresent");
2010 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersion");
2011 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersionEx");
2012 ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DNSMachineName");
2013 ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
2014 ret &= test_AddForm(torture, p, &ctx->server_handle, true);
2015 ret &= test_EnumPorts(torture, p, ctx);
2016 ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
2017 ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
2018 ret &= test_EnumPrinterDrivers(torture, p, ctx);
2019 ret &= test_EnumMonitors(torture, p, ctx);
2020 ret &= test_EnumPrintProcessors(torture, p, ctx);
2021 ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
2022 ret &= test_EnumPrinters(torture, p, ctx);
2023 ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
2024 ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
2025 ret &= test_OpenPrinter_badname(torture, p, "");
2026 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
2027 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
2028 ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
2029 ret &= test_OpenPrinter_badname(torture, p,
2030 talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
2033 ret &= test_AddPort(torture, p);
2034 ret &= test_EnumPorts_old(torture, p);
2035 ret &= test_EnumPrinters_old(torture, p);
2036 ret &= test_EnumPrinterDrivers_old(torture, p);