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-2010
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 "librpc/gen_ndr/ndr_misc.h"
27 #include "librpc/gen_ndr/ndr_spoolss.h"
28 #include "librpc/gen_ndr/ndr_spoolss_c.h"
29 #include "librpc/gen_ndr/ndr_winreg_c.h"
30 #include "librpc/gen_ndr/ndr_security.h"
31 #include "libcli/security/security.h"
32 #include "torture/rpc/rpc.h"
33 #include "param/param.h"
34 #include "lib/registry/registry.h"
36 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
37 #define TORTURE_PRINTER "torture_printer"
38 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
39 #define TORTURE_PRINTER_EX "torture_printer_ex"
41 struct test_spoolss_context {
42 /* print server handle */
43 struct policy_handle server_handle;
46 uint32_t port_count[3];
47 union spoolss_PortInfo *ports[3];
49 /* for EnumPrinterDrivers */
50 uint32_t driver_count[8];
51 union spoolss_DriverInfo *drivers[8];
53 /* for EnumMonitors */
54 uint32_t monitor_count[3];
55 union spoolss_MonitorInfo *monitors[3];
57 /* for EnumPrintProcessors */
58 uint32_t print_processor_count[2];
59 union spoolss_PrintProcessorInfo *print_processors[2];
61 /* for EnumPrinters */
62 uint32_t printer_count[6];
63 union spoolss_PrinterInfo *printers[6];
66 #define COMPARE_STRING(tctx, c,r,e) \
67 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
69 /* not every compiler supports __typeof__() */
71 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
72 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
73 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
75 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
76 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
80 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
83 #define COMPARE_UINT32(tctx, c, r, e) do {\
84 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
85 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
88 #define COMPARE_UINT64(tctx, c, r, e) do {\
89 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
90 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
94 #define COMPARE_NTTIME(tctx, c, r, e) do {\
95 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
96 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
99 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
101 if (!c.e && !r.e) { \
105 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
108 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
110 for (__i=0;c.e[__i] != NULL; __i++) { \
111 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
115 #define CHECK_ALIGN(size, n) do {\
117 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
118 size, n, size + n - (size % n));\
122 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
124 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, ic, needed, align) do { \
125 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
126 uint32_t size = ndr_size_##fn##_info(tctx, ic, level, count, info);\
127 uint32_t round_size = DO_ROUND(size, align);\
128 if (round_size != needed) {\
129 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
130 CHECK_ALIGN(size, align);\
135 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, ic, needed, align) do { \
136 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
137 uint32_t size = ndr_size_##fn##_info(tctx, ic, count, info);\
138 uint32_t round_size = DO_ROUND(size, align);\
139 if (round_size != needed) {\
140 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
141 CHECK_ALIGN(size, align);\
146 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, ic, needed, align) do { \
147 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
148 uint32_t size = ndr_size_##fn(info, level, ic, 0);\
149 uint32_t round_size = DO_ROUND(size, align);\
150 if (round_size != needed) {\
151 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
152 CHECK_ALIGN(size, align);\
157 static bool test_OpenPrinter_server(struct torture_context *tctx,
158 struct dcerpc_pipe *p,
159 struct policy_handle *server_handle)
162 struct spoolss_OpenPrinter op;
164 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
165 op.in.datatype = NULL;
166 op.in.devmode_ctr.devmode= NULL;
167 op.in.access_mask = 0;
168 op.out.handle = server_handle;
170 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
172 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
173 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
174 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
179 static bool test_EnumPorts(struct torture_context *tctx,
180 struct dcerpc_pipe *p,
181 struct test_spoolss_context *ctx)
184 struct spoolss_EnumPorts r;
185 uint16_t levels[] = { 1, 2 };
188 for (i=0;i<ARRAY_SIZE(levels);i++) {
189 int level = levels[i];
193 union spoolss_PortInfo *info;
195 r.in.servername = "";
199 r.out.needed = &needed;
200 r.out.count = &count;
203 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
205 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
206 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
207 if (W_ERROR_IS_OK(r.out.result)) {
208 /* TODO: do some more checks here */
211 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
212 "EnumPorts unexpected return code");
214 blob = data_blob_talloc(ctx, NULL, needed);
215 data_blob_clear(&blob);
217 r.in.offered = needed;
219 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
220 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
222 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
224 torture_assert(tctx, info, "EnumPorts returned no info");
226 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
228 ctx->port_count[level] = count;
229 ctx->ports[level] = info;
232 for (i=1;i<ARRAY_SIZE(levels);i++) {
233 int level = levels[i];
234 int old_level = levels[i-1];
235 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
236 "EnumPorts invalid value");
238 /* if the array sizes are not the same we would maybe segfault in the following code */
240 for (i=0;i<ARRAY_SIZE(levels);i++) {
241 int level = levels[i];
242 for (j=0;j<ctx->port_count[level];j++) {
243 union spoolss_PortInfo *cur = &ctx->ports[level][j];
244 union spoolss_PortInfo *ref = &ctx->ports[2][j];
247 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
250 /* level 2 is our reference, and it makes no sense to compare it to itself */
259 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
260 struct dcerpc_pipe *p,
261 struct test_spoolss_context *ctx,
262 const char *environment)
265 struct spoolss_GetPrintProcessorDirectory r;
280 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
283 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
289 for (i=0;i<ARRAY_SIZE(levels);i++) {
290 int level = levels[i].level;
293 r.in.server = levels[i].server;
294 r.in.environment = environment;
298 r.out.needed = &needed;
300 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
302 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
303 torture_assert_ntstatus_ok(tctx, status,
304 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
305 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
306 "GetPrintProcessorDirectory unexpected return code");
308 blob = data_blob_talloc(ctx, NULL, needed);
309 data_blob_clear(&blob);
311 r.in.offered = needed;
313 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
314 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
316 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
318 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
325 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
326 struct dcerpc_pipe *p,
327 struct test_spoolss_context *ctx,
328 const char *environment)
331 struct spoolss_GetPrinterDriverDirectory r;
346 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
349 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
355 for (i=0;i<ARRAY_SIZE(levels);i++) {
356 int level = levels[i].level;
359 r.in.server = levels[i].server;
360 r.in.environment = environment;
364 r.out.needed = &needed;
366 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
368 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
369 torture_assert_ntstatus_ok(tctx, status,
370 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
371 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
372 "GetPrinterDriverDirectory unexpected return code");
374 blob = data_blob_talloc(ctx, NULL, needed);
375 data_blob_clear(&blob);
377 r.in.offered = needed;
379 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
380 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
382 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
384 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
390 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
391 struct dcerpc_pipe *p,
392 struct test_spoolss_context *ctx,
393 const char *architecture)
396 struct spoolss_EnumPrinterDrivers r;
397 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
400 for (i=0;i<ARRAY_SIZE(levels);i++) {
401 int level = levels[i];
405 union spoolss_DriverInfo *info;
407 /* FIXME: gd, come back and fix "" as server, and handle
408 * priority of returned error codes in torture test and samba 3
411 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
412 r.in.environment = architecture;
416 r.out.needed = &needed;
417 r.out.count = &count;
420 torture_comment(tctx, "Testing EnumPrinterDrivers level %u (%s)\n", r.in.level, r.in.environment);
422 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
423 torture_assert_ntstatus_ok(tctx, status,
424 "dcerpc_spoolss_EnumPrinterDrivers failed");
425 if (W_ERROR_IS_OK(r.out.result)) {
426 /* TODO: do some more checks here */
429 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
430 blob = data_blob_talloc(ctx, NULL, needed);
431 data_blob_clear(&blob);
433 r.in.offered = needed;
435 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
436 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
439 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
441 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
443 ctx->driver_count[level] = count;
444 ctx->drivers[level] = info;
447 for (i=1;i<ARRAY_SIZE(levels);i++) {
448 int level = levels[i];
449 int old_level = levels[i-1];
451 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
452 "EnumPrinterDrivers invalid value");
455 for (i=0;i<ARRAY_SIZE(levels);i++) {
456 int level = levels[i];
458 for (j=0;j<ctx->driver_count[level];j++) {
459 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
460 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
464 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
467 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
468 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
469 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
470 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
471 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
472 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
475 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
476 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
477 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
478 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
479 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
480 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
481 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
482 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
483 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
484 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
487 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
488 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
489 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
490 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
491 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
492 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
493 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
494 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
495 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
496 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
497 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
500 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
501 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
502 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
503 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
504 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
505 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
506 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
507 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
508 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
511 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
512 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
513 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
514 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
515 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
516 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
517 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
518 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
519 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
520 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
521 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
522 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
523 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
524 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
525 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
526 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
527 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
530 /* level 8 is our reference, and it makes no sense to compare it to itself */
539 static bool test_EnumMonitors(struct torture_context *tctx,
540 struct dcerpc_pipe *p,
541 struct test_spoolss_context *ctx)
544 struct spoolss_EnumMonitors r;
545 uint16_t levels[] = { 1, 2 };
548 for (i=0;i<ARRAY_SIZE(levels);i++) {
549 int level = levels[i];
553 union spoolss_MonitorInfo *info;
555 r.in.servername = "";
559 r.out.needed = &needed;
560 r.out.count = &count;
563 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
565 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
566 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
567 if (W_ERROR_IS_OK(r.out.result)) {
568 /* TODO: do some more checks here */
571 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
572 "EnumMonitors failed");
574 blob = data_blob_talloc(ctx, NULL, needed);
575 data_blob_clear(&blob);
577 r.in.offered = needed;
579 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
580 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
582 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
584 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
586 ctx->monitor_count[level] = count;
587 ctx->monitors[level] = info;
590 for (i=1;i<ARRAY_SIZE(levels);i++) {
591 int level = levels[i];
592 int old_level = levels[i-1];
593 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
594 "EnumMonitors invalid value");
597 for (i=0;i<ARRAY_SIZE(levels);i++) {
598 int level = levels[i];
599 for (j=0;j<ctx->monitor_count[level];j++) {
600 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
601 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
604 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
607 /* level 2 is our reference, and it makes no sense to compare it to itself */
616 static bool test_EnumPrintProcessors(struct torture_context *tctx,
617 struct dcerpc_pipe *p,
618 struct test_spoolss_context *ctx,
619 const char *environment)
622 struct spoolss_EnumPrintProcessors r;
623 uint16_t levels[] = { 1 };
626 for (i=0;i<ARRAY_SIZE(levels);i++) {
627 int level = levels[i];
631 union spoolss_PrintProcessorInfo *info;
633 r.in.servername = "";
634 r.in.environment = environment;
638 r.out.needed = &needed;
639 r.out.count = &count;
642 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
644 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
645 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
646 if (W_ERROR_IS_OK(r.out.result)) {
647 /* TODO: do some more checks here */
650 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
651 "EnumPrintProcessors unexpected return code");
653 blob = data_blob_talloc(ctx, NULL, needed);
654 data_blob_clear(&blob);
656 r.in.offered = needed;
658 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
659 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
661 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
663 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
665 ctx->print_processor_count[level] = count;
666 ctx->print_processors[level] = info;
669 for (i=1;i<ARRAY_SIZE(levels);i++) {
670 int level = levels[i];
671 int old_level = levels[i-1];
672 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
673 "EnumPrintProcessors failed");
676 for (i=0;i<ARRAY_SIZE(levels);i++) {
677 int level = levels[i];
678 for (j=0;j<ctx->print_processor_count[level];j++) {
680 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
681 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
685 /* level 1 is our reference, and it makes no sense to compare it to itself */
694 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
695 struct dcerpc_pipe *p,
696 struct test_spoolss_context *ctx)
699 struct spoolss_EnumPrintProcDataTypes r;
700 uint16_t levels[] = { 1 };
703 for (i=0;i<ARRAY_SIZE(levels);i++) {
704 int level = levels[i];
708 union spoolss_PrintProcDataTypesInfo *info;
710 r.in.servername = "";
711 r.in.print_processor_name = "winprint";
715 r.out.needed = &needed;
716 r.out.count = &count;
719 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
721 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
722 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
723 if (W_ERROR_IS_OK(r.out.result)) {
724 /* TODO: do some more checks here */
727 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
728 "EnumPrintProcDataTypes unexpected return code");
730 blob = data_blob_talloc(ctx, NULL, needed);
731 data_blob_clear(&blob);
733 r.in.offered = needed;
735 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
736 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
738 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
740 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
748 static bool test_EnumPrinters(struct torture_context *tctx,
749 struct dcerpc_pipe *p,
750 struct test_spoolss_context *ctx)
752 struct spoolss_EnumPrinters r;
754 uint16_t levels[] = { 0, 1, 2, 4, 5 };
757 for (i=0;i<ARRAY_SIZE(levels);i++) {
758 int level = levels[i];
762 union spoolss_PrinterInfo *info;
764 r.in.flags = PRINTER_ENUM_LOCAL;
769 r.out.needed = &needed;
770 r.out.count = &count;
773 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
775 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
776 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
777 if (W_ERROR_IS_OK(r.out.result)) {
778 /* TODO: do some more checks here */
781 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
782 "EnumPrinters unexpected return code");
784 blob = data_blob_talloc(ctx, NULL, needed);
785 data_blob_clear(&blob);
787 r.in.offered = needed;
789 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
790 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
792 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
794 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
796 ctx->printer_count[level] = count;
797 ctx->printers[level] = info;
800 for (i=1;i<ARRAY_SIZE(levels);i++) {
801 int level = levels[i];
802 int old_level = levels[i-1];
803 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
804 "EnumPrinters invalid value");
807 for (i=0;i<ARRAY_SIZE(levels);i++) {
808 int level = levels[i];
809 for (j=0;j<ctx->printer_count[level];j++) {
810 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
811 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
814 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
815 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
816 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
817 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
818 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
819 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
820 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
821 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
822 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
823 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
824 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
825 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
826 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
827 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
828 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
829 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
830 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
831 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
832 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
833 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
834 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
835 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
836 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
837 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
838 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
839 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
840 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
841 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
842 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
845 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
846 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
847 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
848 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
851 /* level 2 is our reference, and it makes no sense to compare it to itself */
854 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
855 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
856 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
859 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
860 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
861 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
862 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
863 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
870 * - verify that the port of a printer was in the list returned by EnumPorts
876 static bool test_GetPrinterDriver2(struct torture_context *tctx,
877 struct dcerpc_pipe *p,
878 struct policy_handle *handle,
879 const char *driver_name,
880 const char *environment);
882 bool test_GetPrinter_level(struct torture_context *tctx,
883 struct dcerpc_pipe *p,
884 struct policy_handle *handle,
886 union spoolss_PrinterInfo *info)
888 struct spoolss_GetPrinter r;
891 r.in.handle = handle;
895 r.out.needed = &needed;
897 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
899 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter(p, tctx, &r),
900 "GetPrinter failed");
902 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
903 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
904 data_blob_clear(&blob);
906 r.in.offered = needed;
908 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter(p, tctx, &r),
909 "GetPrinter failed");
912 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
914 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
916 if (info && r.out.info) {
924 static bool test_GetPrinter(struct torture_context *tctx,
925 struct dcerpc_pipe *p,
926 struct policy_handle *handle,
927 const char *environment)
929 uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
932 for (i=0;i<ARRAY_SIZE(levels);i++) {
934 union spoolss_PrinterInfo info;
938 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, levels[i], &info),
939 "failed to call GetPrinter");
941 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
943 test_GetPrinterDriver2(tctx, p, handle, info.info2.drivername, environment),
944 "failed to call test_GetPrinterDriver2");
951 static bool test_SetPrinter(struct torture_context *tctx,
952 struct dcerpc_pipe *p,
953 struct policy_handle *handle,
954 struct spoolss_SetPrinterInfoCtr *info_ctr,
955 struct spoolss_DevmodeContainer *devmode_ctr,
956 struct sec_desc_buf *secdesc_ctr,
957 enum spoolss_PrinterControl command)
959 struct spoolss_SetPrinter r;
961 r.in.handle = handle;
962 r.in.info_ctr = info_ctr;
963 r.in.devmode_ctr = devmode_ctr;
964 r.in.secdesc_ctr = secdesc_ctr;
965 r.in.command = command;
967 torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
969 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
970 "failed to call SetPrinter");
971 torture_assert_werr_ok(tctx, r.out.result,
972 "failed to call SetPrinter");
977 static bool test_SetPrinter_errors(struct torture_context *tctx,
978 struct dcerpc_pipe *p,
979 struct policy_handle *handle)
981 struct spoolss_SetPrinter r;
982 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
985 struct spoolss_SetPrinterInfoCtr info_ctr;
986 struct spoolss_DevmodeContainer devmode_ctr;
987 struct sec_desc_buf secdesc_ctr;
990 info_ctr.info.info0 = NULL;
992 ZERO_STRUCT(devmode_ctr);
993 ZERO_STRUCT(secdesc_ctr);
995 r.in.handle = handle;
996 r.in.info_ctr = &info_ctr;
997 r.in.devmode_ctr = &devmode_ctr;
998 r.in.secdesc_ctr = &secdesc_ctr;
1001 torture_comment(tctx, "Testing SetPrinter all zero\n");
1003 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
1004 "failed to call SetPrinter");
1005 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1006 "failed to call SetPrinter");
1009 for (i=0; i < ARRAY_SIZE(levels); i++) {
1011 struct spoolss_SetPrinterInfo0 info0;
1012 struct spoolss_SetPrinterInfo1 info1;
1013 struct spoolss_SetPrinterInfo2 info2;
1014 struct spoolss_SetPrinterInfo3 info3;
1015 struct spoolss_SetPrinterInfo4 info4;
1016 struct spoolss_SetPrinterInfo5 info5;
1017 struct spoolss_SetPrinterInfo6 info6;
1018 struct spoolss_SetPrinterInfo7 info7;
1019 struct spoolss_SetPrinterInfo8 info8;
1020 struct spoolss_SetPrinterInfo9 info9;
1023 info_ctr.level = levels[i];
1024 switch (levels[i]) {
1027 info_ctr.info.info0 = &info0;
1031 info_ctr.info.info1 = &info1;
1035 info_ctr.info.info2 = &info2;
1039 info_ctr.info.info3 = &info3;
1043 info_ctr.info.info4 = &info4;
1047 info_ctr.info.info5 = &info5;
1051 info_ctr.info.info6 = &info6;
1055 info_ctr.info.info7 = &info7;
1059 info_ctr.info.info8 = &info8;
1063 info_ctr.info.info9 = &info9;
1067 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1068 info_ctr.level, r.in.command);
1070 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
1071 "failed to call SetPrinter");
1073 switch (r.in.command) {
1074 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1075 /* is ignored for all levels other then 0 */
1076 if (info_ctr.level > 0) {
1080 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1081 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1082 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1083 if (info_ctr.level > 0) {
1084 /* is invalid for all levels other then 0 */
1085 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1086 "unexpected error code returned");
1089 torture_assert_werr_ok(tctx, r.out.result,
1090 "failed to call SetPrinter with non 0 command");
1095 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1096 /* FIXME: gd needs further investigation */
1098 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1099 "unexpected error code returned");
1103 switch (info_ctr.level) {
1105 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1106 "unexpected error code returned");
1109 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1110 "unexpected error code returned");
1116 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1117 "unexpected error code returned");
1120 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1121 "unexpected error code returned");
1124 torture_assert_werr_ok(tctx, r.out.result,
1125 "failed to call SetPrinter");
1130 if (r.in.command < 5) {
1138 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1140 if ((r->level == 2) && (r->info.info2)) {
1141 r->info.info2->secdesc_ptr = 0;
1142 r->info.info2->devmode_ptr = 0;
1146 static bool test_PrinterInfo(struct torture_context *tctx,
1147 struct dcerpc_pipe *p,
1148 struct policy_handle *handle)
1151 struct spoolss_SetPrinter s;
1152 struct spoolss_GetPrinter q;
1153 struct spoolss_GetPrinter q0;
1154 struct spoolss_SetPrinterInfoCtr info_ctr;
1155 union spoolss_PrinterInfo info;
1156 struct spoolss_DevmodeContainer devmode_ctr;
1157 struct sec_desc_buf secdesc_ctr;
1162 uint32_t status_list[] = {
1163 /* these do not stick
1164 PRINTER_STATUS_PAUSED,
1165 PRINTER_STATUS_ERROR,
1166 PRINTER_STATUS_PENDING_DELETION, */
1167 PRINTER_STATUS_PAPER_JAM,
1168 PRINTER_STATUS_PAPER_OUT,
1169 PRINTER_STATUS_MANUAL_FEED,
1170 PRINTER_STATUS_PAPER_PROBLEM,
1171 PRINTER_STATUS_OFFLINE,
1172 PRINTER_STATUS_IO_ACTIVE,
1173 PRINTER_STATUS_BUSY,
1174 PRINTER_STATUS_PRINTING,
1175 PRINTER_STATUS_OUTPUT_BIN_FULL,
1176 PRINTER_STATUS_NOT_AVAILABLE,
1177 PRINTER_STATUS_WAITING,
1178 PRINTER_STATUS_PROCESSING,
1179 PRINTER_STATUS_INITIALIZING,
1180 PRINTER_STATUS_WARMING_UP,
1181 PRINTER_STATUS_TONER_LOW,
1182 PRINTER_STATUS_NO_TONER,
1183 PRINTER_STATUS_PAGE_PUNT,
1184 PRINTER_STATUS_USER_INTERVENTION,
1185 PRINTER_STATUS_OUT_OF_MEMORY,
1186 PRINTER_STATUS_DOOR_OPEN,
1187 PRINTER_STATUS_SERVER_UNKNOWN,
1188 PRINTER_STATUS_POWER_SAVE,
1189 /* these do not stick
1198 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1199 uint32_t attribute_list[] = {
1200 PRINTER_ATTRIBUTE_QUEUED,
1201 /* fails with WERR_INVALID_DATATYPE:
1202 PRINTER_ATTRIBUTE_DIRECT, */
1204 PRINTER_ATTRIBUTE_DEFAULT, */
1205 PRINTER_ATTRIBUTE_SHARED,
1207 PRINTER_ATTRIBUTE_NETWORK, */
1208 PRINTER_ATTRIBUTE_HIDDEN,
1209 PRINTER_ATTRIBUTE_LOCAL,
1210 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1211 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1212 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1213 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1215 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1216 /* fails with WERR_INVALID_DATATYPE:
1217 PRINTER_ATTRIBUTE_RAW_ONLY, */
1218 /* these do not stick
1219 PRINTER_ATTRIBUTE_PUBLISHED,
1220 PRINTER_ATTRIBUTE_FAX,
1221 PRINTER_ATTRIBUTE_TS,
1240 ZERO_STRUCT(devmode_ctr);
1241 ZERO_STRUCT(secdesc_ctr);
1243 s.in.handle = handle;
1245 s.in.info_ctr = &info_ctr;
1246 s.in.devmode_ctr = &devmode_ctr;
1247 s.in.secdesc_ctr = &secdesc_ctr;
1249 q.in.handle = handle;
1253 #define TESTGETCALL(call, r) \
1254 r.in.buffer = NULL; \
1256 r.out.needed = &needed; \
1257 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1258 if (!NT_STATUS_IS_OK(status)) { \
1259 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1260 r.in.level, nt_errstr(status), __location__); \
1264 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1265 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1266 data_blob_clear(&blob); \
1267 r.in.buffer = &blob; \
1268 r.in.offered = needed; \
1270 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1271 if (!NT_STATUS_IS_OK(status)) { \
1272 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1273 r.in.level, nt_errstr(status), __location__); \
1277 if (!W_ERROR_IS_OK(r.out.result)) { \
1278 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1279 r.in.level, win_errstr(r.out.result), __location__); \
1285 #define TESTSETCALL_EXP(call, r, err) \
1286 clear_info2(&info_ctr);\
1287 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1288 if (!NT_STATUS_IS_OK(status)) { \
1289 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1290 r.in.info_ctr->level, nt_errstr(status), __location__); \
1294 if (!W_ERROR_IS_OK(err)) { \
1295 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1296 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1297 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1302 if (!W_ERROR_IS_OK(r.out.result)) { \
1303 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1304 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1309 #define TESTSETCALL(call, r) \
1310 TESTSETCALL_EXP(call, r, WERR_OK)
1312 #define STRING_EQUAL(s1, s2, field) \
1313 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1314 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1315 #field, s2, __location__); \
1320 #define MEM_EQUAL(s1, s2, length, field) \
1321 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1322 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1323 #field, (const char *)s2, __location__); \
1328 #define INT_EQUAL(i1, i2, field) \
1330 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1331 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1336 #define SD_EQUAL(sd1, sd2, field) \
1337 if (!security_descriptor_equal(sd1, sd2)) { \
1338 torture_comment(tctx, "Failed to set %s (%s)\n", \
1339 #field, __location__); \
1344 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1345 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1346 q.in.level = lvl1; \
1347 TESTGETCALL(GetPrinter, q) \
1348 info_ctr.level = lvl1; \
1349 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1350 info_ctr.info.info ## lvl1->field1 = value;\
1351 TESTSETCALL_EXP(SetPrinter, s, err) \
1352 info_ctr.info.info ## lvl1->field1 = ""; \
1353 TESTGETCALL(GetPrinter, q) \
1354 info_ctr.info.info ## lvl1->field1 = value; \
1355 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1356 q.in.level = lvl2; \
1357 TESTGETCALL(GetPrinter, q) \
1358 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1359 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1362 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1363 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1366 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1367 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1368 q.in.level = lvl1; \
1369 TESTGETCALL(GetPrinter, q) \
1370 info_ctr.level = lvl1; \
1371 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1372 info_ctr.info.info ## lvl1->field1 = value; \
1373 TESTSETCALL(SetPrinter, s) \
1374 info_ctr.info.info ## lvl1->field1 = 0; \
1375 TESTGETCALL(GetPrinter, q) \
1376 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1377 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1378 q.in.level = lvl2; \
1379 TESTGETCALL(GetPrinter, q) \
1380 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1381 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1384 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1385 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1389 do { TESTGETCALL(GetPrinter, q0) } while (0);
1391 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1392 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1394 /* level 0 printername does not stick */
1395 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1396 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1397 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1398 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1399 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1400 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1401 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1402 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1403 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1404 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1405 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1406 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1407 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1408 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1409 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1411 /* servername can be set but does not stick
1412 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1413 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1414 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1417 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1418 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1419 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1420 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1421 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1423 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1424 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1425 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1426 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1427 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1428 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1429 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1430 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1431 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1432 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1434 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1435 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1437 (attribute_list[i] | default_attribute)
1439 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1441 (attribute_list[i] | default_attribute)
1443 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1445 (attribute_list[i] | default_attribute)
1447 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1449 (attribute_list[i] | default_attribute)
1451 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1453 (attribute_list[i] | default_attribute)
1455 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1457 (attribute_list[i] | default_attribute)
1459 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1461 (attribute_list[i] | default_attribute)
1463 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1465 (attribute_list[i] | default_attribute)
1467 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1469 (attribute_list[i] | default_attribute)
1471 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1473 (attribute_list[i] | default_attribute)
1475 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1477 (attribute_list[i] | default_attribute)
1479 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1481 (attribute_list[i] | default_attribute)
1485 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1486 /* level 2 sets do not stick
1487 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1488 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1489 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1490 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1491 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1492 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1495 /* priorities need to be between 0 and 99
1496 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1497 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1498 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1499 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1500 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1501 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1502 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1503 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1504 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1506 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1507 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1510 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1511 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1514 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1515 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1517 /* FIXME: gd also test devmode and secdesc behavior */
1520 /* verify composition of level 1 description field */
1521 const char *description;
1525 do { TESTGETCALL(GetPrinter, q0) } while (0);
1527 description = talloc_strdup(tctx, q0.out.info->info1.description);
1530 do { TESTGETCALL(GetPrinter, q0) } while (0);
1532 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1533 q0.out.info->info2.printername,
1534 q0.out.info->info2.drivername,
1535 q0.out.info->info2.location);
1537 do { STRING_EQUAL(description, tmp, "description")} while (0);
1543 #define torture_assert_sid_equal(torture_ctx,got,expected,cmt)\
1544 do { struct dom_sid *__got = (got), *__expected = (expected); \
1545 if (!dom_sid_equal(__got, __expected)) { \
1546 torture_result(torture_ctx, TORTURE_FAIL, \
1547 __location__": "#got" was %s, expected %s: %s", \
1548 dom_sid_string(torture_ctx, __got), dom_sid_string(torture_ctx, __expected), cmt); \
1553 static bool test_security_descriptor_equal(struct torture_context *tctx,
1554 const struct security_descriptor *sd1,
1555 const struct security_descriptor *sd2)
1562 torture_comment(tctx, "%s\n", __location__);
1566 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1567 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1569 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1570 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1572 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1573 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1574 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1575 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1578 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1579 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1580 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1581 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1588 static bool test_sd_set_level(struct torture_context *tctx,
1589 struct dcerpc_pipe *p,
1590 struct policy_handle *handle,
1592 struct security_descriptor *sd)
1594 struct spoolss_SetPrinterInfoCtr info_ctr;
1595 struct spoolss_DevmodeContainer devmode_ctr;
1596 struct sec_desc_buf secdesc_ctr;
1598 ZERO_STRUCT(devmode_ctr);
1599 ZERO_STRUCT(secdesc_ctr);
1603 union spoolss_PrinterInfo info;
1604 struct spoolss_SetPrinterInfo2 info2;
1605 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1607 info2.servername = info.info2.servername;
1608 info2.printername = info.info2.printername;
1609 info2.sharename = info.info2.sharename;
1610 info2.portname = info.info2.portname;
1611 info2.drivername = info.info2.drivername;
1612 info2.comment = info.info2.comment;
1613 info2.location = info.info2.location;
1614 info2.devmode_ptr = 0;
1615 info2.sepfile = info.info2.sepfile;
1616 info2.printprocessor = info.info2.printprocessor;
1617 info2.datatype = info.info2.datatype;
1618 info2.parameters = info.info2.parameters;
1619 info2.secdesc_ptr = 0;
1620 info2.attributes = info.info2.attributes;
1621 info2.priority = info.info2.priority;
1622 info2.defaultpriority = info.info2.defaultpriority;
1623 info2.starttime = info.info2.starttime;
1624 info2.untiltime = info.info2.untiltime;
1625 info2.status = info.info2.status;
1626 info2.cjobs = info.info2.cjobs;
1627 info2.averageppm = info.info2.averageppm;
1630 info_ctr.info.info2 = &info2;
1635 struct spoolss_SetPrinterInfo3 info3;
1637 info3.sec_desc_ptr = 0;
1640 info_ctr.info.info3 = &info3;
1648 secdesc_ctr.sd = sd;
1650 torture_assert(tctx,
1651 test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1656 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1657 struct dcerpc_pipe *p,
1658 struct policy_handle *handle)
1660 union spoolss_PrinterInfo info;
1661 struct security_descriptor *sd1, *sd2;
1664 /* just compare level 2 and level 3 */
1666 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1668 sd1 = info.info2.secdesc;
1670 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 3, &info), "");
1672 sd2 = info.info3.secdesc;
1674 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1675 "SD level 2 != SD level 3");
1678 /* query level 2, set level 2, query level 2 */
1680 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1682 sd1 = info.info2.secdesc;
1684 torture_assert(tctx, test_sd_set_level(tctx, p, handle, 2, sd1), "");
1686 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1688 sd2 = info.info2.secdesc;
1689 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1690 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1691 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1694 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1695 "SD level 2 != SD level 2 after SD has been set via level 2");
1698 /* query level 2, set level 3, query level 2 */
1700 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1702 sd1 = info.info2.secdesc;
1704 torture_assert(tctx, test_sd_set_level(tctx, p, handle, 3, sd1), "");
1706 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1708 sd2 = info.info2.secdesc;
1710 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1711 "SD level 2 != SD level 2 after SD has been set via level 3");
1713 /* set modified sd level 3, query level 2 */
1715 for (i=0; i < 93; i++) {
1716 struct security_ace a;
1717 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1718 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1720 a.size = 0; /* autogenerated */
1722 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1723 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1726 torture_assert(tctx, test_sd_set_level(tctx, p, handle, 3, sd1), "");
1728 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1729 sd2 = info.info2.secdesc;
1731 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1732 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1733 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1736 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1737 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1744 * wrapper call that saves original sd, runs tests, and restores sd
1747 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1748 struct dcerpc_pipe *p,
1749 struct policy_handle *handle)
1751 union spoolss_PrinterInfo info;
1752 struct security_descriptor *sd;
1755 torture_comment(tctx, "\nTesting Printer Security Descriptors\n");
1757 /* save original sd */
1759 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
1760 "failed to get initial security descriptor");
1762 sd = security_descriptor_copy(tctx, info.info2.secdesc);
1766 ret = test_PrinterInfo_SDs(tctx, p, handle);
1768 /* restore original sd */
1770 torture_assert(tctx, test_sd_set_level(tctx, p, handle, 3, sd),
1771 "failed to restore initial security descriptor");
1773 torture_comment(tctx, "Printer Security Descriptors test %s\n",
1774 ret ? "succeeded" : "failed");
1780 static bool test_devmode_set_level(struct torture_context *tctx,
1781 struct dcerpc_pipe *p,
1782 struct policy_handle *handle,
1784 struct spoolss_DeviceMode *devmode)
1786 struct spoolss_SetPrinterInfoCtr info_ctr;
1787 struct spoolss_DevmodeContainer devmode_ctr;
1788 struct sec_desc_buf secdesc_ctr;
1790 ZERO_STRUCT(devmode_ctr);
1791 ZERO_STRUCT(secdesc_ctr);
1795 union spoolss_PrinterInfo info;
1796 struct spoolss_SetPrinterInfo2 info2;
1797 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1799 info2.servername = info.info2.servername;
1800 info2.printername = info.info2.printername;
1801 info2.sharename = info.info2.sharename;
1802 info2.portname = info.info2.portname;
1803 info2.drivername = info.info2.drivername;
1804 info2.comment = info.info2.comment;
1805 info2.location = info.info2.location;
1806 info2.devmode_ptr = 0;
1807 info2.sepfile = info.info2.sepfile;
1808 info2.printprocessor = info.info2.printprocessor;
1809 info2.datatype = info.info2.datatype;
1810 info2.parameters = info.info2.parameters;
1811 info2.secdesc_ptr = 0;
1812 info2.attributes = info.info2.attributes;
1813 info2.priority = info.info2.priority;
1814 info2.defaultpriority = info.info2.defaultpriority;
1815 info2.starttime = info.info2.starttime;
1816 info2.untiltime = info.info2.untiltime;
1817 info2.status = info.info2.status;
1818 info2.cjobs = info.info2.cjobs;
1819 info2.averageppm = info.info2.averageppm;
1822 info_ctr.info.info2 = &info2;
1827 struct spoolss_SetPrinterInfo8 info8;
1829 info8.devmode_ptr = 0;
1832 info_ctr.info.info8 = &info8;
1840 devmode_ctr.devmode = devmode;
1842 torture_assert(tctx,
1843 test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1849 static bool test_devicemode_equal(struct torture_context *tctx,
1850 const struct spoolss_DeviceMode *d1,
1851 const struct spoolss_DeviceMode *d2)
1858 torture_comment(tctx, "%s\n", __location__);
1861 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
1862 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
1863 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
1864 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
1865 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
1866 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
1867 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
1868 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
1869 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
1870 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
1871 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
1872 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
1873 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
1874 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
1875 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
1876 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
1877 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
1878 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
1879 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
1880 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
1881 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
1882 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
1883 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
1884 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
1885 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
1886 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
1887 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
1888 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
1889 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
1890 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
1891 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
1892 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
1893 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
1894 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
1895 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
1900 static bool test_devicemode_full(struct torture_context *tctx,
1901 struct dcerpc_pipe *p,
1902 struct policy_handle *handle)
1904 struct spoolss_SetPrinter s;
1905 struct spoolss_GetPrinter q;
1906 struct spoolss_GetPrinter q0;
1907 struct spoolss_SetPrinterInfoCtr info_ctr;
1908 struct spoolss_SetPrinterInfo8 info8;
1909 union spoolss_PrinterInfo info;
1910 struct spoolss_DevmodeContainer devmode_ctr;
1911 struct sec_desc_buf secdesc_ctr;
1916 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1917 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1918 q.in.level = lvl1; \
1919 TESTGETCALL(GetPrinter, q) \
1920 info_ctr.level = lvl1; \
1922 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1923 } else if (lvl1 == 8) {\
1924 info_ctr.info.info ## lvl1 = &info8; \
1926 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
1927 devmode_ctr.devmode->field1 = value; \
1928 TESTSETCALL(SetPrinter, s) \
1929 TESTGETCALL(GetPrinter, q) \
1930 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
1931 q.in.level = lvl2; \
1932 TESTGETCALL(GetPrinter, q) \
1933 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
1936 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
1937 TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1940 ZERO_STRUCT(devmode_ctr);
1941 ZERO_STRUCT(secdesc_ctr);
1944 s.in.handle = handle;
1946 s.in.info_ctr = &info_ctr;
1947 s.in.devmode_ctr = &devmode_ctr;
1948 s.in.secdesc_ctr = &secdesc_ctr;
1950 q.in.handle = handle;
1955 const char *devicename;/* [charset(UTF16)] */
1956 enum spoolss_DeviceModeSpecVersion specversion;
1957 uint16_t driverversion;
1959 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
1963 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
1964 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
1965 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
1966 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
1967 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
1968 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
1969 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
1970 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
1971 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
1972 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
1973 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
1974 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
1975 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
1977 const char *formname;/* [charset(UTF16)] */
1979 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
1980 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
1981 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
1982 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
1983 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
1984 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
1985 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
1986 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
1987 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
1988 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
1989 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
1990 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
1991 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
1992 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
1997 static bool call_OpenPrinterEx(struct torture_context *tctx,
1998 struct dcerpc_pipe *p,
2000 struct spoolss_DeviceMode *devmode,
2001 struct policy_handle *handle);
2003 static bool test_ClosePrinter(struct torture_context *tctx,
2004 struct dcerpc_pipe *p,
2005 struct policy_handle *handle);
2007 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2008 struct dcerpc_pipe *p,
2009 struct policy_handle *handle,
2012 union spoolss_PrinterInfo info;
2013 struct spoolss_DeviceMode *devmode;
2014 struct spoolss_DeviceMode *devmode2;
2015 struct policy_handle handle_devmode;
2017 /* simply compare level8 and level2 devmode */
2019 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 8, &info), "");
2021 devmode = info.info8.devmode;
2023 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
2025 devmode2 = info.info2.devmode;
2027 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2028 "DM level 8 != DM level 2");
2031 /* set devicemode level 8 and see if it persists */
2033 devmode->copies = 93;
2034 devmode->formname = talloc_strdup(tctx, "Legal");
2036 torture_assert(tctx, test_devmode_set_level(tctx, p, handle, 8, devmode), "");
2038 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 8, &info), "");
2040 devmode2 = info.info8.devmode;
2042 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2043 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2045 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
2047 devmode2 = info.info2.devmode;
2049 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2050 "modified DM level 8 != DM level 2");
2053 /* set devicemode level 2 and see if it persists */
2055 devmode->copies = 39;
2056 devmode->formname = talloc_strdup(tctx, "Executive");
2058 torture_assert(tctx, test_devmode_set_level(tctx, p, handle, 2, devmode), "");
2060 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 8, &info), "");
2062 devmode2 = info.info8.devmode;
2064 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2065 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2067 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
2069 devmode2 = info.info2.devmode;
2071 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2072 "modified DM level 8 != DM level 2");
2075 /* check every single bit in public part of devicemode */
2077 torture_assert(tctx, test_devicemode_full(tctx, p, handle),
2078 "failed to set every single devicemode component");
2081 /* change formname upon open and see if it persists in getprinter calls */
2083 devmode->formname = talloc_strdup(tctx, "A4");
2084 devmode->copies = 42;
2086 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2087 "failed to open printer handle");
2089 torture_assert(tctx, test_GetPrinter_level(tctx, p, &handle_devmode, 8, &info), "");
2091 devmode2 = info.info8.devmode;
2093 if (strequal(devmode->devicename, devmode2->devicename)) {
2094 torture_comment(tctx, "devicenames are the same\n");
2096 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2097 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2100 if (strequal(devmode->formname, devmode2->formname)) {
2101 torture_warning(tctx, "formname are the same\n");
2103 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2104 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2107 if (devmode->copies == devmode2->copies) {
2108 torture_warning(tctx, "copies are the same\n");
2110 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2111 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2114 torture_assert(tctx, test_GetPrinter_level(tctx, p, &handle_devmode, 2, &info), "");
2116 devmode2 = info.info2.devmode;
2118 if (strequal(devmode->devicename, devmode2->devicename)) {
2119 torture_comment(tctx, "devicenames are the same\n");
2121 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2122 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2125 if (strequal(devmode->formname, devmode2->formname)) {
2126 torture_warning(tctx, "formname is the same\n");
2128 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2129 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2132 if (devmode->copies == devmode2->copies) {
2133 torture_warning(tctx, "copies are the same\n");
2135 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2136 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2139 test_ClosePrinter(tctx, p, &handle_devmode);
2145 * wrapper call that saves original devmode, runs tests, and restores devmode
2148 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2149 struct dcerpc_pipe *p,
2150 struct policy_handle *handle,
2153 union spoolss_PrinterInfo info;
2154 struct spoolss_DeviceMode *devmode;
2157 torture_comment(tctx, "\nTesting Printer Devicemodes\n");
2159 /* save original devmode */
2161 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 8, &info),
2162 "failed to get initial global devicemode");
2164 devmode = info.info8.devmode;
2168 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2170 /* restore original devmode */
2172 torture_assert(tctx, test_devmode_set_level(tctx, p, handle, 8, devmode),
2173 "failed to restore initial global device mode");
2175 torture_comment(tctx, "Printer Devicemodes test %s\n",
2176 ret ? "succeeded" : "failed");
2182 static bool test_ClosePrinter(struct torture_context *tctx,
2183 struct dcerpc_pipe *p,
2184 struct policy_handle *handle)
2187 struct spoolss_ClosePrinter r;
2189 r.in.handle = handle;
2190 r.out.handle = handle;
2192 torture_comment(tctx, "Testing ClosePrinter\n");
2194 status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
2195 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2196 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2201 static bool test_GetForm(struct torture_context *tctx,
2202 struct dcerpc_pipe *p,
2203 struct policy_handle *handle,
2204 const char *form_name,
2208 struct spoolss_GetForm r;
2211 r.in.handle = handle;
2212 r.in.form_name = form_name;
2216 r.out.needed = &needed;
2218 torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
2220 status = dcerpc_spoolss_GetForm(p, tctx, &r);
2221 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2223 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2224 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2225 data_blob_clear(&blob);
2226 r.in.buffer = &blob;
2227 r.in.offered = needed;
2228 status = dcerpc_spoolss_GetForm(p, tctx, &r);
2229 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2231 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2233 torture_assert(tctx, r.out.info, "No form info returned");
2236 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2238 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2243 static bool test_EnumForms(struct torture_context *tctx,
2244 struct dcerpc_pipe *p,
2245 struct policy_handle *handle, bool print_server)
2248 struct spoolss_EnumForms r;
2252 uint32_t levels[] = { 1, 2 };
2255 for (i=0; i<ARRAY_SIZE(levels); i++) {
2257 union spoolss_FormInfo *info;
2259 r.in.handle = handle;
2260 r.in.level = levels[i];
2263 r.out.needed = &needed;
2264 r.out.count = &count;
2267 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
2269 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
2270 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
2272 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2276 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
2277 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2279 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2281 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2282 data_blob_clear(&blob);
2283 r.in.buffer = &blob;
2284 r.in.offered = needed;
2286 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
2288 torture_assert(tctx, info, "No forms returned");
2290 for (j = 0; j < count; j++) {
2292 ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
2296 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
2298 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2300 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2306 static bool test_DeleteForm(struct torture_context *tctx,
2307 struct dcerpc_pipe *p,
2308 struct policy_handle *handle,
2309 const char *form_name)
2312 struct spoolss_DeleteForm r;
2314 r.in.handle = handle;
2315 r.in.form_name = form_name;
2317 status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
2319 torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
2321 torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
2326 static bool test_AddForm(struct torture_context *tctx,
2327 struct dcerpc_pipe *p,
2328 struct policy_handle *handle, bool print_server)
2330 struct spoolss_AddForm r;
2331 struct spoolss_AddFormInfo1 addform;
2332 const char *form_name = "testform3";
2336 r.in.handle = handle;
2338 r.in.info.info1 = &addform;
2339 addform.flags = SPOOLSS_FORM_USER;
2340 addform.form_name = form_name;
2341 addform.size.width = 50;
2342 addform.size.height = 25;
2343 addform.area.left = 5;
2344 addform.area.top = 10;
2345 addform.area.right = 45;
2346 addform.area.bottom = 15;
2348 status = dcerpc_spoolss_AddForm(p, tctx, &r);
2350 torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
2352 torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
2354 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
2357 struct spoolss_SetForm sf;
2358 struct spoolss_AddFormInfo1 setform;
2360 sf.in.handle = handle;
2361 sf.in.form_name = form_name;
2363 sf.in.info.info1= &setform;
2364 setform.flags = addform.flags;
2365 setform.form_name = addform.form_name;
2366 setform.size = addform.size;
2367 setform.area = addform.area;
2369 setform.size.width = 1234;
2371 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
2373 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
2375 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
2378 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
2381 struct spoolss_EnumForms e;
2382 union spoolss_FormInfo *info;
2387 e.in.handle = handle;
2391 e.out.needed = &needed;
2392 e.out.count = &count;
2395 torture_comment(tctx, "Testing EnumForms level 1\n");
2397 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
2398 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
2400 if (print_server && W_ERROR_EQUAL(e.out.result, WERR_BADFID))
2401 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2403 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
2405 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2406 data_blob_clear(&blob);
2407 e.in.buffer = &blob;
2408 e.in.offered = needed;
2410 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
2412 torture_assert(tctx, info, "No forms returned");
2414 for (j = 0; j < count; j++) {
2415 if (strequal(form_name, info[j].info1.form_name)) {
2421 torture_assert(tctx, found, "Newly added form not found in enum call");
2424 if (!test_DeleteForm(tctx, p, handle, form_name)) {
2431 static bool test_EnumPorts_old(struct torture_context *tctx,
2432 struct dcerpc_pipe *p)
2435 struct spoolss_EnumPorts r;
2438 union spoolss_PortInfo *info;
2440 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2441 dcerpc_server_name(p));
2445 r.out.needed = &needed;
2446 r.out.count = &count;
2449 torture_comment(tctx, "Testing EnumPorts\n");
2451 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
2453 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2455 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2456 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2457 data_blob_clear(&blob);
2458 r.in.buffer = &blob;
2459 r.in.offered = needed;
2461 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
2462 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2463 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2465 torture_assert(tctx, info, "No ports returned");
2468 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2470 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2475 static bool test_AddPort(struct torture_context *tctx,
2476 struct dcerpc_pipe *p)
2479 struct spoolss_AddPort r;
2481 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
2482 dcerpc_server_name(p));
2484 r.in.monitor_name = "foo";
2486 torture_comment(tctx, "Testing AddPort\n");
2488 status = dcerpc_spoolss_AddPort(p, tctx, &r);
2490 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
2492 /* win2k3 returns WERR_NOT_SUPPORTED */
2496 if (!W_ERROR_IS_OK(r.out.result)) {
2497 printf("AddPort failed - %s\n", win_errstr(r.out.result));
2506 static bool test_GetJob(struct torture_context *tctx,
2507 struct dcerpc_pipe *p,
2508 struct policy_handle *handle, uint32_t job_id)
2511 struct spoolss_GetJob r;
2512 union spoolss_JobInfo info;
2514 uint32_t levels[] = {1, 2 /* 3, 4 */};
2517 r.in.handle = handle;
2518 r.in.job_id = job_id;
2522 r.out.needed = &needed;
2525 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
2527 status = dcerpc_spoolss_GetJob(p, tctx, &r);
2528 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
2530 for (i = 0; i < ARRAY_SIZE(levels); i++) {
2532 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
2536 r.in.level = levels[i];
2540 status = dcerpc_spoolss_GetJob(p, tctx, &r);
2541 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2543 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2544 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2545 data_blob_clear(&blob);
2546 r.in.buffer = &blob;
2547 r.in.offered = needed;
2549 status = dcerpc_spoolss_GetJob(p, tctx, &r);
2550 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2553 torture_assert(tctx, r.out.info, "No job info returned");
2554 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
2556 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2562 static bool test_SetJob(struct torture_context *tctx,
2563 struct dcerpc_pipe *p,
2564 struct policy_handle *handle, uint32_t job_id,
2565 enum spoolss_JobControl command)
2568 struct spoolss_SetJob r;
2570 r.in.handle = handle;
2571 r.in.job_id = job_id;
2573 r.in.command = command;
2576 case SPOOLSS_JOB_CONTROL_PAUSE:
2577 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
2579 case SPOOLSS_JOB_CONTROL_RESUME:
2580 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
2582 case SPOOLSS_JOB_CONTROL_CANCEL:
2583 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
2585 case SPOOLSS_JOB_CONTROL_RESTART:
2586 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
2588 case SPOOLSS_JOB_CONTROL_DELETE:
2589 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
2591 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
2592 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
2594 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
2595 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
2597 case SPOOLSS_JOB_CONTROL_RETAIN:
2598 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
2600 case SPOOLSS_JOB_CONTROL_RELEASE:
2601 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
2604 torture_comment(tctx, "Testing SetJob\n");
2608 status = dcerpc_spoolss_SetJob(p, tctx, &r);
2609 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
2610 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
2615 static bool test_AddJob(struct torture_context *tctx,
2616 struct dcerpc_pipe *p,
2617 struct policy_handle *handle)
2620 struct spoolss_AddJob r;
2624 r.in.handle = handle;
2626 r.out.needed = &needed;
2627 r.in.buffer = r.out.buffer = NULL;
2629 torture_comment(tctx, "Testing AddJob\n");
2631 status = dcerpc_spoolss_AddJob(p, tctx, &r);
2632 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
2636 status = dcerpc_spoolss_AddJob(p, tctx, &r);
2637 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
2643 static bool test_EnumJobs(struct torture_context *tctx,
2644 struct dcerpc_pipe *p,
2645 struct policy_handle *handle)
2648 struct spoolss_EnumJobs r;
2651 union spoolss_JobInfo *info;
2653 r.in.handle = handle;
2655 r.in.numjobs = 0xffffffff;
2659 r.out.needed = &needed;
2660 r.out.count = &count;
2663 torture_comment(tctx, "Testing EnumJobs\n");
2665 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
2667 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
2669 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2671 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2672 data_blob_clear(&blob);
2673 r.in.buffer = &blob;
2674 r.in.offered = needed;
2676 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
2678 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
2679 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
2680 torture_assert(tctx, info, "No jobs returned");
2682 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2684 for (j = 0; j < count; j++) {
2686 torture_assert(tctx, test_GetJob(tctx, p, handle, info[j].info1.job_id),
2687 "failed to call test_GetJob");
2690 if (!torture_setting_bool(tctx, "samba3", false)) {
2691 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
2692 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
2697 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
2703 static bool test_DoPrintTest(struct torture_context *tctx,
2704 struct dcerpc_pipe *p,
2705 struct policy_handle *handle)
2709 struct spoolss_StartDocPrinter s;
2710 struct spoolss_DocumentInfo1 info1;
2711 struct spoolss_StartPagePrinter sp;
2712 struct spoolss_WritePrinter w;
2713 struct spoolss_EndPagePrinter ep;
2714 struct spoolss_EndDocPrinter e;
2717 uint32_t num_written;
2719 torture_comment(tctx, "Testing StartDocPrinter\n");
2721 s.in.handle = handle;
2723 s.in.info.info1 = &info1;
2724 s.out.job_id = &job_id;
2725 info1.document_name = "TorturePrintJob";
2726 info1.output_file = NULL;
2727 info1.datatype = "RAW";
2729 status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
2730 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
2731 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
2733 for (i=1; i < 4; i++) {
2734 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
2736 sp.in.handle = handle;
2738 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
2739 torture_assert_ntstatus_ok(tctx, status,
2740 "dcerpc_spoolss_StartPagePrinter failed");
2741 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
2743 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
2745 w.in.handle = handle;
2746 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
2747 w.out.num_written = &num_written;
2749 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
2750 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
2751 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
2753 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
2755 ep.in.handle = handle;
2757 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
2758 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
2759 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
2762 torture_comment(tctx, "Testing EndDocPrinter\n");
2764 e.in.handle = handle;
2766 status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
2767 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
2768 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
2770 ret &= test_AddJob(tctx, p, handle);
2771 ret &= test_EnumJobs(tctx, p, handle);
2773 ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
2778 static bool test_PausePrinter(struct torture_context *tctx,
2779 struct dcerpc_pipe *p,
2780 struct policy_handle *handle)
2783 struct spoolss_SetPrinter r;
2784 struct spoolss_SetPrinterInfoCtr info_ctr;
2785 struct spoolss_DevmodeContainer devmode_ctr;
2786 struct sec_desc_buf secdesc_ctr;
2789 info_ctr.info.info0 = NULL;
2791 ZERO_STRUCT(devmode_ctr);
2792 ZERO_STRUCT(secdesc_ctr);
2794 r.in.handle = handle;
2795 r.in.info_ctr = &info_ctr;
2796 r.in.devmode_ctr = &devmode_ctr;
2797 r.in.secdesc_ctr = &secdesc_ctr;
2798 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
2800 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
2802 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2804 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2806 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2811 static bool test_ResumePrinter(struct torture_context *tctx,
2812 struct dcerpc_pipe *p,
2813 struct policy_handle *handle)
2816 struct spoolss_SetPrinter r;
2817 struct spoolss_SetPrinterInfoCtr info_ctr;
2818 struct spoolss_DevmodeContainer devmode_ctr;
2819 struct sec_desc_buf secdesc_ctr;
2822 info_ctr.info.info0 = NULL;
2824 ZERO_STRUCT(devmode_ctr);
2825 ZERO_STRUCT(secdesc_ctr);
2827 r.in.handle = handle;
2828 r.in.info_ctr = &info_ctr;
2829 r.in.devmode_ctr = &devmode_ctr;
2830 r.in.secdesc_ctr = &secdesc_ctr;
2831 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
2833 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2835 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2837 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2839 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2844 static bool test_GetPrinterData(struct torture_context *tctx,
2845 struct dcerpc_pipe *p,
2846 struct policy_handle *handle,
2847 const char *value_name,
2848 enum winreg_Type *type_p,
2853 struct spoolss_GetPrinterData r;
2855 enum winreg_Type type;
2856 union spoolss_PrinterData data;
2858 r.in.handle = handle;
2859 r.in.value_name = value_name;
2861 r.out.needed = &needed;
2863 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
2865 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
2867 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2868 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2870 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2871 r.in.offered = needed;
2872 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
2873 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2874 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2877 torture_assert_werr_ok(tctx, r.out.result,
2878 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
2880 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2887 *data_p = r.out.data;
2897 static bool test_GetPrinterDataEx(struct torture_context *tctx,
2898 struct dcerpc_pipe *p,
2899 struct policy_handle *handle,
2900 const char *key_name,
2901 const char *value_name,
2902 enum winreg_Type *type_p,
2907 struct spoolss_GetPrinterDataEx r;
2908 enum winreg_Type type;
2910 union spoolss_PrinterData data;
2912 r.in.handle = handle;
2913 r.in.key_name = key_name;
2914 r.in.value_name = value_name;
2917 r.out.needed = &needed;
2918 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
2920 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
2921 r.in.key_name, r.in.value_name);
2923 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2924 if (!NT_STATUS_IS_OK(status)) {
2925 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
2926 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
2927 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
2929 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2932 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2933 r.in.offered = needed;
2934 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
2935 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2936 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2939 torture_assert_werr_ok(tctx, r.out.result,
2940 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
2942 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2949 *data_p = r.out.data;
2959 static bool test_GetPrinterData_list(struct torture_context *tctx,
2960 struct dcerpc_pipe *p,
2961 struct policy_handle *handle)
2963 const char *list[] = {
2967 /* "NetPopup", not on w2k8 */
2968 /* "NetPopupToComputer", not on w2k8 */
2971 "DefaultSpoolDirectory",
2975 /* "OSVersionEx", not on s3 */
2980 for (i=0; i < ARRAY_SIZE(list); i++) {
2981 enum winreg_Type type, type_ex;
2982 uint8_t *data, *data_ex;
2983 uint32_t needed, needed_ex;
2985 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, list[i], &type, &data, &needed),
2986 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
2987 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
2988 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
2989 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
2990 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
2991 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
2997 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
2998 struct policy_handle *handle)
3001 struct spoolss_EnumPrinterData r;
3004 r.in.handle = handle;
3005 r.in.enum_index = 0;
3008 uint32_t value_size = 0;
3009 uint32_t data_size = 0;
3010 enum winreg_Type type = 0;
3012 r.in.value_offered = value_size;
3013 r.out.value_needed = &value_size;
3014 r.in.data_offered = data_size;
3015 r.out.data_needed = &data_size;
3018 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
3020 torture_comment(tctx, "Testing EnumPrinterData\n");
3022 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
3024 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
3025 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3028 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData");
3030 r.in.value_offered = value_size;
3031 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
3032 r.in.data_offered = data_size;
3033 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
3035 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
3037 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
3038 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
3042 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterData failed");
3044 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, r.out.value_name, NULL, NULL, NULL),
3045 talloc_asprintf(tctx, "failed to call GetPrinterData for %s\n", r.out.value_name));
3047 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", r.out.value_name, NULL, NULL, NULL),
3048 talloc_asprintf(tctx, "failed to call GetPrinterDataEx on PrinterDriverData for %s\n", r.out.value_name));
3052 } while (W_ERROR_IS_OK(r.out.result));
3057 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3058 struct dcerpc_pipe *p,
3059 struct policy_handle *handle,
3060 const char *key_name)
3062 struct spoolss_EnumPrinterDataEx r;
3063 struct spoolss_PrinterEnumValues *info;
3067 r.in.handle = handle;
3068 r.in.key_name = key_name;
3070 r.out.needed = &needed;
3071 r.out.count = &count;
3074 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3076 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
3077 "EnumPrinterDataEx failed");
3078 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3079 r.in.offered = needed;
3080 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
3081 "EnumPrinterDataEx failed");
3084 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3086 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3092 static bool test_DeletePrinterData(struct torture_context *tctx,
3093 struct dcerpc_pipe *p,
3094 struct policy_handle *handle,
3095 const char *value_name)
3098 struct spoolss_DeletePrinterData r;
3100 r.in.handle = handle;
3101 r.in.value_name = value_name;
3103 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
3106 status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
3108 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
3109 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
3114 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
3115 struct dcerpc_pipe *p,
3116 struct policy_handle *handle,
3117 const char *key_name,
3118 const char *value_name)
3120 struct spoolss_DeletePrinterDataEx r;
3122 r.in.handle = handle;
3123 r.in.key_name = key_name;
3124 r.in.value_name = value_name;
3126 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
3127 r.in.key_name, r.in.value_name);
3129 torture_assert_ntstatus_ok(tctx,
3130 dcerpc_spoolss_DeletePrinterDataEx(p, tctx, &r),
3131 "DeletePrinterDataEx failed");
3132 torture_assert_werr_ok(tctx, r.out.result,
3133 "DeletePrinterDataEx failed");
3138 static bool test_DeletePrinterKey(struct torture_context *tctx,
3139 struct dcerpc_pipe *p,
3140 struct policy_handle *handle,
3141 const char *key_name)
3143 struct spoolss_DeletePrinterKey r;
3145 r.in.handle = handle;
3146 r.in.key_name = key_name;
3148 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
3150 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
3151 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
3155 torture_assert_ntstatus_ok(tctx,
3156 dcerpc_spoolss_DeletePrinterKey(p, tctx, &r),
3157 "DeletePrinterKey failed");
3158 torture_assert_werr_ok(tctx, r.out.result,
3159 "DeletePrinterKey failed");
3164 static bool test_SetPrinterData(struct torture_context *tctx,
3165 struct dcerpc_pipe *p,
3166 struct policy_handle *handle)
3169 struct spoolss_SetPrinterData r;
3170 const char *values[] = {
3174 /* FIXME: not working with s3 atm. */
3180 /* FIXME: not working with s3 atm. */
3187 for (i=0; i < ARRAY_SIZE(values); i++) {
3189 enum winreg_Type type;
3194 torture_assert(tctx,
3195 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3196 "REG_SZ", "dog", &r.in.type, &blob), "");
3198 r.in.handle = handle;
3199 r.in.value_name = values[i];
3200 r.in.data = blob.data;
3201 r.in.offered = blob.length;
3203 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
3206 status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
3208 torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
3209 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterData failed");
3211 if (!test_GetPrinterData(tctx, p, handle, r.in.value_name, &type, &data, &needed)) {
3215 torture_assert_int_equal(tctx, r.in.type, type, "type mismatch");
3216 torture_assert_int_equal(tctx, r.in.offered, needed, "size mismatch");
3217 torture_assert_mem_equal(tctx, blob.data, data, needed, "buffer mismatch");
3219 if (!test_DeletePrinterData(tctx, p, handle, r.in.value_name)) {
3227 static bool test_EnumPrinterKey(struct torture_context *tctx,
3228 struct dcerpc_pipe *p,
3229 struct policy_handle *handle,
3230 const char *key_name,
3231 const char ***array);
3233 static bool test_SetPrinterDataEx(struct torture_context *tctx,
3234 struct dcerpc_pipe *p,
3235 struct policy_handle *handle,
3236 const char *key_name,
3237 const char *value_name,
3238 enum winreg_Type type,
3243 struct spoolss_SetPrinterDataEx r;
3245 r.in.handle = handle;
3246 r.in.key_name = key_name;
3247 r.in.value_name = value_name;
3250 r.in.offered = offered;
3252 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
3253 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
3255 status = dcerpc_spoolss_SetPrinterDataEx(p, tctx, &r);
3257 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
3258 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
3263 #define TOP_LEVEL_PRINTER_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"
3265 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
3266 struct dcerpc_pipe *p,
3267 struct policy_handle *handle)
3269 struct winreg_OpenHKLM r;
3271 r.in.system_name = NULL;
3272 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3273 r.out.handle = handle;
3275 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
3277 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM(p, tctx, &r), "OpenHKLM failed");
3278 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
3283 static void init_winreg_String(struct winreg_String *name, const char *s)
3287 name->name_len = 2 * (strlen_m(s) + 1);
3288 name->name_size = name->name_len;
3291 name->name_size = 0;
3295 static bool test_winreg_OpenKey(struct torture_context *tctx,
3296 struct dcerpc_pipe *p,
3297 struct policy_handle *hive_handle,
3298 const char *keyname,
3299 struct policy_handle *key_handle)
3301 struct winreg_OpenKey r;
3303 r.in.parent_handle = hive_handle;
3304 init_winreg_String(&r.in.keyname, keyname);
3305 r.in.unknown = 0x00000000;
3306 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3307 r.out.handle = key_handle;
3309 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
3311 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey(p, tctx, &r), "OpenKey failed");
3312 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
3317 static bool test_winreg_CloseKey(struct torture_context *tctx,
3318 struct dcerpc_pipe *p,
3319 struct policy_handle *handle)
3321 struct winreg_CloseKey r;
3323 r.in.handle = handle;
3324 r.out.handle = handle;
3326 torture_comment(tctx, "Testing winreg_CloseKey\n");
3328 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey(p, tctx, &r), "CloseKey failed");
3329 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
3334 static bool test_winreg_QueryValue(struct torture_context *tctx,
3335 struct dcerpc_pipe *p,
3336 struct policy_handle *handle,
3337 const char *value_name,
3338 enum winreg_Type *type_p,
3339 uint32_t *data_size_p,
3340 uint32_t *data_length_p,
3343 struct winreg_QueryValue r;
3344 enum winreg_Type type = REG_NONE;
3345 uint32_t data_size = 0;
3346 uint32_t data_length = 0;
3347 struct winreg_String valuename;
3349 init_winreg_String(&valuename, value_name);
3351 r.in.handle = handle;
3352 r.in.value_name = &valuename;
3354 r.in.data_size = &data_size;
3355 r.in.data_length = &data_length;
3357 r.out.data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
3358 r.out.data_size = &data_size;
3359 r.out.data_length = &data_length;
3361 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
3363 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue(p, tctx, &r), "QueryValue failed");
3364 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3365 *r.in.data_size = *r.out.data_size;
3366 r.out.data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
3367 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue(p, tctx, &r), "QueryValue failed");
3369 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
3372 *type_p = *r.out.type;
3375 *data_size_p = *r.out.data_size;
3377 if (data_length_p) {
3378 *data_length_p = *r.out.data_length;
3381 *data_p = r.out.data;
3387 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
3388 struct dcerpc_pipe *p,
3389 struct policy_handle *handle,
3390 const char *printername,
3391 struct dcerpc_pipe *winreg_pipe,
3392 struct policy_handle *hive_handle)
3394 const char *value_name = "dog";
3395 const char *keys[] = {
3399 /* FIXME: not working with s3 atm. */
3400 "torturedataex_with_subkey\\subkey",
3401 "torturedataex_with_subkey\\subkey:0",
3402 "torturedataex_with_subkey\\subkey:1",
3403 "torturedataex_with_subkey\\subkey\\subsubkey",
3404 "torturedataex_with_subkey\\subkey\\subsubkey:0",
3405 "torturedataex_with_subkey\\subkey\\subsubkey:1",
3409 /* FIXME: not working with s3 atm. */
3416 enum winreg_Type types[] = {
3421 const char *str = "abcdefghijklmnopqrstuvwxzy";
3425 for (i=0; i < ARRAY_SIZE(keys); i++) {
3426 for (t=0; t < ARRAY_SIZE(types); t++) {
3427 for (s=0; s < strlen(str); s++) {
3431 enum winreg_Type type;
3432 const char *string = talloc_strndup(tctx, str, s);
3433 DATA_BLOB blob = data_blob_string_const(string);
3434 const char **subkeys;
3437 uint32_t needed, offered = 0;
3443 offered = blob.length;
3446 torture_assert(tctx,
3447 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3448 "REG_SZ", string, &type, &data), "");
3449 offered = data.length;
3450 /*strlen_m_term(data.string)*2;*/
3453 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
3456 torture_assert(tctx,
3457 test_SetPrinterDataEx(tctx, p, handle, keys[i], value_name, types[t], data.data, offered),
3458 "failed to call SetPrinterDataEx");
3460 if (!test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &data_out, &needed)) {
3463 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
3464 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
3465 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
3467 if (winreg_pipe && hive_handle) {
3468 const char *printer_key;
3469 struct policy_handle key_handle;
3470 enum winreg_Type w_type;
3471 uint32_t w_size, w_length;
3474 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
3475 TOP_LEVEL_PRINTER_KEY, printername, keys[i]);
3477 torture_assert(tctx, test_winreg_OpenKey(tctx, winreg_pipe, hive_handle, printer_key, &key_handle), "");
3479 torture_assert(tctx,
3480 test_winreg_QueryValue(tctx, winreg_pipe, &key_handle, value_name, &w_type, &w_size, &w_length, &w_data), "");
3482 test_winreg_CloseKey(tctx, winreg_pipe, &key_handle);
3484 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
3485 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
3486 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
3489 key = talloc_strdup(tctx, keys[i]);
3491 if (!test_EnumPrinterDataEx(tctx, p, handle, keys[i])) {
3495 if (!test_DeletePrinterDataEx(tctx, p, handle, keys[i], value_name)) {
3499 c = strchr(key, '\\');
3503 /* we have subkeys */
3507 if (!test_EnumPrinterKey(tctx, p, handle, key, &subkeys)) {
3511 for (i=0; subkeys && subkeys[i]; i++) {
3513 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[i]);
3515 if (!test_DeletePrinterKey(tctx, p, handle, current_key)) {
3520 if (!test_DeletePrinterKey(tctx, p, handle, key)) {
3525 if (!test_DeletePrinterKey(tctx, p, handle, key)) {
3536 static bool test_PrinterData_winreg(struct torture_context *tctx,
3537 struct dcerpc_pipe *p,
3538 struct policy_handle *handle,
3539 const char *printer_name)
3541 struct dcerpc_pipe *p2;
3543 struct policy_handle hive_handle;
3545 torture_assert_ntstatus_ok(tctx,
3546 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
3547 "could not open winreg pipe");
3549 torture_assert(tctx, test_winreg_OpenHKLM(tctx, p2, &hive_handle), "");
3551 ret = test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, p2, &hive_handle);
3553 test_winreg_CloseKey(tctx, p2, &hive_handle);
3560 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
3561 struct dcerpc_pipe *p,
3562 struct policy_handle *handle,
3563 uint32_t *change_id)
3565 enum winreg_Type type;
3569 torture_assert(tctx,
3570 test_GetPrinterData(tctx, p, handle, "ChangeID", &type, &data, &needed),
3571 "failed to call GetPrinterData");
3573 torture_assert(tctx, type == REG_DWORD, "unexpected type");
3574 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
3576 *change_id = IVAL(data, 0);
3581 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
3582 struct dcerpc_pipe *p,
3583 struct policy_handle *handle,
3584 uint32_t *change_id)
3586 enum winreg_Type type;
3590 torture_assert(tctx,
3591 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
3592 "failed to call GetPrinterData");
3594 torture_assert(tctx, type == REG_DWORD, "unexpected type");
3595 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
3597 *change_id = IVAL(data, 0);
3602 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
3603 struct dcerpc_pipe *p,
3604 struct policy_handle *handle,
3605 uint32_t *change_id)
3607 union spoolss_PrinterInfo info;
3609 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 0, &info),
3610 "failed to query Printer level 0");
3612 *change_id = info.info0.change_id;
3617 static bool test_ChangeID(struct torture_context *tctx,
3618 struct dcerpc_pipe *p,
3619 struct policy_handle *handle)
3621 uint32_t change_id, change_id_ex, change_id_info;
3622 uint32_t change_id2, change_id_ex2, change_id_info2;
3623 union spoolss_PrinterInfo info;
3624 const char *comment;
3627 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
3629 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3630 "failed to query for ChangeID");
3631 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3632 "failed to query for ChangeID");
3633 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3634 "failed to query for ChangeID");
3636 torture_assert_int_equal(tctx, change_id, change_id_ex,
3637 "change_ids should all be equal");
3638 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
3639 "change_ids should all be equal");
3642 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
3644 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3645 "failed to query for ChangeID");
3646 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
3647 "failed to query Printer level 2");
3648 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3649 "failed to query for ChangeID");
3650 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3651 "failed to query for ChangeID");
3652 torture_assert_int_equal(tctx, change_id, change_id_ex,
3653 "change_id should not have changed");
3654 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
3655 "change_id should not have changed");
3658 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
3660 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3661 "failed to query for ChangeID");
3662 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3663 "failed to query for ChangeID");
3664 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3665 "failed to query for ChangeID");
3666 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
3667 "failed to query Printer level 2");
3668 comment = talloc_strdup(tctx, info.info2.comment);
3671 struct spoolss_SetPrinterInfoCtr info_ctr;
3672 struct spoolss_DevmodeContainer devmode_ctr;
3673 struct sec_desc_buf secdesc_ctr;
3674 struct spoolss_SetPrinterInfo2 info2;
3676 ZERO_STRUCT(info_ctr);
3677 ZERO_STRUCT(devmode_ctr);
3678 ZERO_STRUCT(secdesc_ctr);
3680 info2.servername = info.info2.servername;
3681 info2.printername = info.info2.printername;
3682 info2.sharename = info.info2.sharename;
3683 info2.portname = info.info2.portname;
3684 info2.drivername = info.info2.drivername;
3685 info2.comment = "torture_comment";
3686 info2.location = info.info2.location;
3687 info2.devmode_ptr = 0;
3688 info2.sepfile = info.info2.sepfile;
3689 info2.printprocessor = info.info2.printprocessor;
3690 info2.datatype = info.info2.datatype;
3691 info2.parameters = info.info2.parameters;
3692 info2.secdesc_ptr = 0;
3693 info2.attributes = info.info2.attributes;
3694 info2.priority = info.info2.priority;
3695 info2.defaultpriority = info.info2.defaultpriority;
3696 info2.starttime = info.info2.starttime;
3697 info2.untiltime = info.info2.untiltime;
3698 info2.status = info.info2.status;
3699 info2.cjobs = info.info2.cjobs;
3700 info2.averageppm = info.info2.averageppm;
3703 info_ctr.info.info2 = &info2;
3705 torture_assert(tctx, test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
3706 "failed to call SetPrinter");
3708 info2.comment = comment;
3710 torture_assert(tctx, test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
3711 "failed to call SetPrinter");
3715 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id2),
3716 "failed to query for ChangeID");
3717 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
3718 "failed to query for ChangeID");
3719 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info2),
3720 "failed to query for ChangeID");
3722 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
3723 "change_ids should all be equal");
3724 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
3725 "change_ids should all be equal");
3727 torture_assert(tctx, (change_id < change_id2),
3728 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3729 change_id2, change_id));
3730 torture_assert(tctx, (change_id_ex < change_id_ex2),
3731 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3732 change_id_ex2, change_id_ex));
3733 torture_assert(tctx, (change_id_info < change_id_info2),
3734 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3735 change_id_info2, change_id_info));
3740 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
3741 struct dcerpc_pipe *p,
3742 struct policy_handle *handle)
3745 struct dcerpc_binding *b;
3746 struct dcerpc_pipe *p2;
3747 struct spoolss_ClosePrinter cp;
3749 /* only makes sense on SMB */
3750 if (p->conn->transport.transport != NCACN_NP) {
3754 torture_comment(tctx, "testing close on secondary pipe\n");
3756 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
3757 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
3759 status = dcerpc_secondary_connection(p, &p2, b);
3760 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
3762 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
3763 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
3765 cp.in.handle = handle;
3766 cp.out.handle = handle;
3768 status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
3769 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
3770 "ERROR: Allowed close on secondary connection");
3772 torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
3773 "Unexpected fault code");
3780 static bool test_OpenPrinter_badname(struct torture_context *tctx,
3781 struct dcerpc_pipe *p, const char *name)
3784 struct spoolss_OpenPrinter op;
3785 struct spoolss_OpenPrinterEx opEx;
3786 struct policy_handle handle;
3789 op.in.printername = name;
3790 op.in.datatype = NULL;
3791 op.in.devmode_ctr.devmode= NULL;
3792 op.in.access_mask = 0;
3793 op.out.handle = &handle;
3795 torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
3797 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
3798 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
3799 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
3800 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
3801 name, win_errstr(op.out.result));
3804 if (W_ERROR_IS_OK(op.out.result)) {
3805 ret &=test_ClosePrinter(tctx, p, &handle);
3808 opEx.in.printername = name;
3809 opEx.in.datatype = NULL;
3810 opEx.in.devmode_ctr.devmode = NULL;
3811 opEx.in.access_mask = 0;
3813 opEx.in.userlevel.level1 = NULL;
3814 opEx.out.handle = &handle;
3816 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
3818 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
3819 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
3820 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
3821 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
3822 name, win_errstr(opEx.out.result));
3825 if (W_ERROR_IS_OK(opEx.out.result)) {
3826 ret &=test_ClosePrinter(tctx, p, &handle);
3832 static bool test_OpenPrinter(struct torture_context *tctx,
3833 struct dcerpc_pipe *p,
3835 const char *environment)
3838 struct spoolss_OpenPrinter r;
3839 struct policy_handle handle;
3842 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
3843 r.in.datatype = NULL;
3844 r.in.devmode_ctr.devmode= NULL;
3845 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3846 r.out.handle = &handle;
3848 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
3850 status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
3852 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
3854 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
3856 if (!test_GetPrinter(tctx, p, &handle, environment)) {
3860 if (!torture_setting_bool(tctx, "samba3", false)) {
3861 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
3866 if (!test_ClosePrinter(tctx, p, &handle)) {
3873 static bool call_OpenPrinterEx(struct torture_context *tctx,
3874 struct dcerpc_pipe *p,
3876 struct spoolss_DeviceMode *devmode,
3877 struct policy_handle *handle)
3879 struct spoolss_OpenPrinterEx r;
3880 struct spoolss_UserLevel1 userlevel1;
3883 if (name && name[0]) {
3884 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
3885 dcerpc_server_name(p), name);
3887 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
3888 dcerpc_server_name(p));
3891 r.in.datatype = NULL;
3892 r.in.devmode_ctr.devmode= devmode;
3893 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3895 r.in.userlevel.level1 = &userlevel1;
3896 r.out.handle = handle;
3898 userlevel1.size = 1234;
3899 userlevel1.client = "hello";
3900 userlevel1.user = "spottyfoot!";
3901 userlevel1.build = 1;
3902 userlevel1.major = 2;
3903 userlevel1.minor = 3;
3904 userlevel1.processor = 4;
3906 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
3908 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
3910 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
3912 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
3917 static bool test_OpenPrinterEx(struct torture_context *tctx,
3918 struct dcerpc_pipe *p,
3920 const char *environment)
3922 struct policy_handle handle;
3925 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
3929 if (!test_PrinterInfo_SD(tctx, p, &handle)) {
3933 if (!test_GetPrinter(tctx, p, &handle, environment)) {
3937 if (!test_EnumForms(tctx, p, &handle, false)) {
3941 if (!test_AddForm(tctx, p, &handle, false)) {
3945 if (!test_EnumPrinterData(tctx, p, &handle)) {
3949 if (!test_EnumPrinterDataEx(tctx, p, &handle, "PrinterDriverData")) {
3953 if (!test_printer_keys(tctx, p, &handle)) {
3957 if (!test_PausePrinter(tctx, p, &handle)) {
3961 if (!test_DoPrintTest(tctx, p, &handle)) {
3965 if (!test_ResumePrinter(tctx, p, &handle)) {
3969 if (!test_SetPrinterData(tctx, p, &handle)) {
3973 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
3977 if (!torture_setting_bool(tctx, "samba3", false)) {
3978 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
3983 if (!test_ClosePrinter(tctx, p, &handle)) {
3990 static bool test_EnumPrinters_old(struct torture_context *tctx,
3991 struct dcerpc_pipe *p,
3992 const char *environment)
3994 struct spoolss_EnumPrinters r;
3996 uint16_t levels[] = {1, 2, 4, 5};
4000 for (i=0;i<ARRAY_SIZE(levels);i++) {
4001 union spoolss_PrinterInfo *info;
4006 r.in.flags = PRINTER_ENUM_LOCAL;
4008 r.in.level = levels[i];
4011 r.out.needed = &needed;
4012 r.out.count = &count;
4015 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
4017 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
4018 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
4020 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4021 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4022 data_blob_clear(&blob);
4023 r.in.buffer = &blob;
4024 r.in.offered = needed;
4025 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
4028 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
4030 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
4032 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4035 torture_comment(tctx, "No printers returned\n");
4039 for (j=0;j<count;j++) {
4040 if (r.in.level == 1) {
4041 char *unc = talloc_strdup(tctx, info[j].info1.name);
4044 if (unc[0] == '\\' && unc[1] == '\\') {
4047 slash = strchr(unc, '\\');
4052 if (!test_OpenPrinter(tctx, p, name, environment)) {
4055 if (!test_OpenPrinterEx(tctx, p, name, environment)) {
4065 static bool test_GetPrinterDriver(struct torture_context *tctx,
4066 struct dcerpc_pipe *p,
4067 struct policy_handle *handle,
4068 const char *driver_name)
4070 struct spoolss_GetPrinterDriver r;
4073 r.in.handle = handle;
4074 r.in.architecture = "W32X86";
4078 r.out.needed = &needed;
4080 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
4082 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
4083 "failed to call GetPrinterDriver");
4084 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4085 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4086 data_blob_clear(&blob);
4087 r.in.buffer = &blob;
4088 r.in.offered = needed;
4089 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
4090 "failed to call GetPrinterDriver");
4093 torture_assert_werr_ok(tctx, r.out.result,
4094 "failed to call GetPrinterDriver");
4096 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4101 static bool test_GetPrinterDriver2(struct torture_context *tctx,
4102 struct dcerpc_pipe *p,
4103 struct policy_handle *handle,
4104 const char *driver_name,
4105 const char *architecture)
4107 struct spoolss_GetPrinterDriver2 r;
4108 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
4110 uint32_t server_major_version;
4111 uint32_t server_minor_version;
4114 r.in.handle = handle;
4115 r.in.architecture = architecture;
4116 r.in.client_major_version = 3;
4117 r.in.client_minor_version = 0;
4118 r.out.needed = &needed;
4119 r.out.server_major_version = &server_major_version;
4120 r.out.server_minor_version = &server_minor_version;
4122 for (i=0;i<ARRAY_SIZE(levels);i++) {
4126 r.in.level = levels[i];
4128 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
4129 driver_name, r.in.level);
4131 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
4132 "failed to call GetPrinterDriver2");
4133 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4134 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4135 data_blob_clear(&blob);
4136 r.in.buffer = &blob;
4137 r.in.offered = needed;
4138 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
4139 "failed to call GetPrinterDriver2");
4142 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
4143 switch (r.in.level) {
4152 torture_assert_werr_ok(tctx, r.out.result,
4153 "failed to call GetPrinterDriver2");
4155 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4161 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
4162 struct dcerpc_pipe *p,
4163 const char *environment)
4165 struct spoolss_EnumPrinterDrivers r;
4167 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
4170 for (i=0;i<ARRAY_SIZE(levels);i++) {
4174 union spoolss_DriverInfo *info;
4176 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
4177 r.in.environment = environment;
4178 r.in.level = levels[i];
4181 r.out.needed = &needed;
4182 r.out.count = &count;
4185 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
4187 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
4189 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
4191 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4192 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4193 data_blob_clear(&blob);
4194 r.in.buffer = &blob;
4195 r.in.offered = needed;
4196 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
4199 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
4201 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
4204 torture_comment(tctx, "No printer drivers returned\n");
4208 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4214 static bool test_DeletePrinter(struct torture_context *tctx,
4215 struct dcerpc_pipe *p,
4216 struct policy_handle *handle)
4218 struct spoolss_DeletePrinter r;
4220 torture_comment(tctx, "Testing DeletePrinter\n");
4222 r.in.handle = handle;
4224 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter(p, tctx, &r),
4225 "failed to delete printer");
4226 torture_assert_werr_ok(tctx, r.out.result,
4227 "failed to delete printer");
4232 static bool test_EnumPrinters_findname(struct torture_context *tctx,
4233 struct dcerpc_pipe *p,
4239 struct spoolss_EnumPrinters e;
4241 union spoolss_PrinterInfo *info;
4252 e.out.count = &count;
4254 e.out.needed = &needed;
4256 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
4257 "failed to enum printers");
4259 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
4260 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4261 data_blob_clear(&blob);
4262 e.in.buffer = &blob;
4263 e.in.offered = needed;
4265 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
4266 "failed to enum printers");
4269 torture_assert_werr_ok(tctx, e.out.result,
4270 "failed to enum printers");
4272 for (i=0; i < count; i++) {
4274 const char *current = NULL;
4279 current = info[i].info1.name;
4283 if (strequal(current, name)) {
4288 p = strrchr(current, '\\');
4291 torture_warning(tctx,
4292 "server returns printername %s incl. servername although we did not set servername", current);
4295 if (strequal(p, name)) {
4305 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
4306 struct dcerpc_pipe *p,
4307 const char *printername,
4311 struct spoolss_AddPrinter r;
4312 struct spoolss_AddPrinterEx rex;
4313 struct spoolss_SetPrinterInfoCtr info_ctr;
4314 struct spoolss_SetPrinterInfo1 info1;
4315 struct spoolss_DevmodeContainer devmode_ctr;
4316 struct sec_desc_buf secdesc_ctr;
4317 struct spoolss_UserLevelCtr userlevel_ctr;
4318 struct policy_handle handle;
4321 ZERO_STRUCT(devmode_ctr);
4322 ZERO_STRUCT(secdesc_ctr);
4323 ZERO_STRUCT(userlevel_ctr);
4326 torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
4328 /* try to add printer to wellknown printer list (level 1) */
4330 userlevel_ctr.level = 1;
4332 info_ctr.info.info1 = &info1;
4335 rex.in.server = NULL;
4336 rex.in.info_ctr = &info_ctr;
4337 rex.in.devmode_ctr = &devmode_ctr;
4338 rex.in.secdesc_ctr = &secdesc_ctr;
4339 rex.in.userlevel_ctr = &userlevel_ctr;
4340 rex.out.handle = &handle;
4343 r.in.info_ctr = &info_ctr;
4344 r.in.devmode_ctr = &devmode_ctr;
4345 r.in.secdesc_ctr = &secdesc_ctr;
4346 r.out.handle = &handle;
4348 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4349 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4350 "failed to add printer");
4351 result = ex ? rex.out.result : r.out.result;
4352 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
4353 "unexpected result code");
4355 info1.name = printername;
4356 info1.flags = PRINTER_ATTRIBUTE_SHARED;
4358 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4359 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4360 "failed to add printer");
4361 result = ex ? rex.out.result : r.out.result;
4362 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4363 "unexpected result code");
4365 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
4366 better do a real check to see the printer is really there */
4368 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4369 PRINTER_ENUM_NETWORK, 1,
4372 "failed to enum printers");
4374 torture_assert(tctx, found, "failed to find newly added printer");
4378 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4379 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4380 "failed to add printer");
4381 result = ex ? rex.out.result : r.out.result;
4382 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4383 "unexpected result code");
4385 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
4386 better do a real check to see the printer has really been removed
4387 from the well known printer list */
4391 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4392 PRINTER_ENUM_NETWORK, 1,
4395 "failed to enum printers");
4397 torture_assert(tctx, !found, "printer still in well known printer list");
4402 static bool test_AddPrinter_normal(struct torture_context *tctx,
4403 struct dcerpc_pipe *p,
4404 struct policy_handle *handle_p,
4405 const char *printername,
4406 const char *drivername,
4407 const char *portname,
4411 struct spoolss_AddPrinter r;
4412 struct spoolss_AddPrinterEx rex;
4413 struct spoolss_SetPrinterInfoCtr info_ctr;
4414 struct spoolss_SetPrinterInfo2 info2;
4415 struct spoolss_DevmodeContainer devmode_ctr;
4416 struct sec_desc_buf secdesc_ctr;
4417 struct spoolss_UserLevelCtr userlevel_ctr;
4418 struct policy_handle handle;
4420 bool existing_printer_deleted = false;
4422 ZERO_STRUCT(devmode_ctr);
4423 ZERO_STRUCT(secdesc_ctr);
4424 ZERO_STRUCT(userlevel_ctr);
4426 torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
4428 userlevel_ctr.level = 1;
4430 rex.in.server = NULL;
4431 rex.in.info_ctr = &info_ctr;
4432 rex.in.devmode_ctr = &devmode_ctr;
4433 rex.in.secdesc_ctr = &secdesc_ctr;
4434 rex.in.userlevel_ctr = &userlevel_ctr;
4435 rex.out.handle = &handle;
4438 r.in.info_ctr = &info_ctr;
4439 r.in.devmode_ctr = &devmode_ctr;
4440 r.in.secdesc_ctr = &secdesc_ctr;
4441 r.out.handle = &handle;
4445 /* try to add printer to printer list (level 2) */
4449 info_ctr.info.info2 = &info2;
4452 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4453 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4454 "failed to add printer");
4455 result = ex ? rex.out.result : r.out.result;
4456 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
4457 "unexpected result code");
4459 info2.printername = printername;
4461 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4462 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4463 "failed to add printer");
4464 result = ex ? rex.out.result : r.out.result;
4466 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
4467 struct policy_handle printer_handle;
4469 if (existing_printer_deleted) {
4470 torture_fail(tctx, "already deleted printer still existing?");
4473 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
4474 "failed to open printer handle");
4476 torture_assert(tctx, test_DeletePrinter(tctx, p, &printer_handle),
4477 "failed to delete printer");
4479 torture_assert(tctx, test_ClosePrinter(tctx, p, &printer_handle),
4480 "failed to close server handle");
4482 existing_printer_deleted = true;
4487 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
4488 "unexpected result code");
4490 info2.portname = portname;
4492 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4493 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4494 "failed to add printer");
4495 result = ex ? rex.out.result : r.out.result;
4496 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
4497 "unexpected result code");
4499 info2.drivername = drivername;
4501 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4502 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4503 "failed to add printer");
4504 result = ex ? rex.out.result : r.out.result;
4506 /* w2k8r2 allows to add printer w/o defining printprocessor */
4508 if (!W_ERROR_IS_OK(result)) {
4509 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
4510 "unexpected result code");
4512 info2.printprocessor = "winprint";
4514 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4515 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4516 "failed to add printer");
4517 result = ex ? rex.out.result : r.out.result;
4518 torture_assert_werr_ok(tctx, result,
4519 "failed to add printer");
4524 /* we are paranoid, really check if the printer is there now */
4526 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4527 PRINTER_ENUM_LOCAL, 1,
4530 "failed to enum printers");
4531 torture_assert(tctx, found, "failed to find newly added printer");
4533 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4534 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4535 "failed to add printer");
4536 result = ex ? rex.out.result : r.out.result;
4537 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4538 "unexpected result code");
4543 static bool test_AddPrinterEx(struct torture_context *tctx,
4544 struct dcerpc_pipe *p,
4545 struct policy_handle *handle_p,
4546 const char *printername,
4547 const char *drivername,
4548 const char *portname)
4552 if (!torture_setting_bool(tctx, "samba3", false)) {
4553 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
4554 torture_comment(tctx, "failed to add printer to well known list\n");
4559 if (!test_AddPrinter_normal(tctx, p, handle_p,
4560 printername, drivername, portname,
4562 torture_comment(tctx, "failed to add printer to printer list\n");
4569 static bool test_AddPrinter(struct torture_context *tctx,
4570 struct dcerpc_pipe *p,
4571 struct policy_handle *handle_p,
4572 const char *printername,
4573 const char *drivername,
4574 const char *portname)
4578 if (!torture_setting_bool(tctx, "samba3", false)) {
4579 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
4580 torture_comment(tctx, "failed to add printer to well known list\n");
4585 if (!test_AddPrinter_normal(tctx, p, handle_p,
4586 printername, drivername, portname,
4588 torture_comment(tctx, "failed to add printer to printer list\n");
4595 static bool test_printer_info(struct torture_context *tctx,
4596 struct dcerpc_pipe *p,
4597 struct policy_handle *handle)
4601 if (torture_setting_bool(tctx, "samba3", false)) {
4602 torture_skip(tctx, "skipping printer info cross tests against samba 3");
4605 if (!test_PrinterInfo(tctx, p, handle)) {
4609 if (!test_SetPrinter_errors(tctx, p, handle)) {
4616 static bool test_EnumPrinterKey(struct torture_context *tctx,
4617 struct dcerpc_pipe *p,
4618 struct policy_handle *handle,
4619 const char *key_name,
4620 const char ***array)
4622 struct spoolss_EnumPrinterKey r;
4623 uint32_t needed = 0;
4624 union spoolss_KeyNames key_buffer;
4625 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
4629 r.in.handle = handle;
4630 r.in.key_name = key_name;
4631 r.out.key_buffer = &key_buffer;
4632 r.out.needed = &needed;
4633 r.out._ndr_size = &_ndr_size;
4635 for (i=0; i < ARRAY_SIZE(offered); i++) {
4637 if (offered[i] < 0 && needed) {
4641 r.in.offered = needed + offered[i];
4643 r.in.offered = offered[i];
4646 ZERO_STRUCT(key_buffer);
4648 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
4650 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
4651 "failed to call EnumPrinterKey");
4652 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4654 torture_assert(tctx, (_ndr_size == r.in.offered/2),
4655 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
4656 _ndr_size, r.in.offered/2));
4658 r.in.offered = needed;
4659 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
4660 "failed to call EnumPrinterKey");
4663 if (offered[i] > 0) {
4664 torture_assert_werr_ok(tctx, r.out.result,
4665 "failed to call EnumPrinterKey");
4668 torture_assert(tctx, (_ndr_size == r.in.offered/2),
4669 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
4670 _ndr_size, r.in.offered/2));
4672 torture_assert(tctx, (*r.out.needed <= r.in.offered),
4673 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
4675 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
4676 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
4678 if (key_buffer.string_array) {
4679 uint32_t calc_needed = 0;
4681 for (s=0; key_buffer.string_array[s]; s++) {
4682 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
4684 if (!key_buffer.string_array[0]) {
4689 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
4690 "EnumPrinterKey unexpected size");
4695 *array = key_buffer.string_array;
4701 bool test_printer_keys(struct torture_context *tctx,
4702 struct dcerpc_pipe *p,
4703 struct policy_handle *handle)
4705 const char **key_array = NULL;
4708 torture_comment(tctx, "\nTesting Printer Keys\n");
4710 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, "", &key_array),
4711 "failed to call test_EnumPrinterKey");
4713 for (i=0; key_array && key_array[i]; i++) {
4714 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, key_array[i], NULL),
4715 "failed to call test_EnumPrinterKey");
4717 for (i=0; key_array && key_array[i]; i++) {
4718 torture_assert(tctx, test_EnumPrinterDataEx(tctx, p, handle, key_array[i]),
4719 "failed to call test_EnumPrinterDataEx");
4725 static bool test_one_printer(struct torture_context *tctx,
4726 struct dcerpc_pipe *p,
4727 struct policy_handle *handle,
4732 if (!test_printer_info(tctx, p, handle)) {
4736 if (!test_PrinterInfo_SD(tctx, p, handle)) {
4740 if (!test_PrinterInfo_DevMode(tctx, p, handle, name)) {
4744 if (!test_ChangeID(tctx, p, handle)) {
4748 if (!test_printer_keys(tctx, p, handle)) {
4752 if (!test_SetPrinterDataEx_matrix(tctx, p, handle, name, NULL, NULL)) {
4756 if (!test_PrinterData_winreg(tctx, p, handle, name)) {
4763 static bool test_printer(struct torture_context *tctx,
4764 struct dcerpc_pipe *p)
4767 struct policy_handle handle[2];
4769 const char *drivername = "Microsoft XPS Document Writer";
4770 const char *portname = "LPT1:";
4772 /* test printer created via AddPrinter */
4774 if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
4778 if (!test_one_printer(tctx, p, &handle[0], TORTURE_PRINTER)) {
4782 if (!test_DeletePrinter(tctx, p, &handle[0])) {
4786 if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
4787 TORTURE_PRINTER, &found)) {
4791 torture_assert(tctx, !found, "deleted printer still there");
4793 /* test printer created via AddPrinterEx */
4795 if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
4799 if (!test_one_printer(tctx, p, &handle[1], TORTURE_PRINTER_EX)) {
4803 if (!test_DeletePrinter(tctx, p, &handle[1])) {
4807 if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
4808 TORTURE_PRINTER_EX, &found)) {
4812 torture_assert(tctx, !found, "deleted printer still there");
4817 static bool test_architecture_buffer(struct torture_context *tctx,
4818 struct dcerpc_pipe *p)
4820 struct spoolss_OpenPrinterEx r;
4821 struct spoolss_UserLevel1 u1;
4822 struct policy_handle handle;
4823 uint32_t architectures[] = {
4824 PROCESSOR_ARCHITECTURE_INTEL,
4825 PROCESSOR_ARCHITECTURE_IA64,
4826 PROCESSOR_ARCHITECTURE_AMD64
4831 for (i=0; i < ARRAY_SIZE(architectures); i++) {
4833 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
4841 u1.processor = architectures[i];
4843 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
4844 r.in.datatype = NULL;
4845 r.in.devmode_ctr.devmode= NULL;
4846 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4848 r.in.userlevel.level1 = &u1;
4849 r.out.handle = &handle;
4851 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx(p, tctx, &r), "");
4852 torture_assert_werr_ok(tctx, r.out.result, "");
4855 struct spoolss_EnumPrinters e;
4857 union spoolss_PrinterInfo *info;
4859 e.in.flags = PRINTER_ENUM_LOCAL;
4864 e.out.count = &count;
4866 e.out.needed = &needed[i];
4868 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e), "");
4870 torture_comment(tctx, "needed was %d\n", needed[i]);
4874 torture_assert(tctx, test_ClosePrinter(tctx, p, &handle), "");
4877 for (i=1; i < ARRAY_SIZE(architectures); i++) {
4878 if (needed[i-1] != needed[i]) {
4880 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
4881 needed[i-1], architectures[i-1], needed[i], architectures[i]));
4888 bool torture_rpc_spoolss(struct torture_context *torture)
4891 struct dcerpc_pipe *p;
4893 struct test_spoolss_context *ctx;
4894 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
4896 status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
4897 if (!NT_STATUS_IS_OK(status)) {
4901 ctx = talloc_zero(torture, struct test_spoolss_context);
4903 ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
4904 ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle);
4905 ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
4906 ret &= test_AddForm(torture, p, &ctx->server_handle, true);
4907 ret &= test_EnumPorts(torture, p, ctx);
4908 ret &= test_GetPrinterDriverDirectory(torture, p, ctx, environment);
4909 ret &= test_GetPrintProcessorDirectory(torture, p, ctx, environment);
4910 ret &= test_EnumPrinterDrivers(torture, p, ctx, environment);
4911 ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
4912 ret &= test_EnumMonitors(torture, p, ctx);
4913 ret &= test_EnumPrintProcessors(torture, p, ctx, environment);
4914 ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
4915 ret &= test_EnumPrinters(torture, p, ctx);
4916 ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
4917 ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
4918 ret &= test_OpenPrinter_badname(torture, p, "");
4919 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
4920 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
4921 ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
4922 ret &= test_OpenPrinter_badname(torture, p,
4923 talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
4926 ret &= test_AddPort(torture, p);
4927 ret &= test_EnumPorts_old(torture, p);
4928 ret &= test_EnumPrinters_old(torture, p, environment);
4929 ret &= test_EnumPrinterDrivers_old(torture, p, environment);
4930 ret &= test_architecture_buffer(torture, p);
4935 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
4937 struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
4939 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
4940 "printer", &ndr_table_spoolss);
4942 torture_rpc_tcase_add_test(tcase, "printer", test_printer);