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_PrinterEnumValues **info_p)
3064 struct spoolss_EnumPrinterDataEx r;
3065 struct spoolss_PrinterEnumValues *info;
3069 r.in.handle = handle;
3070 r.in.key_name = key_name;
3072 r.out.needed = &needed;
3073 r.out.count = &count;
3076 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3078 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
3079 "EnumPrinterDataEx failed");
3080 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3081 r.in.offered = needed;
3082 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
3083 "EnumPrinterDataEx failed");
3086 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3088 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3101 static bool test_DeletePrinterData(struct torture_context *tctx,
3102 struct dcerpc_pipe *p,
3103 struct policy_handle *handle,
3104 const char *value_name)
3107 struct spoolss_DeletePrinterData r;
3109 r.in.handle = handle;
3110 r.in.value_name = value_name;
3112 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
3115 status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
3117 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
3118 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
3123 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
3124 struct dcerpc_pipe *p,
3125 struct policy_handle *handle,
3126 const char *key_name,
3127 const char *value_name)
3129 struct spoolss_DeletePrinterDataEx r;
3131 r.in.handle = handle;
3132 r.in.key_name = key_name;
3133 r.in.value_name = value_name;
3135 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
3136 r.in.key_name, r.in.value_name);
3138 torture_assert_ntstatus_ok(tctx,
3139 dcerpc_spoolss_DeletePrinterDataEx(p, tctx, &r),
3140 "DeletePrinterDataEx failed");
3141 torture_assert_werr_ok(tctx, r.out.result,
3142 "DeletePrinterDataEx failed");
3147 static bool test_DeletePrinterKey(struct torture_context *tctx,
3148 struct dcerpc_pipe *p,
3149 struct policy_handle *handle,
3150 const char *key_name)
3152 struct spoolss_DeletePrinterKey r;
3154 r.in.handle = handle;
3155 r.in.key_name = key_name;
3157 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
3159 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
3160 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
3164 torture_assert_ntstatus_ok(tctx,
3165 dcerpc_spoolss_DeletePrinterKey(p, tctx, &r),
3166 "DeletePrinterKey failed");
3167 torture_assert_werr_ok(tctx, r.out.result,
3168 "DeletePrinterKey failed");
3173 static bool test_SetPrinterData(struct torture_context *tctx,
3174 struct dcerpc_pipe *p,
3175 struct policy_handle *handle)
3178 struct spoolss_SetPrinterData r;
3179 const char *values[] = {
3183 /* FIXME: not working with s3 atm. */
3189 /* FIXME: not working with s3 atm. */
3196 for (i=0; i < ARRAY_SIZE(values); i++) {
3198 enum winreg_Type type;
3203 torture_assert(tctx,
3204 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3205 "REG_SZ", "dog", &r.in.type, &blob), "");
3207 r.in.handle = handle;
3208 r.in.value_name = values[i];
3209 r.in.data = blob.data;
3210 r.in.offered = blob.length;
3212 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
3215 status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
3217 torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
3218 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterData failed");
3220 if (!test_GetPrinterData(tctx, p, handle, r.in.value_name, &type, &data, &needed)) {
3224 torture_assert_int_equal(tctx, r.in.type, type, "type mismatch");
3225 torture_assert_int_equal(tctx, r.in.offered, needed, "size mismatch");
3226 torture_assert_mem_equal(tctx, blob.data, data, needed, "buffer mismatch");
3228 if (!test_DeletePrinterData(tctx, p, handle, r.in.value_name)) {
3236 static bool test_EnumPrinterKey(struct torture_context *tctx,
3237 struct dcerpc_pipe *p,
3238 struct policy_handle *handle,
3239 const char *key_name,
3240 const char ***array);
3242 static bool test_SetPrinterDataEx(struct torture_context *tctx,
3243 struct dcerpc_pipe *p,
3244 struct policy_handle *handle,
3245 const char *key_name,
3246 const char *value_name,
3247 enum winreg_Type type,
3252 struct spoolss_SetPrinterDataEx r;
3254 r.in.handle = handle;
3255 r.in.key_name = key_name;
3256 r.in.value_name = value_name;
3259 r.in.offered = offered;
3261 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
3262 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
3264 status = dcerpc_spoolss_SetPrinterDataEx(p, tctx, &r);
3266 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
3267 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
3272 #define TOP_LEVEL_PRINTER_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"
3274 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
3275 struct dcerpc_pipe *p,
3276 struct policy_handle *handle)
3278 struct winreg_OpenHKLM r;
3280 r.in.system_name = NULL;
3281 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3282 r.out.handle = handle;
3284 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
3286 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM(p, tctx, &r), "OpenHKLM failed");
3287 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
3292 static void init_winreg_String(struct winreg_String *name, const char *s)
3296 name->name_len = 2 * (strlen_m(s) + 1);
3297 name->name_size = name->name_len;
3300 name->name_size = 0;
3304 static bool test_winreg_OpenKey(struct torture_context *tctx,
3305 struct dcerpc_pipe *p,
3306 struct policy_handle *hive_handle,
3307 const char *keyname,
3308 struct policy_handle *key_handle)
3310 struct winreg_OpenKey r;
3312 r.in.parent_handle = hive_handle;
3313 init_winreg_String(&r.in.keyname, keyname);
3314 r.in.unknown = 0x00000000;
3315 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3316 r.out.handle = key_handle;
3318 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
3320 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey(p, tctx, &r), "OpenKey failed");
3321 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
3326 static bool test_winreg_CloseKey(struct torture_context *tctx,
3327 struct dcerpc_pipe *p,
3328 struct policy_handle *handle)
3330 struct winreg_CloseKey r;
3332 r.in.handle = handle;
3333 r.out.handle = handle;
3335 torture_comment(tctx, "Testing winreg_CloseKey\n");
3337 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey(p, tctx, &r), "CloseKey failed");
3338 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
3343 bool test_winreg_QueryValue(struct torture_context *tctx,
3344 struct dcerpc_pipe *p,
3345 struct policy_handle *handle,
3346 const char *value_name,
3347 enum winreg_Type *type_p,
3348 uint32_t *data_size_p,
3349 uint32_t *data_length_p,
3352 struct winreg_QueryValue r;
3353 enum winreg_Type type = REG_NONE;
3354 uint32_t data_size = 0;
3355 uint32_t data_length = 0;
3356 struct winreg_String valuename;
3357 uint8_t *data = NULL;
3359 init_winreg_String(&valuename, value_name);
3361 data = talloc_zero_array(tctx, uint8_t, 0);
3363 r.in.handle = handle;
3364 r.in.value_name = &valuename;
3366 r.in.data_size = &data_size;
3367 r.in.data_length = &data_length;
3371 r.out.data_size = &data_size;
3372 r.out.data_length = &data_length;
3374 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
3376 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue(p, tctx, &r), "QueryValue failed");
3377 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3378 *r.in.data_size = *r.out.data_size;
3379 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
3382 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue(p, tctx, &r), "QueryValue failed");
3384 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
3387 *type_p = *r.out.type;
3390 *data_size_p = *r.out.data_size;
3392 if (data_length_p) {
3393 *data_length_p = *r.out.data_length;
3396 *data_p = r.out.data;
3402 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
3403 struct dcerpc_pipe *p,
3404 struct policy_handle *handle,
3405 const char *printername,
3406 struct dcerpc_pipe *winreg_pipe,
3407 struct policy_handle *hive_handle)
3409 const char *value_name = "dog";
3410 const char *keys[] = {
3414 /* FIXME: not working with s3 atm. */
3415 "torturedataex_with_subkey\\subkey",
3416 "torturedataex_with_subkey\\subkey:0",
3417 "torturedataex_with_subkey\\subkey:1",
3418 "torturedataex_with_subkey\\subkey\\subsubkey",
3419 "torturedataex_with_subkey\\subkey\\subsubkey:0",
3420 "torturedataex_with_subkey\\subkey\\subsubkey:1",
3424 /* FIXME: not working with s3 atm. */
3431 enum winreg_Type types[] = {
3436 const char *str = "abcdefghijklmnopqrstuvwxzy";
3440 for (i=0; i < ARRAY_SIZE(keys); i++) {
3441 for (t=0; t < ARRAY_SIZE(types); t++) {
3442 for (s=0; s < strlen(str); s++) {
3446 enum winreg_Type type;
3447 const char *string = talloc_strndup(tctx, str, s);
3448 DATA_BLOB blob = data_blob_string_const(string);
3449 const char **subkeys;
3452 uint32_t needed, offered = 0;
3454 struct spoolss_PrinterEnumValues *einfo;
3460 offered = blob.length;
3463 torture_assert(tctx,
3464 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3465 "REG_SZ", string, &type, &data), "");
3466 offered = data.length;
3467 /*strlen_m_term(data.string)*2;*/
3470 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
3473 torture_assert(tctx,
3474 test_SetPrinterDataEx(tctx, p, handle, keys[i], value_name, types[t], data.data, offered),
3475 "failed to call SetPrinterDataEx");
3477 torture_assert(tctx,
3478 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &data_out, &needed),
3479 "failed to call GetPrinterDataEx");
3481 torture_assert(tctx,
3482 test_EnumPrinterDataEx(tctx, p, handle, keys[i], &ecount, &einfo),
3483 "failed to call EnumPrinterDataEx");
3485 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
3486 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
3487 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
3489 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
3490 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
3491 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
3492 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
3493 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
3494 if (einfo[0].data_length > 0) {
3495 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
3498 if (winreg_pipe && hive_handle) {
3499 const char *printer_key;
3500 struct policy_handle key_handle;
3501 enum winreg_Type w_type;
3502 uint32_t w_size, w_length;
3505 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
3506 TOP_LEVEL_PRINTER_KEY, printername, keys[i]);
3508 torture_assert(tctx, test_winreg_OpenKey(tctx, winreg_pipe, hive_handle, printer_key, &key_handle), "");
3510 torture_assert(tctx,
3511 test_winreg_QueryValue(tctx, winreg_pipe, &key_handle, value_name, &w_type, &w_size, &w_length, &w_data), "");
3513 test_winreg_CloseKey(tctx, winreg_pipe, &key_handle);
3515 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
3516 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
3517 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
3520 key = talloc_strdup(tctx, keys[i]);
3522 if (!test_DeletePrinterDataEx(tctx, p, handle, keys[i], value_name)) {
3526 c = strchr(key, '\\');
3530 /* we have subkeys */
3534 if (!test_EnumPrinterKey(tctx, p, handle, key, &subkeys)) {
3538 for (k=0; subkeys && subkeys[k]; k++) {
3540 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
3542 if (!test_DeletePrinterKey(tctx, p, handle, current_key)) {
3547 if (!test_DeletePrinterKey(tctx, p, handle, key)) {
3552 if (!test_DeletePrinterKey(tctx, p, handle, key)) {
3563 static bool test_PrinterData_winreg(struct torture_context *tctx,
3564 struct dcerpc_pipe *p,
3565 struct policy_handle *handle,
3566 const char *printer_name)
3568 struct dcerpc_pipe *p2;
3570 struct policy_handle hive_handle;
3572 torture_assert_ntstatus_ok(tctx,
3573 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
3574 "could not open winreg pipe");
3576 torture_assert(tctx, test_winreg_OpenHKLM(tctx, p2, &hive_handle), "");
3578 ret = test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, p2, &hive_handle);
3580 test_winreg_CloseKey(tctx, p2, &hive_handle);
3587 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
3588 struct dcerpc_pipe *p,
3589 struct policy_handle *handle,
3590 uint32_t *change_id)
3592 enum winreg_Type type;
3596 torture_assert(tctx,
3597 test_GetPrinterData(tctx, p, handle, "ChangeID", &type, &data, &needed),
3598 "failed to call GetPrinterData");
3600 torture_assert(tctx, type == REG_DWORD, "unexpected type");
3601 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
3603 *change_id = IVAL(data, 0);
3608 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
3609 struct dcerpc_pipe *p,
3610 struct policy_handle *handle,
3611 uint32_t *change_id)
3613 enum winreg_Type type;
3617 torture_assert(tctx,
3618 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
3619 "failed to call GetPrinterData");
3621 torture_assert(tctx, type == REG_DWORD, "unexpected type");
3622 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
3624 *change_id = IVAL(data, 0);
3629 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
3630 struct dcerpc_pipe *p,
3631 struct policy_handle *handle,
3632 uint32_t *change_id)
3634 union spoolss_PrinterInfo info;
3636 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 0, &info),
3637 "failed to query Printer level 0");
3639 *change_id = info.info0.change_id;
3644 static bool test_ChangeID(struct torture_context *tctx,
3645 struct dcerpc_pipe *p,
3646 struct policy_handle *handle)
3648 uint32_t change_id, change_id_ex, change_id_info;
3649 uint32_t change_id2, change_id_ex2, change_id_info2;
3650 union spoolss_PrinterInfo info;
3651 const char *comment;
3654 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
3656 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3657 "failed to query for ChangeID");
3658 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3659 "failed to query for ChangeID");
3660 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3661 "failed to query for ChangeID");
3663 torture_assert_int_equal(tctx, change_id, change_id_ex,
3664 "change_ids should all be equal");
3665 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
3666 "change_ids should all be equal");
3669 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
3671 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3672 "failed to query for ChangeID");
3673 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
3674 "failed to query Printer level 2");
3675 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3676 "failed to query for ChangeID");
3677 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3678 "failed to query for ChangeID");
3679 torture_assert_int_equal(tctx, change_id, change_id_ex,
3680 "change_id should not have changed");
3681 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
3682 "change_id should not have changed");
3685 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
3687 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3688 "failed to query for ChangeID");
3689 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3690 "failed to query for ChangeID");
3691 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3692 "failed to query for ChangeID");
3693 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
3694 "failed to query Printer level 2");
3695 comment = talloc_strdup(tctx, info.info2.comment);
3698 struct spoolss_SetPrinterInfoCtr info_ctr;
3699 struct spoolss_DevmodeContainer devmode_ctr;
3700 struct sec_desc_buf secdesc_ctr;
3701 struct spoolss_SetPrinterInfo2 info2;
3703 ZERO_STRUCT(info_ctr);
3704 ZERO_STRUCT(devmode_ctr);
3705 ZERO_STRUCT(secdesc_ctr);
3707 info2.servername = info.info2.servername;
3708 info2.printername = info.info2.printername;
3709 info2.sharename = info.info2.sharename;
3710 info2.portname = info.info2.portname;
3711 info2.drivername = info.info2.drivername;
3712 info2.comment = "torture_comment";
3713 info2.location = info.info2.location;
3714 info2.devmode_ptr = 0;
3715 info2.sepfile = info.info2.sepfile;
3716 info2.printprocessor = info.info2.printprocessor;
3717 info2.datatype = info.info2.datatype;
3718 info2.parameters = info.info2.parameters;
3719 info2.secdesc_ptr = 0;
3720 info2.attributes = info.info2.attributes;
3721 info2.priority = info.info2.priority;
3722 info2.defaultpriority = info.info2.defaultpriority;
3723 info2.starttime = info.info2.starttime;
3724 info2.untiltime = info.info2.untiltime;
3725 info2.status = info.info2.status;
3726 info2.cjobs = info.info2.cjobs;
3727 info2.averageppm = info.info2.averageppm;
3730 info_ctr.info.info2 = &info2;
3732 torture_assert(tctx, test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
3733 "failed to call SetPrinter");
3735 info2.comment = comment;
3737 torture_assert(tctx, test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
3738 "failed to call SetPrinter");
3742 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id2),
3743 "failed to query for ChangeID");
3744 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
3745 "failed to query for ChangeID");
3746 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info2),
3747 "failed to query for ChangeID");
3749 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
3750 "change_ids should all be equal");
3751 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
3752 "change_ids should all be equal");
3754 torture_assert(tctx, (change_id < change_id2),
3755 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3756 change_id2, change_id));
3757 torture_assert(tctx, (change_id_ex < change_id_ex2),
3758 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3759 change_id_ex2, change_id_ex));
3760 torture_assert(tctx, (change_id_info < change_id_info2),
3761 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3762 change_id_info2, change_id_info));
3767 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
3768 struct dcerpc_pipe *p,
3769 struct policy_handle *handle)
3772 struct dcerpc_binding *b;
3773 struct dcerpc_pipe *p2;
3774 struct spoolss_ClosePrinter cp;
3776 /* only makes sense on SMB */
3777 if (p->conn->transport.transport != NCACN_NP) {
3781 torture_comment(tctx, "testing close on secondary pipe\n");
3783 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
3784 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
3786 status = dcerpc_secondary_connection(p, &p2, b);
3787 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
3789 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
3790 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
3792 cp.in.handle = handle;
3793 cp.out.handle = handle;
3795 status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
3796 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
3797 "ERROR: Allowed close on secondary connection");
3799 torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
3800 "Unexpected fault code");
3807 static bool test_OpenPrinter_badname(struct torture_context *tctx,
3808 struct dcerpc_pipe *p, const char *name)
3811 struct spoolss_OpenPrinter op;
3812 struct spoolss_OpenPrinterEx opEx;
3813 struct policy_handle handle;
3816 op.in.printername = name;
3817 op.in.datatype = NULL;
3818 op.in.devmode_ctr.devmode= NULL;
3819 op.in.access_mask = 0;
3820 op.out.handle = &handle;
3822 torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
3824 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
3825 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
3826 if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
3827 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
3828 name, win_errstr(op.out.result));
3831 if (W_ERROR_IS_OK(op.out.result)) {
3832 ret &=test_ClosePrinter(tctx, p, &handle);
3835 opEx.in.printername = name;
3836 opEx.in.datatype = NULL;
3837 opEx.in.devmode_ctr.devmode = NULL;
3838 opEx.in.access_mask = 0;
3840 opEx.in.userlevel.level1 = NULL;
3841 opEx.out.handle = &handle;
3843 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
3845 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
3846 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
3847 if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
3848 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
3849 name, win_errstr(opEx.out.result));
3852 if (W_ERROR_IS_OK(opEx.out.result)) {
3853 ret &=test_ClosePrinter(tctx, p, &handle);
3859 static bool test_OpenPrinter(struct torture_context *tctx,
3860 struct dcerpc_pipe *p,
3862 const char *environment)
3865 struct spoolss_OpenPrinter r;
3866 struct policy_handle handle;
3869 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
3870 r.in.datatype = NULL;
3871 r.in.devmode_ctr.devmode= NULL;
3872 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3873 r.out.handle = &handle;
3875 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
3877 status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
3879 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
3881 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
3883 if (!test_GetPrinter(tctx, p, &handle, environment)) {
3887 if (!torture_setting_bool(tctx, "samba3", false)) {
3888 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
3893 if (!test_ClosePrinter(tctx, p, &handle)) {
3900 static bool call_OpenPrinterEx(struct torture_context *tctx,
3901 struct dcerpc_pipe *p,
3903 struct spoolss_DeviceMode *devmode,
3904 struct policy_handle *handle)
3906 struct spoolss_OpenPrinterEx r;
3907 struct spoolss_UserLevel1 userlevel1;
3910 if (name && name[0]) {
3911 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
3912 dcerpc_server_name(p), name);
3914 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
3915 dcerpc_server_name(p));
3918 r.in.datatype = NULL;
3919 r.in.devmode_ctr.devmode= devmode;
3920 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3922 r.in.userlevel.level1 = &userlevel1;
3923 r.out.handle = handle;
3925 userlevel1.size = 1234;
3926 userlevel1.client = "hello";
3927 userlevel1.user = "spottyfoot!";
3928 userlevel1.build = 1;
3929 userlevel1.major = 2;
3930 userlevel1.minor = 3;
3931 userlevel1.processor = 4;
3933 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
3935 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
3937 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
3939 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
3944 static bool test_OpenPrinterEx(struct torture_context *tctx,
3945 struct dcerpc_pipe *p,
3947 const char *environment)
3949 struct policy_handle handle;
3952 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
3956 if (!test_PrinterInfo_SD(tctx, p, &handle)) {
3960 if (!test_GetPrinter(tctx, p, &handle, environment)) {
3964 if (!test_EnumForms(tctx, p, &handle, false)) {
3968 if (!test_AddForm(tctx, p, &handle, false)) {
3972 if (!test_EnumPrinterData(tctx, p, &handle)) {
3976 if (!test_EnumPrinterDataEx(tctx, p, &handle, "PrinterDriverData", NULL, NULL)) {
3980 if (!test_printer_keys(tctx, p, &handle)) {
3984 if (!test_PausePrinter(tctx, p, &handle)) {
3988 if (!test_DoPrintTest(tctx, p, &handle)) {
3992 if (!test_ResumePrinter(tctx, p, &handle)) {
3996 if (!test_SetPrinterData(tctx, p, &handle)) {
4000 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
4004 if (!torture_setting_bool(tctx, "samba3", false)) {
4005 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
4010 if (!test_ClosePrinter(tctx, p, &handle)) {
4017 static bool test_EnumPrinters_old(struct torture_context *tctx,
4018 struct dcerpc_pipe *p,
4019 const char *environment)
4021 struct spoolss_EnumPrinters r;
4023 uint16_t levels[] = {1, 2, 4, 5};
4027 for (i=0;i<ARRAY_SIZE(levels);i++) {
4028 union spoolss_PrinterInfo *info;
4033 r.in.flags = PRINTER_ENUM_LOCAL;
4035 r.in.level = levels[i];
4038 r.out.needed = &needed;
4039 r.out.count = &count;
4042 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
4044 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
4045 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
4047 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4048 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4049 data_blob_clear(&blob);
4050 r.in.buffer = &blob;
4051 r.in.offered = needed;
4052 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
4055 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
4057 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
4059 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4062 torture_comment(tctx, "No printers returned\n");
4066 for (j=0;j<count;j++) {
4067 if (r.in.level == 1) {
4068 char *unc = talloc_strdup(tctx, info[j].info1.name);
4071 if (unc[0] == '\\' && unc[1] == '\\') {
4074 slash = strchr(unc, '\\');
4079 if (!test_OpenPrinter(tctx, p, name, environment)) {
4082 if (!test_OpenPrinterEx(tctx, p, name, environment)) {
4092 static bool test_GetPrinterDriver(struct torture_context *tctx,
4093 struct dcerpc_pipe *p,
4094 struct policy_handle *handle,
4095 const char *driver_name)
4097 struct spoolss_GetPrinterDriver r;
4100 r.in.handle = handle;
4101 r.in.architecture = "W32X86";
4105 r.out.needed = &needed;
4107 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
4109 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
4110 "failed to call GetPrinterDriver");
4111 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4112 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4113 data_blob_clear(&blob);
4114 r.in.buffer = &blob;
4115 r.in.offered = needed;
4116 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
4117 "failed to call GetPrinterDriver");
4120 torture_assert_werr_ok(tctx, r.out.result,
4121 "failed to call GetPrinterDriver");
4123 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4128 static bool test_GetPrinterDriver2(struct torture_context *tctx,
4129 struct dcerpc_pipe *p,
4130 struct policy_handle *handle,
4131 const char *driver_name,
4132 const char *architecture)
4134 struct spoolss_GetPrinterDriver2 r;
4135 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
4137 uint32_t server_major_version;
4138 uint32_t server_minor_version;
4141 r.in.handle = handle;
4142 r.in.architecture = architecture;
4143 r.in.client_major_version = 3;
4144 r.in.client_minor_version = 0;
4145 r.out.needed = &needed;
4146 r.out.server_major_version = &server_major_version;
4147 r.out.server_minor_version = &server_minor_version;
4149 for (i=0;i<ARRAY_SIZE(levels);i++) {
4153 r.in.level = levels[i];
4155 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
4156 driver_name, r.in.level);
4158 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
4159 "failed to call GetPrinterDriver2");
4160 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4161 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4162 data_blob_clear(&blob);
4163 r.in.buffer = &blob;
4164 r.in.offered = needed;
4165 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
4166 "failed to call GetPrinterDriver2");
4169 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
4170 switch (r.in.level) {
4179 torture_assert_werr_ok(tctx, r.out.result,
4180 "failed to call GetPrinterDriver2");
4182 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4188 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
4189 struct dcerpc_pipe *p,
4190 const char *environment)
4192 struct spoolss_EnumPrinterDrivers r;
4194 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
4197 for (i=0;i<ARRAY_SIZE(levels);i++) {
4201 union spoolss_DriverInfo *info;
4203 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
4204 r.in.environment = environment;
4205 r.in.level = levels[i];
4208 r.out.needed = &needed;
4209 r.out.count = &count;
4212 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
4214 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
4216 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
4218 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4219 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4220 data_blob_clear(&blob);
4221 r.in.buffer = &blob;
4222 r.in.offered = needed;
4223 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
4226 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
4228 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
4231 torture_comment(tctx, "No printer drivers returned\n");
4235 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4241 static bool test_DeletePrinter(struct torture_context *tctx,
4242 struct dcerpc_pipe *p,
4243 struct policy_handle *handle)
4245 struct spoolss_DeletePrinter r;
4247 torture_comment(tctx, "Testing DeletePrinter\n");
4249 r.in.handle = handle;
4251 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter(p, tctx, &r),
4252 "failed to delete printer");
4253 torture_assert_werr_ok(tctx, r.out.result,
4254 "failed to delete printer");
4259 static bool test_EnumPrinters_findname(struct torture_context *tctx,
4260 struct dcerpc_pipe *p,
4266 struct spoolss_EnumPrinters e;
4268 union spoolss_PrinterInfo *info;
4279 e.out.count = &count;
4281 e.out.needed = &needed;
4283 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
4284 "failed to enum printers");
4286 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
4287 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4288 data_blob_clear(&blob);
4289 e.in.buffer = &blob;
4290 e.in.offered = needed;
4292 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
4293 "failed to enum printers");
4296 torture_assert_werr_ok(tctx, e.out.result,
4297 "failed to enum printers");
4299 for (i=0; i < count; i++) {
4301 const char *current = NULL;
4306 current = info[i].info1.name;
4310 if (strequal(current, name)) {
4315 q = strrchr(current, '\\');
4318 torture_warning(tctx,
4319 "server returns printername %s incl. servername although we did not set servername", current);
4322 if (strequal(q, name)) {
4332 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
4333 struct dcerpc_pipe *p,
4334 const char *printername,
4338 struct spoolss_AddPrinter r;
4339 struct spoolss_AddPrinterEx rex;
4340 struct spoolss_SetPrinterInfoCtr info_ctr;
4341 struct spoolss_SetPrinterInfo1 info1;
4342 struct spoolss_DevmodeContainer devmode_ctr;
4343 struct sec_desc_buf secdesc_ctr;
4344 struct spoolss_UserLevelCtr userlevel_ctr;
4345 struct policy_handle handle;
4348 ZERO_STRUCT(devmode_ctr);
4349 ZERO_STRUCT(secdesc_ctr);
4350 ZERO_STRUCT(userlevel_ctr);
4353 torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
4355 /* try to add printer to wellknown printer list (level 1) */
4357 userlevel_ctr.level = 1;
4359 info_ctr.info.info1 = &info1;
4362 rex.in.server = NULL;
4363 rex.in.info_ctr = &info_ctr;
4364 rex.in.devmode_ctr = &devmode_ctr;
4365 rex.in.secdesc_ctr = &secdesc_ctr;
4366 rex.in.userlevel_ctr = &userlevel_ctr;
4367 rex.out.handle = &handle;
4370 r.in.info_ctr = &info_ctr;
4371 r.in.devmode_ctr = &devmode_ctr;
4372 r.in.secdesc_ctr = &secdesc_ctr;
4373 r.out.handle = &handle;
4375 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4376 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4377 "failed to add printer");
4378 result = ex ? rex.out.result : r.out.result;
4379 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
4380 "unexpected result code");
4382 info1.name = printername;
4383 info1.flags = PRINTER_ATTRIBUTE_SHARED;
4385 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4386 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4387 "failed to add printer");
4388 result = ex ? rex.out.result : r.out.result;
4389 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4390 "unexpected result code");
4392 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
4393 better do a real check to see the printer is really there */
4395 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4396 PRINTER_ENUM_NETWORK, 1,
4399 "failed to enum printers");
4401 torture_assert(tctx, found, "failed to find newly added printer");
4405 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4406 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4407 "failed to add printer");
4408 result = ex ? rex.out.result : r.out.result;
4409 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4410 "unexpected result code");
4412 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
4413 better do a real check to see the printer has really been removed
4414 from the well known printer list */
4418 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4419 PRINTER_ENUM_NETWORK, 1,
4422 "failed to enum printers");
4424 torture_assert(tctx, !found, "printer still in well known printer list");
4429 static bool test_AddPrinter_normal(struct torture_context *tctx,
4430 struct dcerpc_pipe *p,
4431 struct policy_handle *handle_p,
4432 const char *printername,
4433 const char *drivername,
4434 const char *portname,
4438 struct spoolss_AddPrinter r;
4439 struct spoolss_AddPrinterEx rex;
4440 struct spoolss_SetPrinterInfoCtr info_ctr;
4441 struct spoolss_SetPrinterInfo2 info2;
4442 struct spoolss_DevmodeContainer devmode_ctr;
4443 struct sec_desc_buf secdesc_ctr;
4444 struct spoolss_UserLevelCtr userlevel_ctr;
4445 struct policy_handle handle;
4447 bool existing_printer_deleted = false;
4449 ZERO_STRUCT(devmode_ctr);
4450 ZERO_STRUCT(secdesc_ctr);
4451 ZERO_STRUCT(userlevel_ctr);
4453 torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
4455 userlevel_ctr.level = 1;
4457 rex.in.server = NULL;
4458 rex.in.info_ctr = &info_ctr;
4459 rex.in.devmode_ctr = &devmode_ctr;
4460 rex.in.secdesc_ctr = &secdesc_ctr;
4461 rex.in.userlevel_ctr = &userlevel_ctr;
4462 rex.out.handle = &handle;
4465 r.in.info_ctr = &info_ctr;
4466 r.in.devmode_ctr = &devmode_ctr;
4467 r.in.secdesc_ctr = &secdesc_ctr;
4468 r.out.handle = &handle;
4472 /* try to add printer to printer list (level 2) */
4476 info_ctr.info.info2 = &info2;
4479 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4480 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4481 "failed to add printer");
4482 result = ex ? rex.out.result : r.out.result;
4483 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
4484 "unexpected result code");
4486 info2.printername = printername;
4488 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4489 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4490 "failed to add printer");
4491 result = ex ? rex.out.result : r.out.result;
4493 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
4494 struct policy_handle printer_handle;
4496 if (existing_printer_deleted) {
4497 torture_fail(tctx, "already deleted printer still existing?");
4500 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
4501 "failed to open printer handle");
4503 torture_assert(tctx, test_DeletePrinter(tctx, p, &printer_handle),
4504 "failed to delete printer");
4506 torture_assert(tctx, test_ClosePrinter(tctx, p, &printer_handle),
4507 "failed to close server handle");
4509 existing_printer_deleted = true;
4514 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
4515 "unexpected result code");
4517 info2.portname = portname;
4519 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4520 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4521 "failed to add printer");
4522 result = ex ? rex.out.result : r.out.result;
4523 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
4524 "unexpected result code");
4526 info2.drivername = drivername;
4528 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4529 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4530 "failed to add printer");
4531 result = ex ? rex.out.result : r.out.result;
4533 /* w2k8r2 allows to add printer w/o defining printprocessor */
4535 if (!W_ERROR_IS_OK(result)) {
4536 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
4537 "unexpected result code");
4539 info2.printprocessor = "winprint";
4541 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4542 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4543 "failed to add printer");
4544 result = ex ? rex.out.result : r.out.result;
4545 torture_assert_werr_ok(tctx, result,
4546 "failed to add printer");
4551 /* we are paranoid, really check if the printer is there now */
4553 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4554 PRINTER_ENUM_LOCAL, 1,
4557 "failed to enum printers");
4558 torture_assert(tctx, found, "failed to find newly added printer");
4560 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4561 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4562 "failed to add printer");
4563 result = ex ? rex.out.result : r.out.result;
4564 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4565 "unexpected result code");
4570 static bool test_AddPrinterEx(struct torture_context *tctx,
4571 struct dcerpc_pipe *p,
4572 struct policy_handle *handle_p,
4573 const char *printername,
4574 const char *drivername,
4575 const char *portname)
4579 if (!torture_setting_bool(tctx, "samba3", false)) {
4580 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
4581 torture_comment(tctx, "failed to add printer to well known list\n");
4586 if (!test_AddPrinter_normal(tctx, p, handle_p,
4587 printername, drivername, portname,
4589 torture_comment(tctx, "failed to add printer to printer list\n");
4596 static bool test_AddPrinter(struct torture_context *tctx,
4597 struct dcerpc_pipe *p,
4598 struct policy_handle *handle_p,
4599 const char *printername,
4600 const char *drivername,
4601 const char *portname)
4605 if (!torture_setting_bool(tctx, "samba3", false)) {
4606 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
4607 torture_comment(tctx, "failed to add printer to well known list\n");
4612 if (!test_AddPrinter_normal(tctx, p, handle_p,
4613 printername, drivername, portname,
4615 torture_comment(tctx, "failed to add printer to printer list\n");
4622 static bool test_printer_info(struct torture_context *tctx,
4623 struct dcerpc_pipe *p,
4624 struct policy_handle *handle)
4628 if (torture_setting_bool(tctx, "samba3", false)) {
4629 torture_skip(tctx, "skipping printer info cross tests against samba 3");
4632 if (!test_PrinterInfo(tctx, p, handle)) {
4636 if (!test_SetPrinter_errors(tctx, p, handle)) {
4643 static bool test_EnumPrinterKey(struct torture_context *tctx,
4644 struct dcerpc_pipe *p,
4645 struct policy_handle *handle,
4646 const char *key_name,
4647 const char ***array)
4649 struct spoolss_EnumPrinterKey r;
4650 uint32_t needed = 0;
4651 union spoolss_KeyNames key_buffer;
4652 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
4656 r.in.handle = handle;
4657 r.in.key_name = key_name;
4658 r.out.key_buffer = &key_buffer;
4659 r.out.needed = &needed;
4660 r.out._ndr_size = &_ndr_size;
4662 for (i=0; i < ARRAY_SIZE(offered); i++) {
4664 if (offered[i] < 0 && needed) {
4668 r.in.offered = needed + offered[i];
4670 r.in.offered = offered[i];
4673 ZERO_STRUCT(key_buffer);
4675 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
4677 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
4678 "failed to call EnumPrinterKey");
4679 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4681 torture_assert(tctx, (_ndr_size == r.in.offered/2),
4682 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
4683 _ndr_size, r.in.offered/2));
4685 r.in.offered = needed;
4686 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
4687 "failed to call EnumPrinterKey");
4690 if (offered[i] > 0) {
4691 torture_assert_werr_ok(tctx, r.out.result,
4692 "failed to call EnumPrinterKey");
4695 torture_assert(tctx, (_ndr_size == r.in.offered/2),
4696 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
4697 _ndr_size, r.in.offered/2));
4699 torture_assert(tctx, (*r.out.needed <= r.in.offered),
4700 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
4702 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
4703 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
4705 if (key_buffer.string_array) {
4706 uint32_t calc_needed = 0;
4708 for (s=0; key_buffer.string_array[s]; s++) {
4709 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
4711 if (!key_buffer.string_array[0]) {
4716 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
4717 "EnumPrinterKey unexpected size");
4722 *array = key_buffer.string_array;
4728 bool test_printer_keys(struct torture_context *tctx,
4729 struct dcerpc_pipe *p,
4730 struct policy_handle *handle)
4732 const char **key_array = NULL;
4735 torture_comment(tctx, "\nTesting Printer Keys\n");
4737 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, "", &key_array),
4738 "failed to call test_EnumPrinterKey");
4740 for (i=0; key_array && key_array[i]; i++) {
4741 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, key_array[i], NULL),
4742 "failed to call test_EnumPrinterKey");
4744 for (i=0; key_array && key_array[i]; i++) {
4745 torture_assert(tctx, test_EnumPrinterDataEx(tctx, p, handle, key_array[i], NULL, NULL),
4746 "failed to call test_EnumPrinterDataEx");
4752 static bool test_one_printer(struct torture_context *tctx,
4753 struct dcerpc_pipe *p,
4754 struct policy_handle *handle,
4759 if (!test_printer_info(tctx, p, handle)) {
4763 if (!test_PrinterInfo_SD(tctx, p, handle)) {
4767 if (!test_PrinterInfo_DevMode(tctx, p, handle, name)) {
4771 if (!test_ChangeID(tctx, p, handle)) {
4775 if (!test_printer_keys(tctx, p, handle)) {
4779 if (!test_SetPrinterDataEx_matrix(tctx, p, handle, name, NULL, NULL)) {
4783 if (!test_PrinterData_winreg(tctx, p, handle, name)) {
4790 static bool test_printer(struct torture_context *tctx,
4791 struct dcerpc_pipe *p)
4794 struct policy_handle handle[2];
4796 const char *drivername = "Microsoft XPS Document Writer";
4797 const char *portname = "LPT1:";
4799 /* test printer created via AddPrinter */
4801 if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
4805 if (!test_one_printer(tctx, p, &handle[0], TORTURE_PRINTER)) {
4809 if (!test_DeletePrinter(tctx, p, &handle[0])) {
4813 if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
4814 TORTURE_PRINTER, &found)) {
4818 torture_assert(tctx, !found, "deleted printer still there");
4820 /* test printer created via AddPrinterEx */
4822 if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
4826 if (!test_one_printer(tctx, p, &handle[1], TORTURE_PRINTER_EX)) {
4830 if (!test_DeletePrinter(tctx, p, &handle[1])) {
4834 if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
4835 TORTURE_PRINTER_EX, &found)) {
4839 torture_assert(tctx, !found, "deleted printer still there");
4844 static bool test_architecture_buffer(struct torture_context *tctx,
4845 struct dcerpc_pipe *p)
4847 struct spoolss_OpenPrinterEx r;
4848 struct spoolss_UserLevel1 u1;
4849 struct policy_handle handle;
4850 uint32_t architectures[] = {
4851 PROCESSOR_ARCHITECTURE_INTEL,
4852 PROCESSOR_ARCHITECTURE_IA64,
4853 PROCESSOR_ARCHITECTURE_AMD64
4858 for (i=0; i < ARRAY_SIZE(architectures); i++) {
4860 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
4868 u1.processor = architectures[i];
4870 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
4871 r.in.datatype = NULL;
4872 r.in.devmode_ctr.devmode= NULL;
4873 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4875 r.in.userlevel.level1 = &u1;
4876 r.out.handle = &handle;
4878 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx(p, tctx, &r), "");
4879 torture_assert_werr_ok(tctx, r.out.result, "");
4882 struct spoolss_EnumPrinters e;
4884 union spoolss_PrinterInfo *info;
4886 e.in.flags = PRINTER_ENUM_LOCAL;
4891 e.out.count = &count;
4893 e.out.needed = &needed[i];
4895 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e), "");
4897 torture_comment(tctx, "needed was %d\n", needed[i]);
4901 torture_assert(tctx, test_ClosePrinter(tctx, p, &handle), "");
4904 for (i=1; i < ARRAY_SIZE(architectures); i++) {
4905 if (needed[i-1] != needed[i]) {
4907 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
4908 needed[i-1], architectures[i-1], needed[i], architectures[i]));
4915 bool torture_rpc_spoolss(struct torture_context *torture)
4918 struct dcerpc_pipe *p;
4920 struct test_spoolss_context *ctx;
4921 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
4923 status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
4924 if (!NT_STATUS_IS_OK(status)) {
4928 ctx = talloc_zero(torture, struct test_spoolss_context);
4930 ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
4931 ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle);
4932 ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
4933 ret &= test_AddForm(torture, p, &ctx->server_handle, true);
4934 ret &= test_EnumPorts(torture, p, ctx);
4935 ret &= test_GetPrinterDriverDirectory(torture, p, ctx, environment);
4936 ret &= test_GetPrintProcessorDirectory(torture, p, ctx, environment);
4937 ret &= test_EnumPrinterDrivers(torture, p, ctx, environment);
4938 ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
4939 ret &= test_EnumMonitors(torture, p, ctx);
4940 ret &= test_EnumPrintProcessors(torture, p, ctx, environment);
4941 ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
4942 ret &= test_EnumPrinters(torture, p, ctx);
4943 ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
4944 ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
4945 ret &= test_OpenPrinter_badname(torture, p, "");
4946 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
4947 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
4948 ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
4949 ret &= test_OpenPrinter_badname(torture, p,
4950 talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
4953 ret &= test_AddPort(torture, p);
4954 ret &= test_EnumPorts_old(torture, p);
4955 ret &= test_EnumPrinters_old(torture, p, environment);
4956 ret &= test_EnumPrinterDrivers_old(torture, p, environment);
4957 ret &= test_architecture_buffer(torture, p);
4962 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
4964 struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
4966 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
4967 "printer", &ndr_table_spoolss);
4969 torture_rpc_tcase_add_test(tcase, "printer", test_printer);