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 #define TOP_LEVEL_PRINTER_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"
43 struct test_spoolss_context {
44 /* print server handle */
45 struct policy_handle server_handle;
48 uint32_t port_count[3];
49 union spoolss_PortInfo *ports[3];
51 /* for EnumPrinterDrivers */
52 uint32_t driver_count[8];
53 union spoolss_DriverInfo *drivers[8];
55 /* for EnumMonitors */
56 uint32_t monitor_count[3];
57 union spoolss_MonitorInfo *monitors[3];
59 /* for EnumPrintProcessors */
60 uint32_t print_processor_count[2];
61 union spoolss_PrintProcessorInfo *print_processors[2];
63 /* for EnumPrinters */
64 uint32_t printer_count[6];
65 union spoolss_PrinterInfo *printers[6];
68 #define COMPARE_STRING(tctx, c,r,e) \
69 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
71 /* not every compiler supports __typeof__() */
73 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
74 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
75 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
77 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
78 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
82 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
85 #define COMPARE_UINT32(tctx, c, r, e) do {\
86 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
87 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
90 #define COMPARE_UINT64(tctx, c, r, e) do {\
91 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
92 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
96 #define COMPARE_NTTIME(tctx, c, r, e) do {\
97 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
98 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
101 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
103 if (!c.e && !r.e) { \
107 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
110 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
112 for (__i=0;c.e[__i] != NULL; __i++) { \
113 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
117 #define CHECK_ALIGN(size, n) do {\
119 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
120 size, n, size + n - (size % n));\
124 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
126 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, ic, needed, align) do { \
127 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
128 uint32_t size = ndr_size_##fn##_info(tctx, ic, level, count, info);\
129 uint32_t round_size = DO_ROUND(size, align);\
130 if (round_size != needed) {\
131 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
132 CHECK_ALIGN(size, align);\
137 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, ic, needed, align) do { \
138 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
139 uint32_t size = ndr_size_##fn##_info(tctx, ic, count, info);\
140 uint32_t round_size = DO_ROUND(size, align);\
141 if (round_size != needed) {\
142 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
143 CHECK_ALIGN(size, align);\
148 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, ic, needed, align) do { \
149 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
150 uint32_t size = ndr_size_##fn(info, level, ic, 0);\
151 uint32_t round_size = DO_ROUND(size, align);\
152 if (round_size != needed) {\
153 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
154 CHECK_ALIGN(size, align);\
159 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context *tctx,
160 const union spoolss_PrinterInfo *i,
162 union spoolss_SetPrinterInfo *s)
166 s->info0 = talloc(tctx, struct spoolss_SetPrinterInfo0);
169 s->info2 = talloc(tctx, struct spoolss_SetPrinterInfo2);
170 s->info2->servername = i->info2.servername;
171 s->info2->printername = i->info2.printername;
172 s->info2->sharename = i->info2.sharename;
173 s->info2->portname = i->info2.portname;
174 s->info2->drivername = i->info2.drivername;
175 s->info2->comment = i->info2.comment;
176 s->info2->location = i->info2.location;
177 s->info2->devmode_ptr = 0;
178 s->info2->sepfile = i->info2.sepfile;
179 s->info2->printprocessor = i->info2.printprocessor;
180 s->info2->datatype = i->info2.datatype;
181 s->info2->parameters = i->info2.parameters;
182 s->info2->secdesc_ptr = 0;
183 s->info2->attributes = i->info2.attributes;
184 s->info2->priority = i->info2.priority;
185 s->info2->defaultpriority = i->info2.defaultpriority;
186 s->info2->starttime = i->info2.starttime;
187 s->info2->untiltime = i->info2.untiltime;
188 s->info2->status = i->info2.status;
189 s->info2->cjobs = i->info2.cjobs;
190 s->info2->averageppm = i->info2.averageppm;
206 static bool test_OpenPrinter_server(struct torture_context *tctx,
207 struct dcerpc_pipe *p,
208 struct policy_handle *server_handle)
211 struct spoolss_OpenPrinter op;
213 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
214 op.in.datatype = NULL;
215 op.in.devmode_ctr.devmode= NULL;
216 op.in.access_mask = 0;
217 op.out.handle = server_handle;
219 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
221 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
222 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
223 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
228 static bool test_EnumPorts(struct torture_context *tctx,
229 struct dcerpc_pipe *p,
230 struct test_spoolss_context *ctx)
233 struct spoolss_EnumPorts r;
234 uint16_t levels[] = { 1, 2 };
237 for (i=0;i<ARRAY_SIZE(levels);i++) {
238 int level = levels[i];
242 union spoolss_PortInfo *info;
244 r.in.servername = "";
248 r.out.needed = &needed;
249 r.out.count = &count;
252 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
254 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
255 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
256 if (W_ERROR_IS_OK(r.out.result)) {
257 /* TODO: do some more checks here */
260 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
261 "EnumPorts unexpected return code");
263 blob = data_blob_talloc(ctx, NULL, needed);
264 data_blob_clear(&blob);
266 r.in.offered = needed;
268 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
269 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
271 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
273 torture_assert(tctx, info, "EnumPorts returned no info");
275 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
277 ctx->port_count[level] = count;
278 ctx->ports[level] = info;
281 for (i=1;i<ARRAY_SIZE(levels);i++) {
282 int level = levels[i];
283 int old_level = levels[i-1];
284 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
285 "EnumPorts invalid value");
287 /* if the array sizes are not the same we would maybe segfault in the following code */
289 for (i=0;i<ARRAY_SIZE(levels);i++) {
290 int level = levels[i];
291 for (j=0;j<ctx->port_count[level];j++) {
292 union spoolss_PortInfo *cur = &ctx->ports[level][j];
293 union spoolss_PortInfo *ref = &ctx->ports[2][j];
296 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
299 /* level 2 is our reference, and it makes no sense to compare it to itself */
308 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
309 struct dcerpc_pipe *p,
310 struct test_spoolss_context *ctx,
311 const char *environment)
314 struct spoolss_GetPrintProcessorDirectory r;
329 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
332 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
338 for (i=0;i<ARRAY_SIZE(levels);i++) {
339 int level = levels[i].level;
342 r.in.server = levels[i].server;
343 r.in.environment = environment;
347 r.out.needed = &needed;
349 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
351 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
352 torture_assert_ntstatus_ok(tctx, status,
353 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
354 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
355 "GetPrintProcessorDirectory unexpected return code");
357 blob = data_blob_talloc(ctx, NULL, needed);
358 data_blob_clear(&blob);
360 r.in.offered = needed;
362 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
363 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
365 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
367 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
374 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
375 struct dcerpc_pipe *p,
376 struct test_spoolss_context *ctx,
377 const char *environment)
380 struct spoolss_GetPrinterDriverDirectory r;
395 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
398 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
404 for (i=0;i<ARRAY_SIZE(levels);i++) {
405 int level = levels[i].level;
408 r.in.server = levels[i].server;
409 r.in.environment = environment;
413 r.out.needed = &needed;
415 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
417 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
418 torture_assert_ntstatus_ok(tctx, status,
419 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
420 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
421 "GetPrinterDriverDirectory unexpected return code");
423 blob = data_blob_talloc(ctx, NULL, needed);
424 data_blob_clear(&blob);
426 r.in.offered = needed;
428 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
429 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
431 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
433 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
439 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
440 struct dcerpc_pipe *p,
441 struct test_spoolss_context *ctx,
442 const char *architecture)
445 struct spoolss_EnumPrinterDrivers r;
446 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
449 for (i=0;i<ARRAY_SIZE(levels);i++) {
450 int level = levels[i];
454 union spoolss_DriverInfo *info;
456 /* FIXME: gd, come back and fix "" as server, and handle
457 * priority of returned error codes in torture test and samba 3
460 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
461 r.in.environment = architecture;
465 r.out.needed = &needed;
466 r.out.count = &count;
469 torture_comment(tctx, "Testing EnumPrinterDrivers level %u (%s)\n", r.in.level, r.in.environment);
471 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
472 torture_assert_ntstatus_ok(tctx, status,
473 "dcerpc_spoolss_EnumPrinterDrivers failed");
474 if (W_ERROR_IS_OK(r.out.result)) {
475 /* TODO: do some more checks here */
478 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
479 blob = data_blob_talloc(ctx, NULL, needed);
480 data_blob_clear(&blob);
482 r.in.offered = needed;
484 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
485 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
488 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
490 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
492 ctx->driver_count[level] = count;
493 ctx->drivers[level] = info;
496 for (i=1;i<ARRAY_SIZE(levels);i++) {
497 int level = levels[i];
498 int old_level = levels[i-1];
500 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
501 "EnumPrinterDrivers invalid value");
504 for (i=0;i<ARRAY_SIZE(levels);i++) {
505 int level = levels[i];
507 for (j=0;j<ctx->driver_count[level];j++) {
508 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
509 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
513 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
516 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
517 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
518 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
519 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
520 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
521 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
524 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
525 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
526 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
527 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
528 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
529 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
530 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
531 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
532 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
533 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
536 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
537 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
538 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
539 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
540 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
541 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
542 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
543 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
544 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
545 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
546 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
549 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
550 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
551 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
552 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
553 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
554 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
555 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
556 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
557 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
560 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
561 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
562 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
563 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
564 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
565 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
566 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
567 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
568 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
569 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
570 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
571 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
572 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
573 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
574 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
575 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
576 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
579 /* level 8 is our reference, and it makes no sense to compare it to itself */
588 static bool test_EnumMonitors(struct torture_context *tctx,
589 struct dcerpc_pipe *p,
590 struct test_spoolss_context *ctx)
593 struct spoolss_EnumMonitors r;
594 uint16_t levels[] = { 1, 2 };
597 for (i=0;i<ARRAY_SIZE(levels);i++) {
598 int level = levels[i];
602 union spoolss_MonitorInfo *info;
604 r.in.servername = "";
608 r.out.needed = &needed;
609 r.out.count = &count;
612 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
614 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
615 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
616 if (W_ERROR_IS_OK(r.out.result)) {
617 /* TODO: do some more checks here */
620 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
621 "EnumMonitors failed");
623 blob = data_blob_talloc(ctx, NULL, needed);
624 data_blob_clear(&blob);
626 r.in.offered = needed;
628 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
629 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
631 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
633 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
635 ctx->monitor_count[level] = count;
636 ctx->monitors[level] = info;
639 for (i=1;i<ARRAY_SIZE(levels);i++) {
640 int level = levels[i];
641 int old_level = levels[i-1];
642 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
643 "EnumMonitors invalid value");
646 for (i=0;i<ARRAY_SIZE(levels);i++) {
647 int level = levels[i];
648 for (j=0;j<ctx->monitor_count[level];j++) {
649 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
650 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
653 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
656 /* level 2 is our reference, and it makes no sense to compare it to itself */
665 static bool test_EnumPrintProcessors(struct torture_context *tctx,
666 struct dcerpc_pipe *p,
667 struct test_spoolss_context *ctx,
668 const char *environment)
671 struct spoolss_EnumPrintProcessors r;
672 uint16_t levels[] = { 1 };
675 for (i=0;i<ARRAY_SIZE(levels);i++) {
676 int level = levels[i];
680 union spoolss_PrintProcessorInfo *info;
682 r.in.servername = "";
683 r.in.environment = environment;
687 r.out.needed = &needed;
688 r.out.count = &count;
691 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
693 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
694 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
695 if (W_ERROR_IS_OK(r.out.result)) {
696 /* TODO: do some more checks here */
699 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
700 "EnumPrintProcessors unexpected return code");
702 blob = data_blob_talloc(ctx, NULL, needed);
703 data_blob_clear(&blob);
705 r.in.offered = needed;
707 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
708 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
710 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
712 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
714 ctx->print_processor_count[level] = count;
715 ctx->print_processors[level] = info;
718 for (i=1;i<ARRAY_SIZE(levels);i++) {
719 int level = levels[i];
720 int old_level = levels[i-1];
721 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
722 "EnumPrintProcessors failed");
725 for (i=0;i<ARRAY_SIZE(levels);i++) {
726 int level = levels[i];
727 for (j=0;j<ctx->print_processor_count[level];j++) {
729 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
730 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
734 /* level 1 is our reference, and it makes no sense to compare it to itself */
743 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
744 struct dcerpc_pipe *p,
745 struct test_spoolss_context *ctx)
748 struct spoolss_EnumPrintProcDataTypes r;
749 uint16_t levels[] = { 1 };
752 for (i=0;i<ARRAY_SIZE(levels);i++) {
753 int level = levels[i];
757 union spoolss_PrintProcDataTypesInfo *info;
759 r.in.servername = "";
760 r.in.print_processor_name = "winprint";
764 r.out.needed = &needed;
765 r.out.count = &count;
768 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
770 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
771 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
772 if (W_ERROR_IS_OK(r.out.result)) {
773 /* TODO: do some more checks here */
776 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
777 "EnumPrintProcDataTypes unexpected return code");
779 blob = data_blob_talloc(ctx, NULL, needed);
780 data_blob_clear(&blob);
782 r.in.offered = needed;
784 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
785 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
787 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
789 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
797 static bool test_EnumPrinters(struct torture_context *tctx,
798 struct dcerpc_pipe *p,
799 struct test_spoolss_context *ctx)
801 struct spoolss_EnumPrinters r;
803 uint16_t levels[] = { 0, 1, 2, 4, 5 };
806 for (i=0;i<ARRAY_SIZE(levels);i++) {
807 int level = levels[i];
811 union spoolss_PrinterInfo *info;
813 r.in.flags = PRINTER_ENUM_LOCAL;
818 r.out.needed = &needed;
819 r.out.count = &count;
822 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
824 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
825 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
826 if (W_ERROR_IS_OK(r.out.result)) {
827 /* TODO: do some more checks here */
830 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
831 "EnumPrinters unexpected return code");
833 blob = data_blob_talloc(ctx, NULL, needed);
834 data_blob_clear(&blob);
836 r.in.offered = needed;
838 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
839 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
841 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
843 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
845 ctx->printer_count[level] = count;
846 ctx->printers[level] = info;
849 for (i=1;i<ARRAY_SIZE(levels);i++) {
850 int level = levels[i];
851 int old_level = levels[i-1];
852 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
853 "EnumPrinters invalid value");
856 for (i=0;i<ARRAY_SIZE(levels);i++) {
857 int level = levels[i];
858 for (j=0;j<ctx->printer_count[level];j++) {
859 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
860 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
863 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
864 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
865 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
866 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
867 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
868 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
869 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
870 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
871 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
872 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
873 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
874 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
875 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
876 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
877 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
878 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
879 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
880 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
881 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
882 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
883 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
884 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
885 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
886 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
887 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
888 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
889 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
890 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
891 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
894 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
895 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
896 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
897 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
900 /* level 2 is our reference, and it makes no sense to compare it to itself */
903 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
904 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
905 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
908 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
909 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
910 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
911 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
912 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
919 * - verify that the port of a printer was in the list returned by EnumPorts
925 static bool test_GetPrinterDriver2(struct torture_context *tctx,
926 struct dcerpc_pipe *p,
927 struct policy_handle *handle,
928 const char *driver_name,
929 const char *environment);
931 bool test_GetPrinter_level(struct torture_context *tctx,
932 struct dcerpc_pipe *p,
933 struct policy_handle *handle,
935 union spoolss_PrinterInfo *info)
937 struct spoolss_GetPrinter r;
940 r.in.handle = handle;
944 r.out.needed = &needed;
946 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
948 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter(p, tctx, &r),
949 "GetPrinter failed");
951 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
952 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
953 data_blob_clear(&blob);
955 r.in.offered = needed;
957 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter(p, tctx, &r),
958 "GetPrinter failed");
961 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
963 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
965 if (info && r.out.info) {
973 static bool test_GetPrinter(struct torture_context *tctx,
974 struct dcerpc_pipe *p,
975 struct policy_handle *handle,
976 const char *environment)
978 uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
981 for (i=0;i<ARRAY_SIZE(levels);i++) {
983 union spoolss_PrinterInfo info;
987 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, levels[i], &info),
988 "failed to call GetPrinter");
990 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
992 test_GetPrinterDriver2(tctx, p, handle, info.info2.drivername, environment),
993 "failed to call test_GetPrinterDriver2");
1000 static bool test_SetPrinter(struct torture_context *tctx,
1001 struct dcerpc_pipe *p,
1002 struct policy_handle *handle,
1003 struct spoolss_SetPrinterInfoCtr *info_ctr,
1004 struct spoolss_DevmodeContainer *devmode_ctr,
1005 struct sec_desc_buf *secdesc_ctr,
1006 enum spoolss_PrinterControl command)
1008 struct spoolss_SetPrinter r;
1010 r.in.handle = handle;
1011 r.in.info_ctr = info_ctr;
1012 r.in.devmode_ctr = devmode_ctr;
1013 r.in.secdesc_ctr = secdesc_ctr;
1014 r.in.command = command;
1016 torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1018 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
1019 "failed to call SetPrinter");
1020 torture_assert_werr_ok(tctx, r.out.result,
1021 "failed to call SetPrinter");
1026 static bool test_SetPrinter_errors(struct torture_context *tctx,
1027 struct dcerpc_pipe *p,
1028 struct policy_handle *handle)
1030 struct spoolss_SetPrinter r;
1031 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1034 struct spoolss_SetPrinterInfoCtr info_ctr;
1035 struct spoolss_DevmodeContainer devmode_ctr;
1036 struct sec_desc_buf secdesc_ctr;
1039 info_ctr.info.info0 = NULL;
1041 ZERO_STRUCT(devmode_ctr);
1042 ZERO_STRUCT(secdesc_ctr);
1044 r.in.handle = handle;
1045 r.in.info_ctr = &info_ctr;
1046 r.in.devmode_ctr = &devmode_ctr;
1047 r.in.secdesc_ctr = &secdesc_ctr;
1050 torture_comment(tctx, "Testing SetPrinter all zero\n");
1052 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
1053 "failed to call SetPrinter");
1054 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1055 "failed to call SetPrinter");
1058 for (i=0; i < ARRAY_SIZE(levels); i++) {
1060 struct spoolss_SetPrinterInfo0 info0;
1061 struct spoolss_SetPrinterInfo1 info1;
1062 struct spoolss_SetPrinterInfo2 info2;
1063 struct spoolss_SetPrinterInfo3 info3;
1064 struct spoolss_SetPrinterInfo4 info4;
1065 struct spoolss_SetPrinterInfo5 info5;
1066 struct spoolss_SetPrinterInfo6 info6;
1067 struct spoolss_SetPrinterInfo7 info7;
1068 struct spoolss_SetPrinterInfo8 info8;
1069 struct spoolss_SetPrinterInfo9 info9;
1072 info_ctr.level = levels[i];
1073 switch (levels[i]) {
1076 info_ctr.info.info0 = &info0;
1080 info_ctr.info.info1 = &info1;
1084 info_ctr.info.info2 = &info2;
1088 info_ctr.info.info3 = &info3;
1092 info_ctr.info.info4 = &info4;
1096 info_ctr.info.info5 = &info5;
1100 info_ctr.info.info6 = &info6;
1104 info_ctr.info.info7 = &info7;
1108 info_ctr.info.info8 = &info8;
1112 info_ctr.info.info9 = &info9;
1116 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1117 info_ctr.level, r.in.command);
1119 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
1120 "failed to call SetPrinter");
1122 switch (r.in.command) {
1123 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1124 /* is ignored for all levels other then 0 */
1125 if (info_ctr.level > 0) {
1129 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1130 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1131 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1132 if (info_ctr.level > 0) {
1133 /* is invalid for all levels other then 0 */
1134 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1135 "unexpected error code returned");
1138 torture_assert_werr_ok(tctx, r.out.result,
1139 "failed to call SetPrinter with non 0 command");
1144 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1145 /* FIXME: gd needs further investigation */
1147 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1148 "unexpected error code returned");
1152 switch (info_ctr.level) {
1154 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1155 "unexpected error code returned");
1158 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1159 "unexpected error code returned");
1165 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1166 "unexpected error code returned");
1169 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1170 "unexpected error code returned");
1173 torture_assert_werr_ok(tctx, r.out.result,
1174 "failed to call SetPrinter");
1179 if (r.in.command < 5) {
1187 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1189 if ((r->level == 2) && (r->info.info2)) {
1190 r->info.info2->secdesc_ptr = 0;
1191 r->info.info2->devmode_ptr = 0;
1195 static bool test_PrinterInfo(struct torture_context *tctx,
1196 struct dcerpc_pipe *p,
1197 struct policy_handle *handle)
1200 struct spoolss_SetPrinter s;
1201 struct spoolss_GetPrinter q;
1202 struct spoolss_GetPrinter q0;
1203 struct spoolss_SetPrinterInfoCtr info_ctr;
1204 union spoolss_PrinterInfo info;
1205 struct spoolss_DevmodeContainer devmode_ctr;
1206 struct sec_desc_buf secdesc_ctr;
1211 uint32_t status_list[] = {
1212 /* these do not stick
1213 PRINTER_STATUS_PAUSED,
1214 PRINTER_STATUS_ERROR,
1215 PRINTER_STATUS_PENDING_DELETION, */
1216 PRINTER_STATUS_PAPER_JAM,
1217 PRINTER_STATUS_PAPER_OUT,
1218 PRINTER_STATUS_MANUAL_FEED,
1219 PRINTER_STATUS_PAPER_PROBLEM,
1220 PRINTER_STATUS_OFFLINE,
1221 PRINTER_STATUS_IO_ACTIVE,
1222 PRINTER_STATUS_BUSY,
1223 PRINTER_STATUS_PRINTING,
1224 PRINTER_STATUS_OUTPUT_BIN_FULL,
1225 PRINTER_STATUS_NOT_AVAILABLE,
1226 PRINTER_STATUS_WAITING,
1227 PRINTER_STATUS_PROCESSING,
1228 PRINTER_STATUS_INITIALIZING,
1229 PRINTER_STATUS_WARMING_UP,
1230 PRINTER_STATUS_TONER_LOW,
1231 PRINTER_STATUS_NO_TONER,
1232 PRINTER_STATUS_PAGE_PUNT,
1233 PRINTER_STATUS_USER_INTERVENTION,
1234 PRINTER_STATUS_OUT_OF_MEMORY,
1235 PRINTER_STATUS_DOOR_OPEN,
1236 PRINTER_STATUS_SERVER_UNKNOWN,
1237 PRINTER_STATUS_POWER_SAVE,
1238 /* these do not stick
1247 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1248 uint32_t attribute_list[] = {
1249 PRINTER_ATTRIBUTE_QUEUED,
1250 /* fails with WERR_INVALID_DATATYPE:
1251 PRINTER_ATTRIBUTE_DIRECT, */
1253 PRINTER_ATTRIBUTE_DEFAULT, */
1254 PRINTER_ATTRIBUTE_SHARED,
1256 PRINTER_ATTRIBUTE_NETWORK, */
1257 PRINTER_ATTRIBUTE_HIDDEN,
1258 PRINTER_ATTRIBUTE_LOCAL,
1259 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1260 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1261 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1262 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1264 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1265 /* fails with WERR_INVALID_DATATYPE:
1266 PRINTER_ATTRIBUTE_RAW_ONLY, */
1267 /* these do not stick
1268 PRINTER_ATTRIBUTE_PUBLISHED,
1269 PRINTER_ATTRIBUTE_FAX,
1270 PRINTER_ATTRIBUTE_TS,
1289 ZERO_STRUCT(devmode_ctr);
1290 ZERO_STRUCT(secdesc_ctr);
1292 s.in.handle = handle;
1294 s.in.info_ctr = &info_ctr;
1295 s.in.devmode_ctr = &devmode_ctr;
1296 s.in.secdesc_ctr = &secdesc_ctr;
1298 q.in.handle = handle;
1302 #define TESTGETCALL(call, r) \
1303 r.in.buffer = NULL; \
1305 r.out.needed = &needed; \
1306 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1307 if (!NT_STATUS_IS_OK(status)) { \
1308 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1309 r.in.level, nt_errstr(status), __location__); \
1313 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1314 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1315 data_blob_clear(&blob); \
1316 r.in.buffer = &blob; \
1317 r.in.offered = needed; \
1319 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1320 if (!NT_STATUS_IS_OK(status)) { \
1321 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1322 r.in.level, nt_errstr(status), __location__); \
1326 if (!W_ERROR_IS_OK(r.out.result)) { \
1327 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1328 r.in.level, win_errstr(r.out.result), __location__); \
1334 #define TESTSETCALL_EXP(call, r, err) \
1335 clear_info2(&info_ctr);\
1336 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1337 if (!NT_STATUS_IS_OK(status)) { \
1338 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1339 r.in.info_ctr->level, nt_errstr(status), __location__); \
1343 if (!W_ERROR_IS_OK(err)) { \
1344 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1345 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1346 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1351 if (!W_ERROR_IS_OK(r.out.result)) { \
1352 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1353 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1358 #define TESTSETCALL(call, r) \
1359 TESTSETCALL_EXP(call, r, WERR_OK)
1361 #define STRING_EQUAL(s1, s2, field) \
1362 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1363 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1364 #field, s2, __location__); \
1369 #define MEM_EQUAL(s1, s2, length, field) \
1370 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1371 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1372 #field, (const char *)s2, __location__); \
1377 #define INT_EQUAL(i1, i2, field) \
1379 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1380 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1385 #define SD_EQUAL(sd1, sd2, field) \
1386 if (!security_descriptor_equal(sd1, sd2)) { \
1387 torture_comment(tctx, "Failed to set %s (%s)\n", \
1388 #field, __location__); \
1393 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1394 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1395 q.in.level = lvl1; \
1396 TESTGETCALL(GetPrinter, q) \
1397 info_ctr.level = lvl1; \
1398 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1399 info_ctr.info.info ## lvl1->field1 = value;\
1400 TESTSETCALL_EXP(SetPrinter, s, err) \
1401 info_ctr.info.info ## lvl1->field1 = ""; \
1402 TESTGETCALL(GetPrinter, q) \
1403 info_ctr.info.info ## lvl1->field1 = value; \
1404 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1405 q.in.level = lvl2; \
1406 TESTGETCALL(GetPrinter, q) \
1407 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1408 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1411 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1412 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1415 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1416 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1417 q.in.level = lvl1; \
1418 TESTGETCALL(GetPrinter, q) \
1419 info_ctr.level = lvl1; \
1420 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1421 info_ctr.info.info ## lvl1->field1 = value; \
1422 TESTSETCALL(SetPrinter, s) \
1423 info_ctr.info.info ## lvl1->field1 = 0; \
1424 TESTGETCALL(GetPrinter, q) \
1425 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1426 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1427 q.in.level = lvl2; \
1428 TESTGETCALL(GetPrinter, q) \
1429 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1430 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1433 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1434 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1438 do { TESTGETCALL(GetPrinter, q0) } while (0);
1440 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1441 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1443 /* level 0 printername does not stick */
1444 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1445 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1446 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1447 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1448 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1449 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1450 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1451 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1452 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1453 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1454 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1455 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1456 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1457 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1458 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1460 /* servername can be set but does not stick
1461 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1462 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1463 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1466 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1467 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1468 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1469 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1470 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1472 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1473 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1474 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1475 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1476 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1477 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1478 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1479 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1480 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1481 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1483 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1484 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1486 (attribute_list[i] | default_attribute)
1488 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1490 (attribute_list[i] | default_attribute)
1492 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1494 (attribute_list[i] | default_attribute)
1496 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1498 (attribute_list[i] | default_attribute)
1500 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1502 (attribute_list[i] | default_attribute)
1504 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1506 (attribute_list[i] | default_attribute)
1508 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1510 (attribute_list[i] | default_attribute)
1512 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1514 (attribute_list[i] | default_attribute)
1516 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1518 (attribute_list[i] | default_attribute)
1520 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1522 (attribute_list[i] | default_attribute)
1524 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1526 (attribute_list[i] | default_attribute)
1528 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1530 (attribute_list[i] | default_attribute)
1534 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1535 /* level 2 sets do not stick
1536 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1537 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1538 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1539 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1540 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1541 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1544 /* priorities need to be between 0 and 99
1545 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1546 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1547 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1548 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1549 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1550 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1551 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1552 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1553 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1555 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1556 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1559 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1560 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1563 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1564 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1566 /* FIXME: gd also test devmode and secdesc behavior */
1569 /* verify composition of level 1 description field */
1570 const char *description;
1574 do { TESTGETCALL(GetPrinter, q0) } while (0);
1576 description = talloc_strdup(tctx, q0.out.info->info1.description);
1579 do { TESTGETCALL(GetPrinter, q0) } while (0);
1581 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1582 q0.out.info->info2.printername,
1583 q0.out.info->info2.drivername,
1584 q0.out.info->info2.location);
1586 do { STRING_EQUAL(description, tmp, "description")} while (0);
1592 #define torture_assert_sid_equal(torture_ctx,got,expected,cmt)\
1593 do { struct dom_sid *__got = (got), *__expected = (expected); \
1594 if (!dom_sid_equal(__got, __expected)) { \
1595 torture_result(torture_ctx, TORTURE_FAIL, \
1596 __location__": "#got" was %s, expected %s: %s", \
1597 dom_sid_string(torture_ctx, __got), dom_sid_string(torture_ctx, __expected), cmt); \
1602 static bool test_security_descriptor_equal(struct torture_context *tctx,
1603 const struct security_descriptor *sd1,
1604 const struct security_descriptor *sd2)
1611 torture_comment(tctx, "%s\n", __location__);
1615 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1616 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1618 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1619 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1621 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1622 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1623 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1624 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1627 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1628 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1629 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1630 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1637 static bool test_sd_set_level(struct torture_context *tctx,
1638 struct dcerpc_pipe *p,
1639 struct policy_handle *handle,
1641 struct security_descriptor *sd)
1643 struct spoolss_SetPrinterInfoCtr info_ctr;
1644 struct spoolss_DevmodeContainer devmode_ctr;
1645 struct sec_desc_buf secdesc_ctr;
1646 union spoolss_SetPrinterInfo sinfo;
1648 ZERO_STRUCT(devmode_ctr);
1649 ZERO_STRUCT(secdesc_ctr);
1653 union spoolss_PrinterInfo info;
1654 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1655 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1658 info_ctr.info = sinfo;
1663 struct spoolss_SetPrinterInfo3 info3;
1665 info3.sec_desc_ptr = 0;
1668 info_ctr.info.info3 = &info3;
1676 secdesc_ctr.sd = sd;
1678 torture_assert(tctx,
1679 test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1684 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1685 struct dcerpc_pipe *p,
1686 struct policy_handle *handle)
1688 union spoolss_PrinterInfo info;
1689 struct security_descriptor *sd1, *sd2;
1692 /* just compare level 2 and level 3 */
1694 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1696 sd1 = info.info2.secdesc;
1698 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 3, &info), "");
1700 sd2 = info.info3.secdesc;
1702 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1703 "SD level 2 != SD level 3");
1706 /* query level 2, set level 2, query level 2 */
1708 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1710 sd1 = info.info2.secdesc;
1712 torture_assert(tctx, test_sd_set_level(tctx, p, handle, 2, sd1), "");
1714 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1716 sd2 = info.info2.secdesc;
1717 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1718 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1719 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1722 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1723 "SD level 2 != SD level 2 after SD has been set via level 2");
1726 /* query level 2, set level 3, query level 2 */
1728 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1730 sd1 = info.info2.secdesc;
1732 torture_assert(tctx, test_sd_set_level(tctx, p, handle, 3, sd1), "");
1734 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1736 sd2 = info.info2.secdesc;
1738 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1739 "SD level 2 != SD level 2 after SD has been set via level 3");
1741 /* set modified sd level 3, query level 2 */
1743 for (i=0; i < 93; i++) {
1744 struct security_ace a;
1745 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1746 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1748 a.size = 0; /* autogenerated */
1750 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1751 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1754 torture_assert(tctx, test_sd_set_level(tctx, p, handle, 3, sd1), "");
1756 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1757 sd2 = info.info2.secdesc;
1759 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1760 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1761 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1764 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1765 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1772 * wrapper call that saves original sd, runs tests, and restores sd
1775 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1776 struct dcerpc_pipe *p,
1777 struct policy_handle *handle)
1779 union spoolss_PrinterInfo info;
1780 struct security_descriptor *sd;
1783 torture_comment(tctx, "Testing Printer Security Descriptors\n");
1785 /* save original sd */
1787 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
1788 "failed to get initial security descriptor");
1790 sd = security_descriptor_copy(tctx, info.info2.secdesc);
1794 ret = test_PrinterInfo_SDs(tctx, p, handle);
1796 /* restore original sd */
1798 torture_assert(tctx, test_sd_set_level(tctx, p, handle, 3, sd),
1799 "failed to restore initial security descriptor");
1801 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
1802 ret ? "succeeded" : "failed");
1808 static bool test_devmode_set_level(struct torture_context *tctx,
1809 struct dcerpc_pipe *p,
1810 struct policy_handle *handle,
1812 struct spoolss_DeviceMode *devmode)
1814 struct spoolss_SetPrinterInfoCtr info_ctr;
1815 struct spoolss_DevmodeContainer devmode_ctr;
1816 struct sec_desc_buf secdesc_ctr;
1817 union spoolss_SetPrinterInfo sinfo;
1819 ZERO_STRUCT(devmode_ctr);
1820 ZERO_STRUCT(secdesc_ctr);
1824 union spoolss_PrinterInfo info;
1825 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
1826 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1829 info_ctr.info = sinfo;
1834 struct spoolss_SetPrinterInfo8 info8;
1836 info8.devmode_ptr = 0;
1839 info_ctr.info.info8 = &info8;
1847 devmode_ctr.devmode = devmode;
1849 torture_assert(tctx,
1850 test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1856 static bool test_devicemode_equal(struct torture_context *tctx,
1857 const struct spoolss_DeviceMode *d1,
1858 const struct spoolss_DeviceMode *d2)
1865 torture_comment(tctx, "%s\n", __location__);
1868 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
1869 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
1870 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
1871 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
1872 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
1873 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
1874 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
1875 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
1876 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
1877 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
1878 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
1879 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
1880 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
1881 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
1882 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
1883 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
1884 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
1885 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
1886 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
1887 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
1888 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
1889 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
1890 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
1891 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
1892 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
1893 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
1894 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
1895 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
1896 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
1897 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
1898 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
1899 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
1900 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
1901 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
1902 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
1907 static bool test_devicemode_full(struct torture_context *tctx,
1908 struct dcerpc_pipe *p,
1909 struct policy_handle *handle)
1911 struct spoolss_SetPrinter s;
1912 struct spoolss_GetPrinter q;
1913 struct spoolss_GetPrinter q0;
1914 struct spoolss_SetPrinterInfoCtr info_ctr;
1915 struct spoolss_SetPrinterInfo8 info8;
1916 union spoolss_PrinterInfo info;
1917 struct spoolss_DevmodeContainer devmode_ctr;
1918 struct sec_desc_buf secdesc_ctr;
1923 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1924 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1925 q.in.level = lvl1; \
1926 TESTGETCALL(GetPrinter, q) \
1927 info_ctr.level = lvl1; \
1929 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1930 } else if (lvl1 == 8) {\
1931 info_ctr.info.info ## lvl1 = &info8; \
1933 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
1934 devmode_ctr.devmode->field1 = value; \
1935 TESTSETCALL(SetPrinter, s) \
1936 TESTGETCALL(GetPrinter, q) \
1937 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
1938 q.in.level = lvl2; \
1939 TESTGETCALL(GetPrinter, q) \
1940 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
1943 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
1944 TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1947 ZERO_STRUCT(devmode_ctr);
1948 ZERO_STRUCT(secdesc_ctr);
1951 s.in.handle = handle;
1953 s.in.info_ctr = &info_ctr;
1954 s.in.devmode_ctr = &devmode_ctr;
1955 s.in.secdesc_ctr = &secdesc_ctr;
1957 q.in.handle = handle;
1962 const char *devicename;/* [charset(UTF16)] */
1963 enum spoolss_DeviceModeSpecVersion specversion;
1964 uint16_t driverversion;
1966 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
1970 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
1971 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
1972 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
1973 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
1974 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
1975 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
1976 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
1977 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
1978 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
1979 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
1980 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
1981 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
1982 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
1984 const char *formname;/* [charset(UTF16)] */
1986 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
1987 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
1988 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
1989 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
1990 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
1991 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
1992 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
1993 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
1994 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
1995 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
1996 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
1997 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
1998 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
1999 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
2004 static bool call_OpenPrinterEx(struct torture_context *tctx,
2005 struct dcerpc_pipe *p,
2007 struct spoolss_DeviceMode *devmode,
2008 struct policy_handle *handle);
2010 static bool test_ClosePrinter(struct torture_context *tctx,
2011 struct dcerpc_pipe *p,
2012 struct policy_handle *handle);
2014 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2015 struct dcerpc_pipe *p,
2016 struct policy_handle *handle,
2019 union spoolss_PrinterInfo info;
2020 struct spoolss_DeviceMode *devmode;
2021 struct spoolss_DeviceMode *devmode2;
2022 struct policy_handle handle_devmode;
2024 /* simply compare level8 and level2 devmode */
2026 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 8, &info), "");
2028 devmode = info.info8.devmode;
2030 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
2032 devmode2 = info.info2.devmode;
2034 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2035 "DM level 8 != DM level 2");
2038 /* set devicemode level 8 and see if it persists */
2040 devmode->copies = 93;
2041 devmode->formname = talloc_strdup(tctx, "Legal");
2043 torture_assert(tctx, test_devmode_set_level(tctx, p, handle, 8, devmode), "");
2045 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 8, &info), "");
2047 devmode2 = info.info8.devmode;
2049 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2050 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2052 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
2054 devmode2 = info.info2.devmode;
2056 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2057 "modified DM level 8 != DM level 2");
2060 /* set devicemode level 2 and see if it persists */
2062 devmode->copies = 39;
2063 devmode->formname = talloc_strdup(tctx, "Executive");
2065 torture_assert(tctx, test_devmode_set_level(tctx, p, handle, 2, devmode), "");
2067 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 8, &info), "");
2069 devmode2 = info.info8.devmode;
2071 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2072 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2074 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info), "");
2076 devmode2 = info.info2.devmode;
2078 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2079 "modified DM level 8 != DM level 2");
2082 /* check every single bit in public part of devicemode */
2084 torture_assert(tctx, test_devicemode_full(tctx, p, handle),
2085 "failed to set every single devicemode component");
2088 /* change formname upon open and see if it persists in getprinter calls */
2090 devmode->formname = talloc_strdup(tctx, "A4");
2091 devmode->copies = 42;
2093 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2094 "failed to open printer handle");
2096 torture_assert(tctx, test_GetPrinter_level(tctx, p, &handle_devmode, 8, &info), "");
2098 devmode2 = info.info8.devmode;
2100 if (strequal(devmode->devicename, devmode2->devicename)) {
2101 torture_warning(tctx, "devicenames are the same\n");
2103 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2104 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2107 if (strequal(devmode->formname, devmode2->formname)) {
2108 torture_warning(tctx, "formname are the same\n");
2110 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2111 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2114 if (devmode->copies == devmode2->copies) {
2115 torture_warning(tctx, "copies are the same\n");
2117 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2118 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2121 torture_assert(tctx, test_GetPrinter_level(tctx, p, &handle_devmode, 2, &info), "");
2123 devmode2 = info.info2.devmode;
2125 if (strequal(devmode->devicename, devmode2->devicename)) {
2126 torture_warning(tctx, "devicenames are the same\n");
2128 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2129 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2132 if (strequal(devmode->formname, devmode2->formname)) {
2133 torture_warning(tctx, "formname is the same\n");
2135 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2136 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2139 if (devmode->copies == devmode2->copies) {
2140 torture_warning(tctx, "copies are the same\n");
2142 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2143 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2146 test_ClosePrinter(tctx, p, &handle_devmode);
2152 * wrapper call that saves original devmode, runs tests, and restores devmode
2155 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2156 struct dcerpc_pipe *p,
2157 struct policy_handle *handle,
2160 union spoolss_PrinterInfo info;
2161 struct spoolss_DeviceMode *devmode;
2164 torture_comment(tctx, "Testing Printer Devicemodes\n");
2166 /* save original devmode */
2168 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 8, &info),
2169 "failed to get initial global devicemode");
2171 devmode = info.info8.devmode;
2175 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2177 /* restore original devmode */
2179 torture_assert(tctx, test_devmode_set_level(tctx, p, handle, 8, devmode),
2180 "failed to restore initial global device mode");
2182 torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2183 ret ? "succeeded" : "failed");
2189 static bool test_ClosePrinter(struct torture_context *tctx,
2190 struct dcerpc_pipe *p,
2191 struct policy_handle *handle)
2194 struct spoolss_ClosePrinter r;
2196 r.in.handle = handle;
2197 r.out.handle = handle;
2199 torture_comment(tctx, "Testing ClosePrinter\n");
2201 status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
2202 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2203 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2208 static bool test_GetForm(struct torture_context *tctx,
2209 struct dcerpc_pipe *p,
2210 struct policy_handle *handle,
2211 const char *form_name,
2215 struct spoolss_GetForm r;
2218 r.in.handle = handle;
2219 r.in.form_name = form_name;
2223 r.out.needed = &needed;
2225 torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
2227 status = dcerpc_spoolss_GetForm(p, tctx, &r);
2228 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2230 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2231 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2232 data_blob_clear(&blob);
2233 r.in.buffer = &blob;
2234 r.in.offered = needed;
2235 status = dcerpc_spoolss_GetForm(p, tctx, &r);
2236 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2238 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2240 torture_assert(tctx, r.out.info, "No form info returned");
2243 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2245 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2250 static bool test_EnumForms(struct torture_context *tctx,
2251 struct dcerpc_pipe *p,
2252 struct policy_handle *handle, bool print_server)
2255 struct spoolss_EnumForms r;
2259 uint32_t levels[] = { 1, 2 };
2262 for (i=0; i<ARRAY_SIZE(levels); i++) {
2264 union spoolss_FormInfo *info;
2266 r.in.handle = handle;
2267 r.in.level = levels[i];
2270 r.out.needed = &needed;
2271 r.out.count = &count;
2274 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
2276 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
2277 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
2279 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2283 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
2284 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2286 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2288 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2289 data_blob_clear(&blob);
2290 r.in.buffer = &blob;
2291 r.in.offered = needed;
2293 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
2295 torture_assert(tctx, info, "No forms returned");
2297 for (j = 0; j < count; j++) {
2299 ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
2303 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
2305 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2307 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2313 static bool test_DeleteForm(struct torture_context *tctx,
2314 struct dcerpc_pipe *p,
2315 struct policy_handle *handle,
2316 const char *form_name)
2319 struct spoolss_DeleteForm r;
2321 r.in.handle = handle;
2322 r.in.form_name = form_name;
2324 status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
2326 torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
2328 torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
2333 static bool test_AddForm(struct torture_context *tctx,
2334 struct dcerpc_pipe *p,
2335 struct policy_handle *handle, bool print_server)
2337 struct spoolss_AddForm r;
2338 struct spoolss_AddFormInfo1 addform;
2339 const char *form_name = "testform3";
2343 r.in.handle = handle;
2345 r.in.info.info1 = &addform;
2346 addform.flags = SPOOLSS_FORM_USER;
2347 addform.form_name = form_name;
2348 addform.size.width = 50;
2349 addform.size.height = 25;
2350 addform.area.left = 5;
2351 addform.area.top = 10;
2352 addform.area.right = 45;
2353 addform.area.bottom = 15;
2355 status = dcerpc_spoolss_AddForm(p, tctx, &r);
2357 torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
2359 torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
2361 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
2364 struct spoolss_SetForm sf;
2365 struct spoolss_AddFormInfo1 setform;
2367 sf.in.handle = handle;
2368 sf.in.form_name = form_name;
2370 sf.in.info.info1= &setform;
2371 setform.flags = addform.flags;
2372 setform.form_name = addform.form_name;
2373 setform.size = addform.size;
2374 setform.area = addform.area;
2376 setform.size.width = 1234;
2378 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
2380 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
2382 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
2385 if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
2388 struct spoolss_EnumForms e;
2389 union spoolss_FormInfo *info;
2394 e.in.handle = handle;
2398 e.out.needed = &needed;
2399 e.out.count = &count;
2402 torture_comment(tctx, "Testing EnumForms level 1\n");
2404 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
2405 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
2407 if (print_server && W_ERROR_EQUAL(e.out.result, WERR_BADFID))
2408 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2410 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
2412 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2413 data_blob_clear(&blob);
2414 e.in.buffer = &blob;
2415 e.in.offered = needed;
2417 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
2419 torture_assert(tctx, info, "No forms returned");
2421 for (j = 0; j < count; j++) {
2422 if (strequal(form_name, info[j].info1.form_name)) {
2428 torture_assert(tctx, found, "Newly added form not found in enum call");
2431 if (!test_DeleteForm(tctx, p, handle, form_name)) {
2438 static bool test_EnumPorts_old(struct torture_context *tctx,
2439 struct dcerpc_pipe *p)
2442 struct spoolss_EnumPorts r;
2445 union spoolss_PortInfo *info;
2447 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2448 dcerpc_server_name(p));
2452 r.out.needed = &needed;
2453 r.out.count = &count;
2456 torture_comment(tctx, "Testing EnumPorts\n");
2458 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
2460 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2462 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2463 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2464 data_blob_clear(&blob);
2465 r.in.buffer = &blob;
2466 r.in.offered = needed;
2468 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
2469 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2470 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2472 torture_assert(tctx, info, "No ports returned");
2475 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2477 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2482 static bool test_AddPort(struct torture_context *tctx,
2483 struct dcerpc_pipe *p)
2486 struct spoolss_AddPort r;
2488 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
2489 dcerpc_server_name(p));
2491 r.in.monitor_name = "foo";
2493 torture_comment(tctx, "Testing AddPort\n");
2495 status = dcerpc_spoolss_AddPort(p, tctx, &r);
2497 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
2499 /* win2k3 returns WERR_NOT_SUPPORTED */
2503 if (!W_ERROR_IS_OK(r.out.result)) {
2504 printf("AddPort failed - %s\n", win_errstr(r.out.result));
2513 static bool test_GetJob(struct torture_context *tctx,
2514 struct dcerpc_pipe *p,
2515 struct policy_handle *handle, uint32_t job_id)
2518 struct spoolss_GetJob r;
2519 union spoolss_JobInfo info;
2521 uint32_t levels[] = {1, 2 /* 3, 4 */};
2524 r.in.handle = handle;
2525 r.in.job_id = job_id;
2529 r.out.needed = &needed;
2532 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
2534 status = dcerpc_spoolss_GetJob(p, tctx, &r);
2535 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
2537 for (i = 0; i < ARRAY_SIZE(levels); i++) {
2539 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
2543 r.in.level = levels[i];
2547 status = dcerpc_spoolss_GetJob(p, tctx, &r);
2548 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2550 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2551 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2552 data_blob_clear(&blob);
2553 r.in.buffer = &blob;
2554 r.in.offered = needed;
2556 status = dcerpc_spoolss_GetJob(p, tctx, &r);
2557 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2560 torture_assert(tctx, r.out.info, "No job info returned");
2561 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
2563 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2569 static bool test_SetJob(struct torture_context *tctx,
2570 struct dcerpc_pipe *p,
2571 struct policy_handle *handle, uint32_t job_id,
2572 enum spoolss_JobControl command)
2575 struct spoolss_SetJob r;
2577 r.in.handle = handle;
2578 r.in.job_id = job_id;
2580 r.in.command = command;
2583 case SPOOLSS_JOB_CONTROL_PAUSE:
2584 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
2586 case SPOOLSS_JOB_CONTROL_RESUME:
2587 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
2589 case SPOOLSS_JOB_CONTROL_CANCEL:
2590 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
2592 case SPOOLSS_JOB_CONTROL_RESTART:
2593 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
2595 case SPOOLSS_JOB_CONTROL_DELETE:
2596 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
2598 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
2599 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
2601 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
2602 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
2604 case SPOOLSS_JOB_CONTROL_RETAIN:
2605 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
2607 case SPOOLSS_JOB_CONTROL_RELEASE:
2608 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
2611 torture_comment(tctx, "Testing SetJob\n");
2615 status = dcerpc_spoolss_SetJob(p, tctx, &r);
2616 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
2617 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
2622 static bool test_AddJob(struct torture_context *tctx,
2623 struct dcerpc_pipe *p,
2624 struct policy_handle *handle)
2627 struct spoolss_AddJob r;
2631 r.in.handle = handle;
2633 r.out.needed = &needed;
2634 r.in.buffer = r.out.buffer = NULL;
2636 torture_comment(tctx, "Testing AddJob\n");
2638 status = dcerpc_spoolss_AddJob(p, tctx, &r);
2639 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
2643 status = dcerpc_spoolss_AddJob(p, tctx, &r);
2644 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
2650 static bool test_EnumJobs(struct torture_context *tctx,
2651 struct dcerpc_pipe *p,
2652 struct policy_handle *handle)
2655 struct spoolss_EnumJobs r;
2658 union spoolss_JobInfo *info;
2660 r.in.handle = handle;
2662 r.in.numjobs = 0xffffffff;
2666 r.out.needed = &needed;
2667 r.out.count = &count;
2670 torture_comment(tctx, "Testing EnumJobs\n");
2672 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
2674 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
2676 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2678 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2679 data_blob_clear(&blob);
2680 r.in.buffer = &blob;
2681 r.in.offered = needed;
2683 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
2685 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
2686 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
2687 torture_assert(tctx, info, "No jobs returned");
2689 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2691 for (j = 0; j < count; j++) {
2693 torture_assert(tctx, test_GetJob(tctx, p, handle, info[j].info1.job_id),
2694 "failed to call test_GetJob");
2697 if (!torture_setting_bool(tctx, "samba3", false)) {
2698 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
2699 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
2704 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
2710 static bool test_DoPrintTest(struct torture_context *tctx,
2711 struct dcerpc_pipe *p,
2712 struct policy_handle *handle)
2716 struct spoolss_StartDocPrinter s;
2717 struct spoolss_DocumentInfo1 info1;
2718 struct spoolss_StartPagePrinter sp;
2719 struct spoolss_WritePrinter w;
2720 struct spoolss_EndPagePrinter ep;
2721 struct spoolss_EndDocPrinter e;
2724 uint32_t num_written;
2726 torture_comment(tctx, "Testing StartDocPrinter\n");
2728 s.in.handle = handle;
2730 s.in.info.info1 = &info1;
2731 s.out.job_id = &job_id;
2732 info1.document_name = "TorturePrintJob";
2733 info1.output_file = NULL;
2734 info1.datatype = "RAW";
2736 status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
2737 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
2738 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
2740 for (i=1; i < 4; i++) {
2741 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
2743 sp.in.handle = handle;
2745 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
2746 torture_assert_ntstatus_ok(tctx, status,
2747 "dcerpc_spoolss_StartPagePrinter failed");
2748 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
2750 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
2752 w.in.handle = handle;
2753 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
2754 w.out.num_written = &num_written;
2756 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
2757 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
2758 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
2760 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
2762 ep.in.handle = handle;
2764 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
2765 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
2766 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
2769 torture_comment(tctx, "Testing EndDocPrinter\n");
2771 e.in.handle = handle;
2773 status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
2774 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
2775 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
2777 ret &= test_AddJob(tctx, p, handle);
2778 ret &= test_EnumJobs(tctx, p, handle);
2780 ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
2785 static bool test_PausePrinter(struct torture_context *tctx,
2786 struct dcerpc_pipe *p,
2787 struct policy_handle *handle)
2790 struct spoolss_SetPrinter r;
2791 struct spoolss_SetPrinterInfoCtr info_ctr;
2792 struct spoolss_DevmodeContainer devmode_ctr;
2793 struct sec_desc_buf secdesc_ctr;
2796 info_ctr.info.info0 = NULL;
2798 ZERO_STRUCT(devmode_ctr);
2799 ZERO_STRUCT(secdesc_ctr);
2801 r.in.handle = handle;
2802 r.in.info_ctr = &info_ctr;
2803 r.in.devmode_ctr = &devmode_ctr;
2804 r.in.secdesc_ctr = &secdesc_ctr;
2805 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
2807 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
2809 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2811 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2813 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2818 static bool test_ResumePrinter(struct torture_context *tctx,
2819 struct dcerpc_pipe *p,
2820 struct policy_handle *handle)
2823 struct spoolss_SetPrinter r;
2824 struct spoolss_SetPrinterInfoCtr info_ctr;
2825 struct spoolss_DevmodeContainer devmode_ctr;
2826 struct sec_desc_buf secdesc_ctr;
2829 info_ctr.info.info0 = NULL;
2831 ZERO_STRUCT(devmode_ctr);
2832 ZERO_STRUCT(secdesc_ctr);
2834 r.in.handle = handle;
2835 r.in.info_ctr = &info_ctr;
2836 r.in.devmode_ctr = &devmode_ctr;
2837 r.in.secdesc_ctr = &secdesc_ctr;
2838 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
2840 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
2842 status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
2844 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2846 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2851 static bool test_GetPrinterData(struct torture_context *tctx,
2852 struct dcerpc_pipe *p,
2853 struct policy_handle *handle,
2854 const char *value_name,
2855 enum winreg_Type *type_p,
2860 struct spoolss_GetPrinterData r;
2862 enum winreg_Type type;
2863 union spoolss_PrinterData data;
2865 r.in.handle = handle;
2866 r.in.value_name = value_name;
2868 r.out.needed = &needed;
2870 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
2872 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
2874 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2875 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2877 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2878 r.in.offered = needed;
2879 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
2880 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2881 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2884 torture_assert_werr_ok(tctx, r.out.result,
2885 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
2887 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2894 *data_p = r.out.data;
2904 static bool test_GetPrinterDataEx(struct torture_context *tctx,
2905 struct dcerpc_pipe *p,
2906 struct policy_handle *handle,
2907 const char *key_name,
2908 const char *value_name,
2909 enum winreg_Type *type_p,
2914 struct spoolss_GetPrinterDataEx r;
2915 enum winreg_Type type;
2917 union spoolss_PrinterData data;
2919 r.in.handle = handle;
2920 r.in.key_name = key_name;
2921 r.in.value_name = value_name;
2924 r.out.needed = &needed;
2925 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
2927 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
2928 r.in.key_name, r.in.value_name);
2930 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2931 if (!NT_STATUS_IS_OK(status)) {
2932 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
2933 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
2934 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
2936 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2939 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2940 r.in.offered = needed;
2941 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
2942 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2943 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2946 torture_assert_werr_ok(tctx, r.out.result,
2947 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
2949 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
2956 *data_p = r.out.data;
2966 static bool test_GetPrinterData_list(struct torture_context *tctx,
2967 struct dcerpc_pipe *p,
2968 struct policy_handle *handle,
2969 const char **architecture)
2971 const char *list[] = {
2975 /* "NetPopup", not on w2k8 */
2976 /* "NetPopupToComputer", not on w2k8 */
2979 "DefaultSpoolDirectory",
2983 /* "OSVersionEx", not on s3 */
2988 for (i=0; i < ARRAY_SIZE(list); i++) {
2989 enum winreg_Type type, type_ex;
2990 uint8_t *data, *data_ex;
2991 uint32_t needed, needed_ex;
2993 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, list[i], &type, &data, &needed),
2994 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
2995 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
2996 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
2997 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
2998 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
2999 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3001 if (strequal(list[i], "Architecture")) {
3003 DATA_BLOB blob = data_blob_const(data, needed);
3004 *architecture = reg_val_data_string(tctx, lp_iconv_convenience(tctx->lp_ctx), REG_SZ, blob);
3012 static bool test_EnumPrinterData(struct torture_context *tctx,
3013 struct dcerpc_pipe *p,
3014 struct policy_handle *handle,
3015 uint32_t enum_index,
3016 uint32_t value_offered,
3017 uint32_t data_offered,
3018 enum winreg_Type *type_p,
3019 uint32_t *value_needed_p,
3020 uint32_t *data_needed_p,
3021 const char **value_name_p,
3025 struct spoolss_EnumPrinterData r;
3026 uint32_t data_needed;
3027 uint32_t value_needed;
3028 enum winreg_Type type;
3030 r.in.handle = handle;
3031 r.in.enum_index = enum_index;
3032 r.in.value_offered = value_offered;
3033 r.in.data_offered = data_offered;
3034 r.out.data_needed = &data_needed;
3035 r.out.value_needed = &value_needed;
3037 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3038 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3040 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3042 torture_assert_ntstatus_ok(tctx,
3043 dcerpc_spoolss_EnumPrinterData(p, tctx, &r),
3044 "EnumPrinterData failed");
3049 if (value_needed_p) {
3050 *value_needed_p = value_needed;
3052 if (data_needed_p) {
3053 *data_needed_p = data_needed;
3056 *value_name_p = r.out.value_name;
3059 *data_p = r.out.data;
3062 *result_p = r.out.result;
3069 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3070 struct dcerpc_pipe *p,
3071 struct policy_handle *handle)
3073 uint32_t enum_index = 0;
3074 enum winreg_Type type;
3075 uint32_t value_needed;
3076 uint32_t data_needed;
3078 const char *value_name;
3081 torture_comment(tctx, "Testing EnumPrinterData\n");
3084 torture_assert(tctx,
3085 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3086 &type, &value_needed, &data_needed,
3087 &value_name, &data, &result),
3088 "EnumPrinterData failed");
3090 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3094 torture_assert(tctx,
3095 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3096 &type, &value_needed, &data_needed,
3097 &value_name, &data, &result),
3098 "EnumPrinterData failed");
3100 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3106 } while (W_ERROR_IS_OK(result));
3108 torture_comment(tctx, "EnumPrinterData test succeeded\n");
3113 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3114 struct dcerpc_pipe *p,
3115 struct policy_handle *handle,
3116 const char *key_name,
3118 struct spoolss_PrinterEnumValues **info_p)
3120 struct spoolss_EnumPrinterDataEx r;
3121 struct spoolss_PrinterEnumValues *info;
3125 r.in.handle = handle;
3126 r.in.key_name = key_name;
3128 r.out.needed = &needed;
3129 r.out.count = &count;
3132 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3134 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
3135 "EnumPrinterDataEx failed");
3136 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3137 r.in.offered = needed;
3138 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
3139 "EnumPrinterDataEx failed");
3142 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3144 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3156 static bool test_SetPrinterData(struct torture_context *tctx,
3157 struct dcerpc_pipe *p,
3158 struct policy_handle *handle,
3159 const char *value_name,
3160 enum winreg_Type type,
3163 static bool test_DeletePrinterData(struct torture_context *tctx,
3164 struct dcerpc_pipe *p,
3165 struct policy_handle *handle,
3166 const char *value_name);
3168 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3169 struct dcerpc_pipe *p,
3170 struct policy_handle *handle)
3173 struct spoolss_PrinterEnumValues *info;
3175 uint32_t value_needed, data_needed;
3176 uint32_t value_offered, data_offered;
3179 enum winreg_Type type;
3182 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3184 torture_assert(tctx,
3185 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3186 "REG_SZ", "torture_data1", &type, &blob), "");
3188 torture_assert(tctx,
3189 test_SetPrinterData(tctx, p, handle, "torture_value1", type, blob.data, blob.length),
3190 "SetPrinterData failed");
3192 blob = data_blob_string_const("torture_data2");
3194 torture_assert(tctx,
3195 test_SetPrinterData(tctx, p, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3196 "SetPrinterData failed");
3198 blob = data_blob_talloc(tctx, NULL, 4);
3199 SIVAL(blob.data, 0, 0x11223344);
3201 torture_assert(tctx,
3202 test_SetPrinterData(tctx, p, handle, "torture_value3", type, blob.data, blob.length),
3203 "SetPrinterData failed");
3205 torture_assert(tctx,
3206 test_EnumPrinterDataEx(tctx, p, handle, "PrinterDriverData", &count, &info),
3207 "failed to call EnumPrinterDataEx");
3209 /* get the max sizes for value and data */
3211 torture_assert(tctx,
3212 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3213 NULL, &value_needed, &data_needed,
3214 NULL, NULL, &result),
3215 "EnumPrinterData failed");
3216 torture_assert_werr_ok(tctx, result, "unexpected result");
3218 /* check if the reply from the EnumPrinterData really matches max values */
3220 for (i=0; i < count; i++) {
3221 if (info[i].value_name_len > value_needed) {
3223 talloc_asprintf(tctx,
3224 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3225 info[i].value_name_len, value_needed));
3227 if (info[i].data_length > data_needed) {
3229 talloc_asprintf(tctx,
3230 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3231 info[i].data_length, data_needed));
3235 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3236 * sort or not sort the replies by value name, we should be able to do
3237 * the following entry comparison */
3239 data_offered = data_needed;
3240 value_offered = value_needed;
3242 for (i=0; i < count; i++) {
3244 const char *value_name;
3247 torture_assert(tctx,
3248 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3249 &type, &value_needed, &data_needed,
3250 &value_name, &data, &result),
3251 "EnumPrinterData failed");
3253 if (i -1 == count) {
3254 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3255 "unexpected result");
3258 torture_assert_werr_ok(tctx, result, "unexpected result");
3261 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3262 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3263 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
3264 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
3265 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
3268 torture_assert(tctx,
3269 test_DeletePrinterData(tctx, p, handle, "torture_value1"),
3270 "DeletePrinterData failed");
3271 torture_assert(tctx,
3272 test_DeletePrinterData(tctx, p, handle, "torture_value2"),
3273 "DeletePrinterData failed");
3274 torture_assert(tctx,
3275 test_DeletePrinterData(tctx, p, handle, "torture_value3"),
3276 "DeletePrinterData failed");
3278 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
3283 static bool test_DeletePrinterData(struct torture_context *tctx,
3284 struct dcerpc_pipe *p,
3285 struct policy_handle *handle,
3286 const char *value_name)
3289 struct spoolss_DeletePrinterData r;
3291 r.in.handle = handle;
3292 r.in.value_name = value_name;
3294 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
3297 status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
3299 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
3300 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
3305 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
3306 struct dcerpc_pipe *p,
3307 struct policy_handle *handle,
3308 const char *key_name,
3309 const char *value_name)
3311 struct spoolss_DeletePrinterDataEx r;
3313 r.in.handle = handle;
3314 r.in.key_name = key_name;
3315 r.in.value_name = value_name;
3317 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
3318 r.in.key_name, r.in.value_name);
3320 torture_assert_ntstatus_ok(tctx,
3321 dcerpc_spoolss_DeletePrinterDataEx(p, tctx, &r),
3322 "DeletePrinterDataEx failed");
3323 torture_assert_werr_ok(tctx, r.out.result,
3324 "DeletePrinterDataEx failed");
3329 static bool test_DeletePrinterKey(struct torture_context *tctx,
3330 struct dcerpc_pipe *p,
3331 struct policy_handle *handle,
3332 const char *key_name)
3334 struct spoolss_DeletePrinterKey r;
3336 r.in.handle = handle;
3337 r.in.key_name = key_name;
3339 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
3341 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
3342 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
3346 torture_assert_ntstatus_ok(tctx,
3347 dcerpc_spoolss_DeletePrinterKey(p, tctx, &r),
3348 "DeletePrinterKey failed");
3349 torture_assert_werr_ok(tctx, r.out.result,
3350 "DeletePrinterKey failed");
3355 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
3356 struct dcerpc_pipe *p,
3357 struct policy_handle *handle)
3359 struct winreg_OpenHKLM r;
3361 r.in.system_name = NULL;
3362 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3363 r.out.handle = handle;
3365 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
3367 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM(p, tctx, &r), "OpenHKLM failed");
3368 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
3373 static void init_winreg_String(struct winreg_String *name, const char *s)
3377 name->name_len = 2 * (strlen_m(s) + 1);
3378 name->name_size = name->name_len;
3381 name->name_size = 0;
3385 static bool test_winreg_OpenKey(struct torture_context *tctx,
3386 struct dcerpc_pipe *p,
3387 struct policy_handle *hive_handle,
3388 const char *keyname,
3389 struct policy_handle *key_handle)
3391 struct winreg_OpenKey r;
3393 r.in.parent_handle = hive_handle;
3394 init_winreg_String(&r.in.keyname, keyname);
3395 r.in.options = REG_KEYTYPE_NON_VOLATILE;
3396 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3397 r.out.handle = key_handle;
3399 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
3401 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey(p, tctx, &r), "OpenKey failed");
3402 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
3407 static bool test_winreg_CloseKey(struct torture_context *tctx,
3408 struct dcerpc_pipe *p,
3409 struct policy_handle *handle)
3411 struct winreg_CloseKey r;
3413 r.in.handle = handle;
3414 r.out.handle = handle;
3416 torture_comment(tctx, "Testing winreg_CloseKey\n");
3418 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey(p, tctx, &r), "CloseKey failed");
3419 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
3424 bool test_winreg_QueryValue(struct torture_context *tctx,
3425 struct dcerpc_pipe *p,
3426 struct policy_handle *handle,
3427 const char *value_name,
3428 enum winreg_Type *type_p,
3429 uint32_t *data_size_p,
3430 uint32_t *data_length_p,
3433 struct winreg_QueryValue r;
3434 enum winreg_Type type = REG_NONE;
3435 uint32_t data_size = 0;
3436 uint32_t data_length = 0;
3437 struct winreg_String valuename;
3438 uint8_t *data = NULL;
3440 init_winreg_String(&valuename, value_name);
3442 data = talloc_zero_array(tctx, uint8_t, 0);
3444 r.in.handle = handle;
3445 r.in.value_name = &valuename;
3447 r.in.data_size = &data_size;
3448 r.in.data_length = &data_length;
3452 r.out.data_size = &data_size;
3453 r.out.data_length = &data_length;
3455 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
3457 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue(p, tctx, &r), "QueryValue failed");
3458 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3459 *r.in.data_size = *r.out.data_size;
3460 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
3463 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue(p, tctx, &r), "QueryValue failed");
3465 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
3468 *type_p = *r.out.type;
3471 *data_size_p = *r.out.data_size;
3473 if (data_length_p) {
3474 *data_length_p = *r.out.data_length;
3477 *data_p = r.out.data;
3483 static bool test_winreg_query_printerdata(struct torture_context *tctx,
3484 struct dcerpc_pipe *p,
3485 struct policy_handle *handle,
3486 const char *printer_name,
3487 const char *key_name,
3488 const char *value_name,
3489 enum winreg_Type *w_type,
3494 const char *printer_key;
3495 struct policy_handle key_handle;
3497 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
3498 TOP_LEVEL_PRINTER_KEY, printer_name, key_name);
3500 torture_assert(tctx,
3501 test_winreg_OpenKey(tctx, p, handle, printer_key, &key_handle), "");
3503 torture_assert(tctx,
3504 test_winreg_QueryValue(tctx, p, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
3506 torture_assert(tctx,
3507 test_winreg_CloseKey(tctx, p, &key_handle), "");
3512 static bool test_SetPrinterData(struct torture_context *tctx,
3513 struct dcerpc_pipe *p,
3514 struct policy_handle *handle,
3515 const char *value_name,
3516 enum winreg_Type type,
3520 struct spoolss_SetPrinterData r;
3522 r.in.handle = handle;
3523 r.in.value_name = value_name;
3526 r.in.offered = offered;
3528 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
3531 torture_assert_ntstatus_ok(tctx,
3532 dcerpc_spoolss_SetPrinterData(p, tctx, &r),
3533 "SetPrinterData failed");
3534 torture_assert_werr_ok(tctx, r.out.result,
3535 "SetPrinterData failed");
3540 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
3541 struct dcerpc_pipe *p,
3542 struct policy_handle *handle,
3543 const char *printer_name,
3544 struct dcerpc_pipe *winreg_pipe,
3545 struct policy_handle *hive_handle)
3547 const char *values[] = {
3551 /* FIXME: not working with s3 atm. */
3557 /* FIXME: not working with s3 atm. */
3564 for (i=0; i < ARRAY_SIZE(values); i++) {
3566 enum winreg_Type type;
3571 torture_assert(tctx,
3572 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3573 "REG_SZ", "dog", &type, &blob), "");
3575 torture_assert(tctx,
3576 test_SetPrinterData(tctx, p, handle, values[i], REG_SZ, blob.data, blob.length),
3577 "SetPrinterData failed");
3579 torture_assert(tctx,
3580 test_GetPrinterData(tctx, p, handle, values[i], &type, &data, &needed),
3581 "GetPrinterData failed");
3583 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
3584 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
3585 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
3587 if (winreg_pipe && hive_handle) {
3589 enum winreg_Type w_type;
3594 torture_assert(tctx,
3595 test_winreg_query_printerdata(tctx, winreg_pipe, hive_handle,
3596 printer_name, "PrinterDriverData", values[i],
3597 &w_type, &w_size, &w_length, &w_data), "");
3599 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
3600 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
3601 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
3602 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
3605 torture_assert(tctx,
3606 test_DeletePrinterData(tctx, p, handle, values[i]),
3607 "DeletePrinterData failed");
3614 static bool test_EnumPrinterKey(struct torture_context *tctx,
3615 struct dcerpc_pipe *p,
3616 struct policy_handle *handle,
3617 const char *key_name,
3618 const char ***array);
3620 static bool test_SetPrinterDataEx(struct torture_context *tctx,
3621 struct dcerpc_pipe *p,
3622 struct policy_handle *handle,
3623 const char *key_name,
3624 const char *value_name,
3625 enum winreg_Type type,
3630 struct spoolss_SetPrinterDataEx r;
3632 r.in.handle = handle;
3633 r.in.key_name = key_name;
3634 r.in.value_name = value_name;
3637 r.in.offered = offered;
3639 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
3640 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
3642 status = dcerpc_spoolss_SetPrinterDataEx(p, tctx, &r);
3644 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
3645 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
3650 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
3651 struct dcerpc_pipe *p,
3652 struct policy_handle *handle,
3653 const char *printername,
3654 struct dcerpc_pipe *winreg_pipe,
3655 struct policy_handle *hive_handle)
3657 const char *value_name = "dog";
3658 const char *keys[] = {
3662 /* FIXME: not working with s3 atm. */
3663 "torturedataex_with_subkey\\subkey",
3664 "torturedataex_with_subkey\\subkey:0",
3665 "torturedataex_with_subkey\\subkey:1",
3666 "torturedataex_with_subkey\\subkey\\subsubkey",
3667 "torturedataex_with_subkey\\subkey\\subsubkey:0",
3668 "torturedataex_with_subkey\\subkey\\subsubkey:1",
3672 /* FIXME: not working with s3 atm. */
3679 enum winreg_Type types[] = {
3684 const char *str = "abcdefghijklmnopqrstuvwxzy";
3688 for (i=0; i < ARRAY_SIZE(keys); i++) {
3689 for (t=0; t < ARRAY_SIZE(types); t++) {
3690 for (s=0; s < strlen(str); s++) {
3694 enum winreg_Type type;
3695 const char *string = talloc_strndup(tctx, str, s);
3696 DATA_BLOB blob = data_blob_string_const(string);
3697 const char **subkeys;
3700 uint32_t needed, offered = 0;
3702 struct spoolss_PrinterEnumValues *einfo;
3708 offered = blob.length;
3711 torture_assert(tctx,
3712 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3713 "REG_SZ", string, &type, &data), "");
3714 offered = data.length;
3715 /*strlen_m_term(data.string)*2;*/
3718 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
3721 torture_assert(tctx,
3722 test_SetPrinterDataEx(tctx, p, handle, keys[i], value_name, types[t], data.data, offered),
3723 "failed to call SetPrinterDataEx");
3725 torture_assert(tctx,
3726 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &data_out, &needed),
3727 "failed to call GetPrinterDataEx");
3729 torture_assert(tctx,
3730 test_EnumPrinterDataEx(tctx, p, handle, keys[i], &ecount, &einfo),
3731 "failed to call EnumPrinterDataEx");
3733 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
3734 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
3735 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
3737 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
3738 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
3739 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
3740 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
3741 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
3742 if (einfo[0].data_length > 0) {
3743 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
3746 if (winreg_pipe && hive_handle) {
3748 enum winreg_Type w_type;
3753 torture_assert(tctx,
3754 test_winreg_query_printerdata(tctx, winreg_pipe, hive_handle,
3755 printername, keys[i], value_name,
3756 &w_type, &w_size, &w_length, &w_data), "");
3758 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
3759 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
3760 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
3761 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
3764 key = talloc_strdup(tctx, keys[i]);
3766 if (!test_DeletePrinterDataEx(tctx, p, handle, keys[i], value_name)) {
3770 c = strchr(key, '\\');
3774 /* we have subkeys */
3778 if (!test_EnumPrinterKey(tctx, p, handle, key, &subkeys)) {
3782 for (k=0; subkeys && subkeys[k]; k++) {
3784 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
3786 if (!test_DeletePrinterKey(tctx, p, handle, current_key)) {
3791 if (!test_DeletePrinterKey(tctx, p, handle, key)) {
3796 if (!test_DeletePrinterKey(tctx, p, handle, key)) {
3807 static bool test_PrinterData_winreg(struct torture_context *tctx,
3808 struct dcerpc_pipe *p,
3809 struct policy_handle *handle,
3810 const char *printer_name)
3812 struct dcerpc_pipe *p2;
3814 struct policy_handle hive_handle;
3816 torture_assert_ntstatus_ok(tctx,
3817 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
3818 "could not open winreg pipe");
3820 torture_assert(tctx, test_winreg_OpenHKLM(tctx, p2, &hive_handle), "");
3822 ret &= test_SetPrinterData_matrix(tctx, p, handle, printer_name, p2, &hive_handle);
3823 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, p2, &hive_handle);
3825 test_winreg_CloseKey(tctx, p2, &hive_handle);
3832 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
3833 struct dcerpc_pipe *p,
3834 struct policy_handle *handle,
3835 uint32_t *change_id)
3837 enum winreg_Type type;
3841 torture_assert(tctx,
3842 test_GetPrinterData(tctx, p, handle, "ChangeID", &type, &data, &needed),
3843 "failed to call GetPrinterData");
3845 torture_assert(tctx, type == REG_DWORD, "unexpected type");
3846 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
3848 *change_id = IVAL(data, 0);
3853 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
3854 struct dcerpc_pipe *p,
3855 struct policy_handle *handle,
3856 uint32_t *change_id)
3858 enum winreg_Type type;
3862 torture_assert(tctx,
3863 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
3864 "failed to call GetPrinterData");
3866 torture_assert(tctx, type == REG_DWORD, "unexpected type");
3867 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
3869 *change_id = IVAL(data, 0);
3874 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
3875 struct dcerpc_pipe *p,
3876 struct policy_handle *handle,
3877 uint32_t *change_id)
3879 union spoolss_PrinterInfo info;
3881 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 0, &info),
3882 "failed to query Printer level 0");
3884 *change_id = info.info0.change_id;
3889 static bool test_ChangeID(struct torture_context *tctx,
3890 struct dcerpc_pipe *p,
3891 struct policy_handle *handle)
3893 uint32_t change_id, change_id_ex, change_id_info;
3894 uint32_t change_id2, change_id_ex2, change_id_info2;
3895 union spoolss_PrinterInfo info;
3896 const char *comment;
3899 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
3901 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3902 "failed to query for ChangeID");
3903 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3904 "failed to query for ChangeID");
3905 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3906 "failed to query for ChangeID");
3908 torture_assert_int_equal(tctx, change_id, change_id_ex,
3909 "change_ids should all be equal");
3910 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
3911 "change_ids should all be equal");
3914 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
3916 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3917 "failed to query for ChangeID");
3918 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
3919 "failed to query Printer level 2");
3920 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3921 "failed to query for ChangeID");
3922 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3923 "failed to query for ChangeID");
3924 torture_assert_int_equal(tctx, change_id, change_id_ex,
3925 "change_id should not have changed");
3926 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
3927 "change_id should not have changed");
3930 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
3932 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id),
3933 "failed to query for ChangeID");
3934 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
3935 "failed to query for ChangeID");
3936 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info),
3937 "failed to query for ChangeID");
3938 torture_assert(tctx, test_GetPrinter_level(tctx, p, handle, 2, &info),
3939 "failed to query Printer level 2");
3940 comment = talloc_strdup(tctx, info.info2.comment);
3943 struct spoolss_SetPrinterInfoCtr info_ctr;
3944 struct spoolss_DevmodeContainer devmode_ctr;
3945 struct sec_desc_buf secdesc_ctr;
3946 union spoolss_SetPrinterInfo sinfo;
3948 ZERO_STRUCT(info_ctr);
3949 ZERO_STRUCT(devmode_ctr);
3950 ZERO_STRUCT(secdesc_ctr);
3953 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
3954 sinfo.info2->comment = "torture_comment";
3957 info_ctr.info = sinfo;
3959 torture_assert(tctx, test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
3960 "failed to call SetPrinter");
3962 sinfo.info2->comment = comment;
3964 torture_assert(tctx, test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
3965 "failed to call SetPrinter");
3969 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, p, handle, &change_id2),
3970 "failed to query for ChangeID");
3971 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
3972 "failed to query for ChangeID");
3973 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, p, handle, &change_id_info2),
3974 "failed to query for ChangeID");
3976 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
3977 "change_ids should all be equal");
3978 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
3979 "change_ids should all be equal");
3981 torture_assert(tctx, (change_id < change_id2),
3982 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3983 change_id2, change_id));
3984 torture_assert(tctx, (change_id_ex < change_id_ex2),
3985 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3986 change_id_ex2, change_id_ex));
3987 torture_assert(tctx, (change_id_info < change_id_info2),
3988 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
3989 change_id_info2, change_id_info));
3991 torture_comment(tctx, "ChangeID tests succeeded\n\n");
3996 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
3997 struct dcerpc_pipe *p,
3998 struct policy_handle *handle)
4001 struct dcerpc_binding *b;
4002 struct dcerpc_pipe *p2;
4003 struct spoolss_ClosePrinter cp;
4005 /* only makes sense on SMB */
4006 if (p->conn->transport.transport != NCACN_NP) {
4010 torture_comment(tctx, "testing close on secondary pipe\n");
4012 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
4013 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
4015 status = dcerpc_secondary_connection(p, &p2, b);
4016 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
4018 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
4019 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
4021 cp.in.handle = handle;
4022 cp.out.handle = handle;
4024 status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
4025 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
4026 "ERROR: Allowed close on secondary connection");
4028 torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
4029 "Unexpected fault code");
4036 static bool test_OpenPrinter_badname(struct torture_context *tctx,
4037 struct dcerpc_pipe *p, const char *name)
4040 struct spoolss_OpenPrinter op;
4041 struct spoolss_OpenPrinterEx opEx;
4042 struct policy_handle handle;
4045 op.in.printername = name;
4046 op.in.datatype = NULL;
4047 op.in.devmode_ctr.devmode= NULL;
4048 op.in.access_mask = 0;
4049 op.out.handle = &handle;
4051 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
4053 status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
4054 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
4055 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
4056 "unexpected result");
4058 if (W_ERROR_IS_OK(op.out.result)) {
4059 ret &=test_ClosePrinter(tctx, p, &handle);
4062 opEx.in.printername = name;
4063 opEx.in.datatype = NULL;
4064 opEx.in.devmode_ctr.devmode = NULL;
4065 opEx.in.access_mask = 0;
4067 opEx.in.userlevel.level1 = NULL;
4068 opEx.out.handle = &handle;
4070 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
4072 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
4073 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
4074 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
4075 "unexpected result");
4077 if (W_ERROR_IS_OK(opEx.out.result)) {
4078 ret &=test_ClosePrinter(tctx, p, &handle);
4084 static bool test_OpenPrinter(struct torture_context *tctx,
4085 struct dcerpc_pipe *p,
4087 const char *environment)
4090 struct spoolss_OpenPrinter r;
4091 struct policy_handle handle;
4094 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
4095 r.in.datatype = NULL;
4096 r.in.devmode_ctr.devmode= NULL;
4097 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4098 r.out.handle = &handle;
4100 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
4102 status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
4104 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
4106 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
4108 if (!test_GetPrinter(tctx, p, &handle, environment)) {
4112 if (!torture_setting_bool(tctx, "samba3", false)) {
4113 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
4118 if (!test_ClosePrinter(tctx, p, &handle)) {
4125 static bool call_OpenPrinterEx(struct torture_context *tctx,
4126 struct dcerpc_pipe *p,
4128 struct spoolss_DeviceMode *devmode,
4129 struct policy_handle *handle)
4131 struct spoolss_OpenPrinterEx r;
4132 struct spoolss_UserLevel1 userlevel1;
4135 if (name && name[0]) {
4136 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
4137 dcerpc_server_name(p), name);
4139 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
4140 dcerpc_server_name(p));
4143 r.in.datatype = NULL;
4144 r.in.devmode_ctr.devmode= devmode;
4145 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4147 r.in.userlevel.level1 = &userlevel1;
4148 r.out.handle = handle;
4150 userlevel1.size = 1234;
4151 userlevel1.client = "hello";
4152 userlevel1.user = "spottyfoot!";
4153 userlevel1.build = 1;
4154 userlevel1.major = 2;
4155 userlevel1.minor = 3;
4156 userlevel1.processor = 4;
4158 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
4160 status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
4162 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
4164 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
4169 static bool test_printer_rename(struct torture_context *tctx,
4170 struct dcerpc_pipe *p,
4171 struct policy_handle *handle,
4175 union spoolss_PrinterInfo info;
4176 union spoolss_SetPrinterInfo sinfo;
4177 struct spoolss_SetPrinterInfoCtr info_ctr;
4178 struct spoolss_DevmodeContainer devmode_ctr;
4179 struct sec_desc_buf secdesc_ctr;
4180 const char *printer_name;
4181 const char *printer_name_orig;
4182 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
4183 struct policy_handle new_handle;
4186 ZERO_STRUCT(devmode_ctr);
4187 ZERO_STRUCT(secdesc_ctr);
4189 torture_comment(tctx, "Testing Printer rename operations\n");
4191 torture_assert(tctx,
4192 test_GetPrinter_level(tctx, p, handle, 2, &info),
4193 "failed to call GetPrinter level 2");
4195 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
4197 q = strrchr(info.info2.printername, '\\');
4199 torture_warning(tctx,
4200 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
4203 torture_assert(tctx,
4204 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
4206 sinfo.info2->printername = printer_name_new;
4209 info_ctr.info = sinfo;
4211 torture_assert(tctx,
4212 test_SetPrinter(tctx, p, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
4213 "failed to call SetPrinter level 2");
4215 torture_assert(tctx,
4216 test_GetPrinter_level(tctx, p, handle, 2, &info),
4217 "failed to call GetPrinter level 2");
4219 printer_name = talloc_strdup(tctx, info.info2.printername);
4221 q = strrchr(info.info2.printername, '\\');
4223 torture_warning(tctx,
4224 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
4229 torture_assert_str_equal(tctx, printer_name, printer_name_new,
4230 "new printer name was not set");
4232 torture_assert(tctx,
4233 test_OpenPrinter_badname(tctx, p, printer_name_orig),
4234 "still can open printer with oldname");
4236 torture_assert(tctx,
4237 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
4238 "failed to open printer with new name");
4240 torture_assert(tctx,
4241 test_GetPrinter_level(tctx, p, &new_handle, 2, &info),
4242 "failed to call GetPrinter level 2");
4244 /* FIXME: we openend with servername! */
4245 printer_name = talloc_asprintf(tctx, "\\\\%s\\%s",
4246 dcerpc_server_name(p), printer_name_new);
4248 torture_assert_str_equal(tctx, info.info2.printername, printer_name,
4249 "new printer name was not set");
4251 torture_assert(tctx,
4252 test_ClosePrinter(tctx, p, &new_handle),
4253 "failed to close printer");
4255 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
4261 static bool test_OpenPrinterEx(struct torture_context *tctx,
4262 struct dcerpc_pipe *p,
4264 const char *environment)
4266 struct policy_handle handle;
4269 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
4273 if (!test_PrinterInfo_SD(tctx, p, &handle)) {
4277 if (!test_GetPrinter(tctx, p, &handle, environment)) {
4281 if (!test_EnumForms(tctx, p, &handle, false)) {
4285 if (!test_AddForm(tctx, p, &handle, false)) {
4289 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
4293 if (!test_EnumPrinterDataEx(tctx, p, &handle, "PrinterDriverData", NULL, NULL)) {
4297 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
4301 if (!test_printer_keys(tctx, p, &handle)) {
4305 if (!test_PausePrinter(tctx, p, &handle)) {
4309 if (!test_DoPrintTest(tctx, p, &handle)) {
4313 if (!test_ResumePrinter(tctx, p, &handle)) {
4317 if (!test_SetPrinterData_matrix(tctx, p, &handle, name, NULL, NULL)) {
4321 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
4325 if (!torture_setting_bool(tctx, "samba3", false)) {
4326 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
4331 if (!test_ClosePrinter(tctx, p, &handle)) {
4338 static bool test_EnumPrinters_old(struct torture_context *tctx,
4339 struct dcerpc_pipe *p,
4340 const char *environment)
4342 struct spoolss_EnumPrinters r;
4344 uint16_t levels[] = {1, 2, 4, 5};
4348 for (i=0;i<ARRAY_SIZE(levels);i++) {
4349 union spoolss_PrinterInfo *info;
4354 r.in.flags = PRINTER_ENUM_LOCAL;
4356 r.in.level = levels[i];
4359 r.out.needed = &needed;
4360 r.out.count = &count;
4363 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
4365 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
4366 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
4368 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4369 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4370 data_blob_clear(&blob);
4371 r.in.buffer = &blob;
4372 r.in.offered = needed;
4373 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
4376 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
4378 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
4380 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4383 torture_comment(tctx, "No printers returned\n");
4387 for (j=0;j<count;j++) {
4388 if (r.in.level == 1) {
4389 char *unc = talloc_strdup(tctx, info[j].info1.name);
4392 if (unc[0] == '\\' && unc[1] == '\\') {
4395 slash = strchr(unc, '\\');
4400 if (!test_OpenPrinter(tctx, p, name, environment)) {
4403 if (!test_OpenPrinterEx(tctx, p, name, environment)) {
4413 static bool test_GetPrinterDriver(struct torture_context *tctx,
4414 struct dcerpc_pipe *p,
4415 struct policy_handle *handle,
4416 const char *driver_name)
4418 struct spoolss_GetPrinterDriver r;
4421 r.in.handle = handle;
4422 r.in.architecture = "W32X86";
4426 r.out.needed = &needed;
4428 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
4430 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
4431 "failed to call GetPrinterDriver");
4432 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4433 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4434 data_blob_clear(&blob);
4435 r.in.buffer = &blob;
4436 r.in.offered = needed;
4437 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
4438 "failed to call GetPrinterDriver");
4441 torture_assert_werr_ok(tctx, r.out.result,
4442 "failed to call GetPrinterDriver");
4444 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4449 static bool test_GetPrinterDriver2(struct torture_context *tctx,
4450 struct dcerpc_pipe *p,
4451 struct policy_handle *handle,
4452 const char *driver_name,
4453 const char *architecture)
4455 struct spoolss_GetPrinterDriver2 r;
4456 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
4458 uint32_t server_major_version;
4459 uint32_t server_minor_version;
4462 r.in.handle = handle;
4463 r.in.architecture = architecture;
4464 r.in.client_major_version = 3;
4465 r.in.client_minor_version = 0;
4466 r.out.needed = &needed;
4467 r.out.server_major_version = &server_major_version;
4468 r.out.server_minor_version = &server_minor_version;
4470 for (i=0;i<ARRAY_SIZE(levels);i++) {
4474 r.in.level = levels[i];
4476 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
4477 driver_name, r.in.level);
4479 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
4480 "failed to call GetPrinterDriver2");
4481 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4482 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4483 data_blob_clear(&blob);
4484 r.in.buffer = &blob;
4485 r.in.offered = needed;
4486 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
4487 "failed to call GetPrinterDriver2");
4490 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
4491 switch (r.in.level) {
4500 torture_assert_werr_ok(tctx, r.out.result,
4501 "failed to call GetPrinterDriver2");
4503 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4509 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
4510 struct dcerpc_pipe *p,
4511 const char *environment)
4513 struct spoolss_EnumPrinterDrivers r;
4515 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
4518 for (i=0;i<ARRAY_SIZE(levels);i++) {
4522 union spoolss_DriverInfo *info;
4524 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
4525 r.in.environment = environment;
4526 r.in.level = levels[i];
4529 r.out.needed = &needed;
4530 r.out.count = &count;
4533 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
4535 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
4537 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
4539 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4540 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4541 data_blob_clear(&blob);
4542 r.in.buffer = &blob;
4543 r.in.offered = needed;
4544 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
4547 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
4549 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
4552 torture_comment(tctx, "No printer drivers returned\n");
4556 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4562 static bool test_DeletePrinter(struct torture_context *tctx,
4563 struct dcerpc_pipe *p,
4564 struct policy_handle *handle)
4566 struct spoolss_DeletePrinter r;
4568 torture_comment(tctx, "Testing DeletePrinter\n");
4570 r.in.handle = handle;
4572 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter(p, tctx, &r),
4573 "failed to delete printer");
4574 torture_assert_werr_ok(tctx, r.out.result,
4575 "failed to delete printer");
4580 static bool test_EnumPrinters_findname(struct torture_context *tctx,
4581 struct dcerpc_pipe *p,
4587 struct spoolss_EnumPrinters e;
4589 union spoolss_PrinterInfo *info;
4600 e.out.count = &count;
4602 e.out.needed = &needed;
4604 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
4605 "failed to enum printers");
4607 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
4608 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4609 data_blob_clear(&blob);
4610 e.in.buffer = &blob;
4611 e.in.offered = needed;
4613 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
4614 "failed to enum printers");
4617 torture_assert_werr_ok(tctx, e.out.result,
4618 "failed to enum printers");
4620 for (i=0; i < count; i++) {
4622 const char *current = NULL;
4627 current = info[i].info1.name;
4631 if (strequal(current, name)) {
4636 q = strrchr(current, '\\');
4639 torture_warning(tctx,
4640 "server returns printername %s incl. servername although we did not set servername", current);
4643 if (strequal(q, name)) {
4653 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
4654 struct dcerpc_pipe *p,
4655 const char *printername,
4659 struct spoolss_AddPrinter r;
4660 struct spoolss_AddPrinterEx rex;
4661 struct spoolss_SetPrinterInfoCtr info_ctr;
4662 struct spoolss_SetPrinterInfo1 info1;
4663 struct spoolss_DevmodeContainer devmode_ctr;
4664 struct sec_desc_buf secdesc_ctr;
4665 struct spoolss_UserLevelCtr userlevel_ctr;
4666 struct policy_handle handle;
4669 ZERO_STRUCT(devmode_ctr);
4670 ZERO_STRUCT(secdesc_ctr);
4671 ZERO_STRUCT(userlevel_ctr);
4674 torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
4676 /* try to add printer to wellknown printer list (level 1) */
4678 userlevel_ctr.level = 1;
4680 info_ctr.info.info1 = &info1;
4683 rex.in.server = NULL;
4684 rex.in.info_ctr = &info_ctr;
4685 rex.in.devmode_ctr = &devmode_ctr;
4686 rex.in.secdesc_ctr = &secdesc_ctr;
4687 rex.in.userlevel_ctr = &userlevel_ctr;
4688 rex.out.handle = &handle;
4691 r.in.info_ctr = &info_ctr;
4692 r.in.devmode_ctr = &devmode_ctr;
4693 r.in.secdesc_ctr = &secdesc_ctr;
4694 r.out.handle = &handle;
4696 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4697 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4698 "failed to add printer");
4699 result = ex ? rex.out.result : r.out.result;
4700 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
4701 "unexpected result code");
4703 info1.name = printername;
4704 info1.flags = PRINTER_ATTRIBUTE_SHARED;
4706 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4707 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4708 "failed to add printer");
4709 result = ex ? rex.out.result : r.out.result;
4710 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4711 "unexpected result code");
4713 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
4714 better do a real check to see the printer is really there */
4716 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4717 PRINTER_ENUM_NETWORK, 1,
4720 "failed to enum printers");
4722 torture_assert(tctx, found, "failed to find newly added printer");
4726 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4727 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4728 "failed to add printer");
4729 result = ex ? rex.out.result : r.out.result;
4730 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4731 "unexpected result code");
4733 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
4734 better do a real check to see the printer has really been removed
4735 from the well known printer list */
4739 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4740 PRINTER_ENUM_NETWORK, 1,
4743 "failed to enum printers");
4745 torture_assert(tctx, !found, "printer still in well known printer list");
4750 static bool test_AddPrinter_normal(struct torture_context *tctx,
4751 struct dcerpc_pipe *p,
4752 struct policy_handle *handle_p,
4753 const char *printername,
4754 const char *drivername,
4755 const char *portname,
4759 struct spoolss_AddPrinter r;
4760 struct spoolss_AddPrinterEx rex;
4761 struct spoolss_SetPrinterInfoCtr info_ctr;
4762 struct spoolss_SetPrinterInfo2 info2;
4763 struct spoolss_DevmodeContainer devmode_ctr;
4764 struct sec_desc_buf secdesc_ctr;
4765 struct spoolss_UserLevelCtr userlevel_ctr;
4766 struct policy_handle handle;
4768 bool existing_printer_deleted = false;
4770 ZERO_STRUCT(devmode_ctr);
4771 ZERO_STRUCT(secdesc_ctr);
4772 ZERO_STRUCT(userlevel_ctr);
4774 torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
4776 userlevel_ctr.level = 1;
4778 rex.in.server = NULL;
4779 rex.in.info_ctr = &info_ctr;
4780 rex.in.devmode_ctr = &devmode_ctr;
4781 rex.in.secdesc_ctr = &secdesc_ctr;
4782 rex.in.userlevel_ctr = &userlevel_ctr;
4783 rex.out.handle = &handle;
4786 r.in.info_ctr = &info_ctr;
4787 r.in.devmode_ctr = &devmode_ctr;
4788 r.in.secdesc_ctr = &secdesc_ctr;
4789 r.out.handle = &handle;
4793 /* try to add printer to printer list (level 2) */
4797 info_ctr.info.info2 = &info2;
4800 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4801 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4802 "failed to add printer");
4803 result = ex ? rex.out.result : r.out.result;
4804 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
4805 "unexpected result code");
4807 info2.printername = printername;
4809 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4810 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4811 "failed to add printer");
4812 result = ex ? rex.out.result : r.out.result;
4814 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
4815 struct policy_handle printer_handle;
4817 if (existing_printer_deleted) {
4818 torture_fail(tctx, "already deleted printer still existing?");
4821 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
4822 "failed to open printer handle");
4824 torture_assert(tctx, test_DeletePrinter(tctx, p, &printer_handle),
4825 "failed to delete printer");
4827 torture_assert(tctx, test_ClosePrinter(tctx, p, &printer_handle),
4828 "failed to close server handle");
4830 existing_printer_deleted = true;
4835 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
4836 "unexpected result code");
4838 info2.portname = portname;
4840 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4841 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4842 "failed to add printer");
4843 result = ex ? rex.out.result : r.out.result;
4844 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
4845 "unexpected result code");
4847 info2.drivername = drivername;
4849 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4850 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4851 "failed to add printer");
4852 result = ex ? rex.out.result : r.out.result;
4854 /* w2k8r2 allows to add printer w/o defining printprocessor */
4856 if (!W_ERROR_IS_OK(result)) {
4857 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
4858 "unexpected result code");
4860 info2.printprocessor = "winprint";
4862 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4863 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4864 "failed to add printer");
4865 result = ex ? rex.out.result : r.out.result;
4866 torture_assert_werr_ok(tctx, result,
4867 "failed to add printer");
4872 /* we are paranoid, really check if the printer is there now */
4874 torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
4875 PRINTER_ENUM_LOCAL, 1,
4878 "failed to enum printers");
4879 torture_assert(tctx, found, "failed to find newly added printer");
4881 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
4882 dcerpc_spoolss_AddPrinter(p, tctx, &r),
4883 "failed to add printer");
4884 result = ex ? rex.out.result : r.out.result;
4885 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
4886 "unexpected result code");
4891 static bool test_AddPrinterEx(struct torture_context *tctx,
4892 struct dcerpc_pipe *p,
4893 struct policy_handle *handle_p,
4894 const char *printername,
4895 const char *drivername,
4896 const char *portname)
4900 if (!torture_setting_bool(tctx, "samba3", false)) {
4901 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
4902 torture_comment(tctx, "failed to add printer to well known list\n");
4907 if (!test_AddPrinter_normal(tctx, p, handle_p,
4908 printername, drivername, portname,
4910 torture_comment(tctx, "failed to add printer to printer list\n");
4917 static bool test_AddPrinter(struct torture_context *tctx,
4918 struct dcerpc_pipe *p,
4919 struct policy_handle *handle_p,
4920 const char *printername,
4921 const char *drivername,
4922 const char *portname)
4926 if (!torture_setting_bool(tctx, "samba3", false)) {
4927 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
4928 torture_comment(tctx, "failed to add printer to well known list\n");
4933 if (!test_AddPrinter_normal(tctx, p, handle_p,
4934 printername, drivername, portname,
4936 torture_comment(tctx, "failed to add printer to printer list\n");
4943 static bool test_printer_info(struct torture_context *tctx,
4944 struct dcerpc_pipe *p,
4945 struct policy_handle *handle)
4949 if (torture_setting_bool(tctx, "samba3", false)) {
4950 torture_skip(tctx, "skipping printer info cross tests against samba 3");
4953 if (!test_PrinterInfo(tctx, p, handle)) {
4957 if (!test_SetPrinter_errors(tctx, p, handle)) {
4964 static bool test_EnumPrinterKey(struct torture_context *tctx,
4965 struct dcerpc_pipe *p,
4966 struct policy_handle *handle,
4967 const char *key_name,
4968 const char ***array)
4970 struct spoolss_EnumPrinterKey r;
4971 uint32_t needed = 0;
4972 union spoolss_KeyNames key_buffer;
4973 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
4977 r.in.handle = handle;
4978 r.in.key_name = key_name;
4979 r.out.key_buffer = &key_buffer;
4980 r.out.needed = &needed;
4981 r.out._ndr_size = &_ndr_size;
4983 for (i=0; i < ARRAY_SIZE(offered); i++) {
4985 if (offered[i] < 0 && needed) {
4989 r.in.offered = needed + offered[i];
4991 r.in.offered = offered[i];
4994 ZERO_STRUCT(key_buffer);
4996 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
4998 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
4999 "failed to call EnumPrinterKey");
5000 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
5002 torture_assert(tctx, (_ndr_size == r.in.offered/2),
5003 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
5004 _ndr_size, r.in.offered/2));
5006 r.in.offered = needed;
5007 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
5008 "failed to call EnumPrinterKey");
5011 if (offered[i] > 0) {
5012 torture_assert_werr_ok(tctx, r.out.result,
5013 "failed to call EnumPrinterKey");
5016 torture_assert(tctx, (_ndr_size == r.in.offered/2),
5017 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
5018 _ndr_size, r.in.offered/2));
5020 torture_assert(tctx, (*r.out.needed <= r.in.offered),
5021 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
5023 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
5024 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
5026 if (key_buffer.string_array) {
5027 uint32_t calc_needed = 0;
5029 for (s=0; key_buffer.string_array[s]; s++) {
5030 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
5032 if (!key_buffer.string_array[0]) {
5037 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
5038 "EnumPrinterKey unexpected size");
5043 *array = key_buffer.string_array;
5049 bool test_printer_keys(struct torture_context *tctx,
5050 struct dcerpc_pipe *p,
5051 struct policy_handle *handle)
5053 const char **key_array = NULL;
5056 torture_comment(tctx, "Testing Printer Keys\n");
5058 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, "", &key_array),
5059 "failed to call test_EnumPrinterKey");
5061 for (i=0; key_array && key_array[i]; i++) {
5062 torture_assert(tctx, test_EnumPrinterKey(tctx, p, handle, key_array[i], NULL),
5063 "failed to call test_EnumPrinterKey");
5065 for (i=0; key_array && key_array[i]; i++) {
5066 torture_assert(tctx, test_EnumPrinterDataEx(tctx, p, handle, key_array[i], NULL, NULL),
5067 "failed to call test_EnumPrinterDataEx");
5070 torture_comment(tctx, "Printer Keys test succeeded\n\n");
5075 static bool test_one_printer(struct torture_context *tctx,
5076 struct dcerpc_pipe *p,
5077 struct policy_handle *handle,
5082 if (!test_printer_info(tctx, p, handle)) {
5086 if (!test_PrinterInfo_SD(tctx, p, handle)) {
5090 if (!test_PrinterInfo_DevMode(tctx, p, handle, name)) {
5094 if (!test_ChangeID(tctx, p, handle)) {
5098 if (!test_printer_keys(tctx, p, handle)) {
5102 if (!test_EnumPrinterData_consistency(tctx, p, handle)) {
5106 if (!test_SetPrinterDataEx_matrix(tctx, p, handle, name, NULL, NULL)) {
5110 if (!test_PrinterData_winreg(tctx, p, handle, name)) {
5114 if (!test_printer_rename(tctx, p, handle, name)) {
5121 static bool test_printer(struct torture_context *tctx,
5122 struct dcerpc_pipe *p)
5125 struct policy_handle handle[2];
5127 const char *drivername = "Microsoft XPS Document Writer";
5128 const char *portname = "LPT1:";
5130 /* test printer created via AddPrinter */
5132 if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
5136 if (!test_one_printer(tctx, p, &handle[0], TORTURE_PRINTER)) {
5140 if (!test_DeletePrinter(tctx, p, &handle[0])) {
5144 if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
5145 TORTURE_PRINTER, &found)) {
5149 torture_assert(tctx, !found, "deleted printer still there");
5151 /* test printer created via AddPrinterEx */
5153 if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
5157 if (!test_one_printer(tctx, p, &handle[1], TORTURE_PRINTER_EX)) {
5161 if (!test_DeletePrinter(tctx, p, &handle[1])) {
5165 if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
5166 TORTURE_PRINTER_EX, &found)) {
5170 torture_assert(tctx, !found, "deleted printer still there");
5175 static bool test_architecture_buffer(struct torture_context *tctx,
5176 struct dcerpc_pipe *p)
5178 struct spoolss_OpenPrinterEx r;
5179 struct spoolss_UserLevel1 u1;
5180 struct policy_handle handle;
5181 uint32_t architectures[] = {
5182 PROCESSOR_ARCHITECTURE_INTEL,
5183 PROCESSOR_ARCHITECTURE_IA64,
5184 PROCESSOR_ARCHITECTURE_AMD64
5189 for (i=0; i < ARRAY_SIZE(architectures); i++) {
5191 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
5199 u1.processor = architectures[i];
5201 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
5202 r.in.datatype = NULL;
5203 r.in.devmode_ctr.devmode= NULL;
5204 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5206 r.in.userlevel.level1 = &u1;
5207 r.out.handle = &handle;
5209 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx(p, tctx, &r), "");
5210 torture_assert_werr_ok(tctx, r.out.result, "");
5213 struct spoolss_EnumPrinters e;
5215 union spoolss_PrinterInfo *info;
5217 e.in.flags = PRINTER_ENUM_LOCAL;
5222 e.out.count = &count;
5224 e.out.needed = &needed[i];
5226 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e), "");
5228 torture_comment(tctx, "needed was %d\n", needed[i]);
5232 torture_assert(tctx, test_ClosePrinter(tctx, p, &handle), "");
5235 for (i=1; i < ARRAY_SIZE(architectures); i++) {
5236 if (needed[i-1] != needed[i]) {
5238 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
5239 needed[i-1], architectures[i-1], needed[i], architectures[i]));
5246 bool torture_rpc_spoolss(struct torture_context *torture)
5249 struct dcerpc_pipe *p;
5251 struct test_spoolss_context *ctx;
5252 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
5254 status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
5255 if (!NT_STATUS_IS_OK(status)) {
5259 ctx = talloc_zero(torture, struct test_spoolss_context);
5261 ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
5262 ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle, &environment);
5263 ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
5264 ret &= test_AddForm(torture, p, &ctx->server_handle, true);
5265 ret &= test_EnumPorts(torture, p, ctx);
5266 ret &= test_GetPrinterDriverDirectory(torture, p, ctx, environment);
5267 ret &= test_GetPrintProcessorDirectory(torture, p, ctx, environment);
5268 ret &= test_EnumPrinterDrivers(torture, p, ctx, environment);
5269 ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
5270 ret &= test_EnumMonitors(torture, p, ctx);
5271 ret &= test_EnumPrintProcessors(torture, p, ctx, environment);
5272 ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
5273 ret &= test_EnumPrinters(torture, p, ctx);
5274 ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
5275 ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
5276 ret &= test_OpenPrinter_badname(torture, p, "");
5277 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
5278 ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
5279 ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
5280 ret &= test_OpenPrinter_badname(torture, p,
5281 talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
5284 ret &= test_AddPort(torture, p);
5285 ret &= test_EnumPorts_old(torture, p);
5286 ret &= test_EnumPrinters_old(torture, p, environment);
5287 ret &= test_EnumPrinterDrivers_old(torture, p, environment);
5288 ret &= test_architecture_buffer(torture, p);
5293 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
5295 struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
5297 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
5298 "printer", &ndr_table_spoolss);
5300 torture_rpc_tcase_add_test(tcase, "printer", test_printer);