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_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
42 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
43 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
44 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
46 struct test_spoolss_context {
47 /* print server handle */
48 struct policy_handle server_handle;
51 uint32_t port_count[3];
52 union spoolss_PortInfo *ports[3];
54 /* for EnumPrinterDrivers */
55 uint32_t driver_count[8];
56 union spoolss_DriverInfo *drivers[8];
58 /* for EnumMonitors */
59 uint32_t monitor_count[3];
60 union spoolss_MonitorInfo *monitors[3];
62 /* for EnumPrintProcessors */
63 uint32_t print_processor_count[2];
64 union spoolss_PrintProcessorInfo *print_processors[2];
66 /* for EnumPrinters */
67 uint32_t printer_count[6];
68 union spoolss_PrinterInfo *printers[6];
71 #define COMPARE_STRING(tctx, c,r,e) \
72 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
74 /* not every compiler supports __typeof__() */
76 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
77 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
78 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
80 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
81 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
85 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
88 #define COMPARE_UINT32(tctx, c, r, e) do {\
89 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
90 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
93 #define COMPARE_UINT64(tctx, c, r, e) do {\
94 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
95 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
99 #define COMPARE_NTTIME(tctx, c, r, e) do {\
100 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
101 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
104 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
106 if (!c.e && !r.e) { \
110 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
113 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
115 for (__i=0;c.e[__i] != NULL; __i++) { \
116 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
120 #define CHECK_ALIGN(size, n) do {\
122 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
123 size, n, size + n - (size % n));\
127 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
129 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, ic, needed, align) do { \
130 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
131 uint32_t size = ndr_size_##fn##_info(tctx, ic, level, count, info);\
132 uint32_t round_size = DO_ROUND(size, align);\
133 if (round_size != needed) {\
134 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
135 CHECK_ALIGN(size, align);\
140 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, ic, needed, align) do { \
141 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
142 uint32_t size = ndr_size_##fn##_info(tctx, ic, count, info);\
143 uint32_t round_size = DO_ROUND(size, align);\
144 if (round_size != needed) {\
145 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
146 CHECK_ALIGN(size, align);\
151 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, ic, needed, align) do { \
152 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
153 uint32_t size = ndr_size_##fn(info, level, ic, 0);\
154 uint32_t round_size = DO_ROUND(size, align);\
155 if (round_size != needed) {\
156 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
157 CHECK_ALIGN(size, align);\
162 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context *tctx,
163 const union spoolss_PrinterInfo *i,
165 union spoolss_SetPrinterInfo *s)
169 s->info0 = talloc(tctx, struct spoolss_SetPrinterInfo0);
172 s->info2 = talloc(tctx, struct spoolss_SetPrinterInfo2);
173 s->info2->servername = i->info2.servername;
174 s->info2->printername = i->info2.printername;
175 s->info2->sharename = i->info2.sharename;
176 s->info2->portname = i->info2.portname;
177 s->info2->drivername = i->info2.drivername;
178 s->info2->comment = i->info2.comment;
179 s->info2->location = i->info2.location;
180 s->info2->devmode_ptr = 0;
181 s->info2->sepfile = i->info2.sepfile;
182 s->info2->printprocessor = i->info2.printprocessor;
183 s->info2->datatype = i->info2.datatype;
184 s->info2->parameters = i->info2.parameters;
185 s->info2->secdesc_ptr = 0;
186 s->info2->attributes = i->info2.attributes;
187 s->info2->priority = i->info2.priority;
188 s->info2->defaultpriority = i->info2.defaultpriority;
189 s->info2->starttime = i->info2.starttime;
190 s->info2->untiltime = i->info2.untiltime;
191 s->info2->status = i->info2.status;
192 s->info2->cjobs = i->info2.cjobs;
193 s->info2->averageppm = i->info2.averageppm;
209 static bool test_OpenPrinter_server(struct torture_context *tctx,
210 struct dcerpc_pipe *p,
211 struct policy_handle *server_handle)
214 struct spoolss_OpenPrinter op;
215 struct dcerpc_binding_handle *b = p->binding_handle;
217 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
218 op.in.datatype = NULL;
219 op.in.devmode_ctr.devmode= NULL;
220 op.in.access_mask = 0;
221 op.out.handle = server_handle;
223 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
225 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
226 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
227 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
232 static bool test_EnumPorts(struct torture_context *tctx,
233 struct dcerpc_binding_handle *b,
234 struct test_spoolss_context *ctx)
237 struct spoolss_EnumPorts r;
238 uint16_t levels[] = { 1, 2 };
241 for (i=0;i<ARRAY_SIZE(levels);i++) {
242 int level = levels[i];
246 union spoolss_PortInfo *info;
248 r.in.servername = "";
252 r.out.needed = &needed;
253 r.out.count = &count;
256 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
258 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
259 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
260 if (W_ERROR_IS_OK(r.out.result)) {
261 /* TODO: do some more checks here */
264 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
265 "EnumPorts unexpected return code");
267 blob = data_blob_talloc(ctx, NULL, needed);
268 data_blob_clear(&blob);
270 r.in.offered = needed;
272 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
273 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
275 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
277 torture_assert(tctx, info, "EnumPorts returned no info");
279 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
281 ctx->port_count[level] = count;
282 ctx->ports[level] = info;
285 for (i=1;i<ARRAY_SIZE(levels);i++) {
286 int level = levels[i];
287 int old_level = levels[i-1];
288 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
289 "EnumPorts invalid value");
291 /* if the array sizes are not the same we would maybe segfault in the following code */
293 for (i=0;i<ARRAY_SIZE(levels);i++) {
294 int level = levels[i];
295 for (j=0;j<ctx->port_count[level];j++) {
296 union spoolss_PortInfo *cur = &ctx->ports[level][j];
297 union spoolss_PortInfo *ref = &ctx->ports[2][j];
300 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
303 /* level 2 is our reference, and it makes no sense to compare it to itself */
312 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
313 struct dcerpc_pipe *p,
314 struct test_spoolss_context *ctx,
315 const char *environment)
318 struct dcerpc_binding_handle *b = p->binding_handle;
319 struct spoolss_GetPrintProcessorDirectory r;
334 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
337 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
343 for (i=0;i<ARRAY_SIZE(levels);i++) {
344 int level = levels[i].level;
347 r.in.server = levels[i].server;
348 r.in.environment = environment;
352 r.out.needed = &needed;
354 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
356 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, ctx, &r);
357 torture_assert_ntstatus_ok(tctx, status,
358 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
359 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
360 "GetPrintProcessorDirectory unexpected return code");
362 blob = data_blob_talloc(ctx, NULL, needed);
363 data_blob_clear(&blob);
365 r.in.offered = needed;
367 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, ctx, &r);
368 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
370 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
372 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
379 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
380 struct dcerpc_pipe *p,
381 struct test_spoolss_context *ctx,
382 const char *environment)
385 struct dcerpc_binding_handle *b = p->binding_handle;
386 struct spoolss_GetPrinterDriverDirectory r;
401 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
404 .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
410 for (i=0;i<ARRAY_SIZE(levels);i++) {
411 int level = levels[i].level;
414 r.in.server = levels[i].server;
415 r.in.environment = environment;
419 r.out.needed = &needed;
421 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
423 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, ctx, &r);
424 torture_assert_ntstatus_ok(tctx, status,
425 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
426 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
427 "GetPrinterDriverDirectory unexpected return code");
429 blob = data_blob_talloc(ctx, NULL, needed);
430 data_blob_clear(&blob);
432 r.in.offered = needed;
434 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, ctx, &r);
435 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
437 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
439 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 2);
445 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
446 struct dcerpc_pipe *p,
447 struct test_spoolss_context *ctx,
448 const char *architecture)
451 struct dcerpc_binding_handle *b = p->binding_handle;
452 struct spoolss_EnumPrinterDrivers r;
453 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
456 for (i=0;i<ARRAY_SIZE(levels);i++) {
457 int level = levels[i];
461 union spoolss_DriverInfo *info;
463 /* FIXME: gd, come back and fix "" as server, and handle
464 * priority of returned error codes in torture test and samba 3
467 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
468 r.in.environment = architecture;
472 r.out.needed = &needed;
473 r.out.count = &count;
476 torture_comment(tctx, "Testing EnumPrinterDrivers level %u (%s)\n", r.in.level, r.in.environment);
478 status = dcerpc_spoolss_EnumPrinterDrivers_r(b, ctx, &r);
479 torture_assert_ntstatus_ok(tctx, status,
480 "dcerpc_spoolss_EnumPrinterDrivers failed");
481 if (W_ERROR_IS_OK(r.out.result)) {
482 /* TODO: do some more checks here */
485 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
486 blob = data_blob_talloc(ctx, NULL, needed);
487 data_blob_clear(&blob);
489 r.in.offered = needed;
491 status = dcerpc_spoolss_EnumPrinterDrivers_r(b, ctx, &r);
492 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
495 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
497 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
499 ctx->driver_count[level] = count;
500 ctx->drivers[level] = info;
503 for (i=1;i<ARRAY_SIZE(levels);i++) {
504 int level = levels[i];
505 int old_level = levels[i-1];
507 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
508 "EnumPrinterDrivers invalid value");
511 for (i=0;i<ARRAY_SIZE(levels);i++) {
512 int level = levels[i];
514 for (j=0;j<ctx->driver_count[level];j++) {
515 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
516 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
520 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
523 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
524 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
525 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
526 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
527 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
528 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
531 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
532 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
533 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
534 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
535 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
536 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
537 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
538 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
539 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
540 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
543 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
544 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
545 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
546 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
547 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
548 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
549 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
550 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
551 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
552 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
553 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
556 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
557 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
558 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
559 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
560 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
561 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
562 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
563 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
564 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
567 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
568 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
569 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
570 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
571 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
572 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
573 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
574 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
575 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
576 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
577 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
578 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
579 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
580 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
581 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
582 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
583 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
586 /* level 8 is our reference, and it makes no sense to compare it to itself */
595 static bool test_EnumMonitors(struct torture_context *tctx,
596 struct dcerpc_binding_handle *b,
597 struct test_spoolss_context *ctx)
600 struct spoolss_EnumMonitors r;
601 uint16_t levels[] = { 1, 2 };
604 for (i=0;i<ARRAY_SIZE(levels);i++) {
605 int level = levels[i];
609 union spoolss_MonitorInfo *info;
611 r.in.servername = "";
615 r.out.needed = &needed;
616 r.out.count = &count;
619 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
621 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
622 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
623 if (W_ERROR_IS_OK(r.out.result)) {
624 /* TODO: do some more checks here */
627 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
628 "EnumMonitors failed");
630 blob = data_blob_talloc(ctx, NULL, needed);
631 data_blob_clear(&blob);
633 r.in.offered = needed;
635 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
636 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
638 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
640 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
642 ctx->monitor_count[level] = count;
643 ctx->monitors[level] = info;
646 for (i=1;i<ARRAY_SIZE(levels);i++) {
647 int level = levels[i];
648 int old_level = levels[i-1];
649 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
650 "EnumMonitors invalid value");
653 for (i=0;i<ARRAY_SIZE(levels);i++) {
654 int level = levels[i];
655 for (j=0;j<ctx->monitor_count[level];j++) {
656 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
657 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
660 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
663 /* level 2 is our reference, and it makes no sense to compare it to itself */
672 static bool test_EnumPrintProcessors(struct torture_context *tctx,
673 struct dcerpc_binding_handle *b,
674 struct test_spoolss_context *ctx,
675 const char *environment)
678 struct spoolss_EnumPrintProcessors r;
679 uint16_t levels[] = { 1 };
682 for (i=0;i<ARRAY_SIZE(levels);i++) {
683 int level = levels[i];
687 union spoolss_PrintProcessorInfo *info;
689 r.in.servername = "";
690 r.in.environment = environment;
694 r.out.needed = &needed;
695 r.out.count = &count;
698 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
700 status = dcerpc_spoolss_EnumPrintProcessors_r(b, ctx, &r);
701 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
702 if (W_ERROR_IS_OK(r.out.result)) {
703 /* TODO: do some more checks here */
706 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
707 "EnumPrintProcessors unexpected return code");
709 blob = data_blob_talloc(ctx, NULL, needed);
710 data_blob_clear(&blob);
712 r.in.offered = needed;
714 status = dcerpc_spoolss_EnumPrintProcessors_r(b, ctx, &r);
715 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
717 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
719 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
721 ctx->print_processor_count[level] = count;
722 ctx->print_processors[level] = info;
725 for (i=1;i<ARRAY_SIZE(levels);i++) {
726 int level = levels[i];
727 int old_level = levels[i-1];
728 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
729 "EnumPrintProcessors failed");
732 for (i=0;i<ARRAY_SIZE(levels);i++) {
733 int level = levels[i];
734 for (j=0;j<ctx->print_processor_count[level];j++) {
736 union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
737 union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
741 /* level 1 is our reference, and it makes no sense to compare it to itself */
750 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
751 struct dcerpc_binding_handle *b,
752 struct test_spoolss_context *ctx)
755 struct spoolss_EnumPrintProcDataTypes r;
756 uint16_t levels[] = { 1 };
759 for (i=0;i<ARRAY_SIZE(levels);i++) {
760 int level = levels[i];
764 union spoolss_PrintProcDataTypesInfo *info;
766 r.in.servername = "";
767 r.in.print_processor_name = "winprint";
771 r.out.needed = &needed;
772 r.out.count = &count;
775 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
777 status = dcerpc_spoolss_EnumPrintProcDataTypes_r(b, ctx, &r);
778 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
779 if (W_ERROR_IS_OK(r.out.result)) {
780 /* TODO: do some more checks here */
783 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
784 "EnumPrintProcDataTypes unexpected return code");
786 blob = data_blob_talloc(ctx, NULL, needed);
787 data_blob_clear(&blob);
789 r.in.offered = needed;
791 status = dcerpc_spoolss_EnumPrintProcDataTypes_r(b, ctx, &r);
792 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
794 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
796 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
804 static bool test_EnumPrinters(struct torture_context *tctx,
805 struct dcerpc_binding_handle *b,
806 struct test_spoolss_context *ctx)
808 struct spoolss_EnumPrinters r;
810 uint16_t levels[] = { 0, 1, 2, 4, 5 };
813 for (i=0;i<ARRAY_SIZE(levels);i++) {
814 int level = levels[i];
818 union spoolss_PrinterInfo *info;
820 r.in.flags = PRINTER_ENUM_LOCAL;
825 r.out.needed = &needed;
826 r.out.count = &count;
829 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
831 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
832 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
833 if (W_ERROR_IS_OK(r.out.result)) {
834 /* TODO: do some more checks here */
837 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
838 "EnumPrinters unexpected return code");
840 blob = data_blob_talloc(ctx, NULL, needed);
841 data_blob_clear(&blob);
843 r.in.offered = needed;
845 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
846 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
848 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
850 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
852 ctx->printer_count[level] = count;
853 ctx->printers[level] = info;
856 for (i=1;i<ARRAY_SIZE(levels);i++) {
857 int level = levels[i];
858 int old_level = levels[i-1];
859 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
860 "EnumPrinters invalid value");
863 for (i=0;i<ARRAY_SIZE(levels);i++) {
864 int level = levels[i];
865 for (j=0;j<ctx->printer_count[level];j++) {
866 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
867 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
870 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
871 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
872 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
873 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
874 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
875 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
876 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
877 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
878 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
879 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
880 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
881 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
882 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
883 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
884 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
885 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
886 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
887 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
888 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
889 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
890 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
891 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
892 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
893 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
894 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
895 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
896 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
897 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
898 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
901 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
902 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
903 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
904 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
907 /* level 2 is our reference, and it makes no sense to compare it to itself */
910 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
911 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
912 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
915 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
916 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
917 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
918 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
919 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
926 * - verify that the port of a printer was in the list returned by EnumPorts
932 static bool test_GetPrinterDriver2(struct torture_context *tctx,
933 struct dcerpc_binding_handle *b,
934 struct policy_handle *handle,
935 const char *driver_name,
936 const char *environment);
938 bool test_GetPrinter_level(struct torture_context *tctx,
939 struct dcerpc_binding_handle *b,
940 struct policy_handle *handle,
942 union spoolss_PrinterInfo *info)
944 struct spoolss_GetPrinter r;
947 r.in.handle = handle;
951 r.out.needed = &needed;
953 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
955 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
956 "GetPrinter failed");
958 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
959 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
960 data_blob_clear(&blob);
962 r.in.offered = needed;
964 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
965 "GetPrinter failed");
968 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
970 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
972 if (info && r.out.info) {
980 static bool test_GetPrinter(struct torture_context *tctx,
981 struct dcerpc_binding_handle *b,
982 struct policy_handle *handle,
983 const char *environment)
985 uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
988 for (i=0;i<ARRAY_SIZE(levels);i++) {
990 union spoolss_PrinterInfo info;
994 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
995 "failed to call GetPrinter");
997 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
999 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
1000 "failed to call test_GetPrinterDriver2");
1007 static bool test_SetPrinter(struct torture_context *tctx,
1008 struct dcerpc_binding_handle *b,
1009 struct policy_handle *handle,
1010 struct spoolss_SetPrinterInfoCtr *info_ctr,
1011 struct spoolss_DevmodeContainer *devmode_ctr,
1012 struct sec_desc_buf *secdesc_ctr,
1013 enum spoolss_PrinterControl command)
1015 struct spoolss_SetPrinter r;
1017 r.in.handle = handle;
1018 r.in.info_ctr = info_ctr;
1019 r.in.devmode_ctr = devmode_ctr;
1020 r.in.secdesc_ctr = secdesc_ctr;
1021 r.in.command = command;
1023 torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1025 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1026 "failed to call SetPrinter");
1027 torture_assert_werr_ok(tctx, r.out.result,
1028 "failed to call SetPrinter");
1033 static bool test_SetPrinter_errors(struct torture_context *tctx,
1034 struct dcerpc_binding_handle *b,
1035 struct policy_handle *handle)
1037 struct spoolss_SetPrinter r;
1038 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1041 struct spoolss_SetPrinterInfoCtr info_ctr;
1042 struct spoolss_DevmodeContainer devmode_ctr;
1043 struct sec_desc_buf secdesc_ctr;
1046 info_ctr.info.info0 = NULL;
1048 ZERO_STRUCT(devmode_ctr);
1049 ZERO_STRUCT(secdesc_ctr);
1051 r.in.handle = handle;
1052 r.in.info_ctr = &info_ctr;
1053 r.in.devmode_ctr = &devmode_ctr;
1054 r.in.secdesc_ctr = &secdesc_ctr;
1057 torture_comment(tctx, "Testing SetPrinter all zero\n");
1059 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1060 "failed to call SetPrinter");
1061 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1062 "failed to call SetPrinter");
1065 for (i=0; i < ARRAY_SIZE(levels); i++) {
1067 struct spoolss_SetPrinterInfo0 info0;
1068 struct spoolss_SetPrinterInfo1 info1;
1069 struct spoolss_SetPrinterInfo2 info2;
1070 struct spoolss_SetPrinterInfo3 info3;
1071 struct spoolss_SetPrinterInfo4 info4;
1072 struct spoolss_SetPrinterInfo5 info5;
1073 struct spoolss_SetPrinterInfo6 info6;
1074 struct spoolss_SetPrinterInfo7 info7;
1075 struct spoolss_SetPrinterInfo8 info8;
1076 struct spoolss_SetPrinterInfo9 info9;
1079 info_ctr.level = levels[i];
1080 switch (levels[i]) {
1083 info_ctr.info.info0 = &info0;
1087 info_ctr.info.info1 = &info1;
1091 info_ctr.info.info2 = &info2;
1095 info_ctr.info.info3 = &info3;
1099 info_ctr.info.info4 = &info4;
1103 info_ctr.info.info5 = &info5;
1107 info_ctr.info.info6 = &info6;
1111 info_ctr.info.info7 = &info7;
1115 info_ctr.info.info8 = &info8;
1119 info_ctr.info.info9 = &info9;
1123 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1124 info_ctr.level, r.in.command);
1126 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1127 "failed to call SetPrinter");
1129 switch (r.in.command) {
1130 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1131 /* is ignored for all levels other then 0 */
1132 if (info_ctr.level > 0) {
1136 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1137 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1138 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1139 if (info_ctr.level > 0) {
1140 /* is invalid for all levels other then 0 */
1141 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1142 "unexpected error code returned");
1145 torture_assert_werr_ok(tctx, r.out.result,
1146 "failed to call SetPrinter with non 0 command");
1151 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1152 /* FIXME: gd needs further investigation */
1154 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1155 "unexpected error code returned");
1159 switch (info_ctr.level) {
1161 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1162 "unexpected error code returned");
1165 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1166 "unexpected error code returned");
1172 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1173 "unexpected error code returned");
1176 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1177 "unexpected error code returned");
1180 torture_assert_werr_ok(tctx, r.out.result,
1181 "failed to call SetPrinter");
1186 if (r.in.command < 5) {
1194 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1196 if ((r->level == 2) && (r->info.info2)) {
1197 r->info.info2->secdesc_ptr = 0;
1198 r->info.info2->devmode_ptr = 0;
1202 static bool test_PrinterInfo(struct torture_context *tctx,
1203 struct dcerpc_binding_handle *b,
1204 struct policy_handle *handle)
1207 struct spoolss_SetPrinter s;
1208 struct spoolss_GetPrinter q;
1209 struct spoolss_GetPrinter q0;
1210 struct spoolss_SetPrinterInfoCtr info_ctr;
1211 union spoolss_PrinterInfo info;
1212 struct spoolss_DevmodeContainer devmode_ctr;
1213 struct sec_desc_buf secdesc_ctr;
1218 uint32_t status_list[] = {
1219 /* these do not stick
1220 PRINTER_STATUS_PAUSED,
1221 PRINTER_STATUS_ERROR,
1222 PRINTER_STATUS_PENDING_DELETION, */
1223 PRINTER_STATUS_PAPER_JAM,
1224 PRINTER_STATUS_PAPER_OUT,
1225 PRINTER_STATUS_MANUAL_FEED,
1226 PRINTER_STATUS_PAPER_PROBLEM,
1227 PRINTER_STATUS_OFFLINE,
1228 PRINTER_STATUS_IO_ACTIVE,
1229 PRINTER_STATUS_BUSY,
1230 PRINTER_STATUS_PRINTING,
1231 PRINTER_STATUS_OUTPUT_BIN_FULL,
1232 PRINTER_STATUS_NOT_AVAILABLE,
1233 PRINTER_STATUS_WAITING,
1234 PRINTER_STATUS_PROCESSING,
1235 PRINTER_STATUS_INITIALIZING,
1236 PRINTER_STATUS_WARMING_UP,
1237 PRINTER_STATUS_TONER_LOW,
1238 PRINTER_STATUS_NO_TONER,
1239 PRINTER_STATUS_PAGE_PUNT,
1240 PRINTER_STATUS_USER_INTERVENTION,
1241 PRINTER_STATUS_OUT_OF_MEMORY,
1242 PRINTER_STATUS_DOOR_OPEN,
1243 PRINTER_STATUS_SERVER_UNKNOWN,
1244 PRINTER_STATUS_POWER_SAVE,
1245 /* these do not stick
1254 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1255 uint32_t attribute_list[] = {
1256 PRINTER_ATTRIBUTE_QUEUED,
1257 /* fails with WERR_INVALID_DATATYPE:
1258 PRINTER_ATTRIBUTE_DIRECT, */
1260 PRINTER_ATTRIBUTE_DEFAULT, */
1261 PRINTER_ATTRIBUTE_SHARED,
1263 PRINTER_ATTRIBUTE_NETWORK, */
1264 PRINTER_ATTRIBUTE_HIDDEN,
1265 PRINTER_ATTRIBUTE_LOCAL,
1266 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1267 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1268 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1269 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1271 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1272 /* fails with WERR_INVALID_DATATYPE:
1273 PRINTER_ATTRIBUTE_RAW_ONLY, */
1274 /* these do not stick
1275 PRINTER_ATTRIBUTE_PUBLISHED,
1276 PRINTER_ATTRIBUTE_FAX,
1277 PRINTER_ATTRIBUTE_TS,
1296 ZERO_STRUCT(devmode_ctr);
1297 ZERO_STRUCT(secdesc_ctr);
1299 s.in.handle = handle;
1301 s.in.info_ctr = &info_ctr;
1302 s.in.devmode_ctr = &devmode_ctr;
1303 s.in.secdesc_ctr = &secdesc_ctr;
1305 q.in.handle = handle;
1309 #define TESTGETCALL(call, r) \
1310 r.in.buffer = NULL; \
1312 r.out.needed = &needed; \
1313 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1314 if (!NT_STATUS_IS_OK(status)) { \
1315 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1316 r.in.level, nt_errstr(status), __location__); \
1320 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1321 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1322 data_blob_clear(&blob); \
1323 r.in.buffer = &blob; \
1324 r.in.offered = needed; \
1326 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1327 if (!NT_STATUS_IS_OK(status)) { \
1328 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1329 r.in.level, nt_errstr(status), __location__); \
1333 if (!W_ERROR_IS_OK(r.out.result)) { \
1334 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1335 r.in.level, win_errstr(r.out.result), __location__); \
1341 #define TESTSETCALL_EXP(call, r, err) \
1342 clear_info2(&info_ctr);\
1343 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1344 if (!NT_STATUS_IS_OK(status)) { \
1345 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1346 r.in.info_ctr->level, nt_errstr(status), __location__); \
1350 if (!W_ERROR_IS_OK(err)) { \
1351 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1352 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1353 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1358 if (!W_ERROR_IS_OK(r.out.result)) { \
1359 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1360 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1365 #define TESTSETCALL(call, r) \
1366 TESTSETCALL_EXP(call, r, WERR_OK)
1368 #define STRING_EQUAL(s1, s2, field) \
1369 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1370 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1371 #field, s2, __location__); \
1376 #define MEM_EQUAL(s1, s2, length, field) \
1377 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1378 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1379 #field, (const char *)s2, __location__); \
1384 #define INT_EQUAL(i1, i2, field) \
1386 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1387 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1392 #define SD_EQUAL(sd1, sd2, field) \
1393 if (!security_descriptor_equal(sd1, sd2)) { \
1394 torture_comment(tctx, "Failed to set %s (%s)\n", \
1395 #field, __location__); \
1400 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1401 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1402 q.in.level = lvl1; \
1403 TESTGETCALL(GetPrinter, q) \
1404 info_ctr.level = lvl1; \
1405 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1406 info_ctr.info.info ## lvl1->field1 = value;\
1407 TESTSETCALL_EXP(SetPrinter, s, err) \
1408 info_ctr.info.info ## lvl1->field1 = ""; \
1409 TESTGETCALL(GetPrinter, q) \
1410 info_ctr.info.info ## lvl1->field1 = value; \
1411 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1412 q.in.level = lvl2; \
1413 TESTGETCALL(GetPrinter, q) \
1414 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1415 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1418 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1419 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1422 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1423 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1424 q.in.level = lvl1; \
1425 TESTGETCALL(GetPrinter, q) \
1426 info_ctr.level = lvl1; \
1427 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1428 info_ctr.info.info ## lvl1->field1 = value; \
1429 TESTSETCALL(SetPrinter, s) \
1430 info_ctr.info.info ## lvl1->field1 = 0; \
1431 TESTGETCALL(GetPrinter, q) \
1432 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1433 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1434 q.in.level = lvl2; \
1435 TESTGETCALL(GetPrinter, q) \
1436 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1437 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1440 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1441 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1445 do { TESTGETCALL(GetPrinter, q0) } while (0);
1447 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1448 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1450 /* level 0 printername does not stick */
1451 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1452 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1453 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1454 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1455 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1456 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1457 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1458 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1459 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1460 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1461 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1462 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1463 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1464 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1465 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1467 /* servername can be set but does not stick
1468 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1469 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1470 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1473 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1474 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1475 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1476 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1477 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1479 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1480 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1481 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1482 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1483 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1484 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1485 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1486 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1487 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1488 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1490 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1491 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1493 (attribute_list[i] | default_attribute)
1495 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1497 (attribute_list[i] | default_attribute)
1499 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1501 (attribute_list[i] | default_attribute)
1503 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1505 (attribute_list[i] | default_attribute)
1507 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1509 (attribute_list[i] | default_attribute)
1511 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1513 (attribute_list[i] | default_attribute)
1515 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1517 (attribute_list[i] | default_attribute)
1519 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1521 (attribute_list[i] | default_attribute)
1523 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1525 (attribute_list[i] | default_attribute)
1527 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1529 (attribute_list[i] | default_attribute)
1531 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1533 (attribute_list[i] | default_attribute)
1535 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1537 (attribute_list[i] | default_attribute)
1541 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1542 /* level 2 sets do not stick
1543 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1544 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1545 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1546 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1547 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1548 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1551 /* priorities need to be between 0 and 99
1552 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1553 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1554 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1555 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1556 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1557 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1558 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1559 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1560 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1562 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1563 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1566 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1567 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1570 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1571 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1573 /* FIXME: gd also test devmode and secdesc behavior */
1576 /* verify composition of level 1 description field */
1577 const char *description;
1581 do { TESTGETCALL(GetPrinter, q0) } while (0);
1583 description = talloc_strdup(tctx, q0.out.info->info1.description);
1586 do { TESTGETCALL(GetPrinter, q0) } while (0);
1588 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1589 q0.out.info->info2.printername,
1590 q0.out.info->info2.drivername,
1591 q0.out.info->info2.location);
1593 do { STRING_EQUAL(description, tmp, "description")} while (0);
1599 #define torture_assert_sid_equal(torture_ctx,got,expected,cmt)\
1600 do { struct dom_sid *__got = (got), *__expected = (expected); \
1601 if (!dom_sid_equal(__got, __expected)) { \
1602 torture_result(torture_ctx, TORTURE_FAIL, \
1603 __location__": "#got" was %s, expected %s: %s", \
1604 dom_sid_string(torture_ctx, __got), dom_sid_string(torture_ctx, __expected), cmt); \
1609 static bool test_security_descriptor_equal(struct torture_context *tctx,
1610 const struct security_descriptor *sd1,
1611 const struct security_descriptor *sd2)
1618 torture_comment(tctx, "%s\n", __location__);
1622 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1623 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1625 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1626 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1628 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1629 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1630 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1631 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1634 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1635 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1636 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1637 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1644 static bool test_sd_set_level(struct torture_context *tctx,
1645 struct dcerpc_binding_handle *b,
1646 struct policy_handle *handle,
1648 struct security_descriptor *sd)
1650 struct spoolss_SetPrinterInfoCtr info_ctr;
1651 struct spoolss_DevmodeContainer devmode_ctr;
1652 struct sec_desc_buf secdesc_ctr;
1653 union spoolss_SetPrinterInfo sinfo;
1655 ZERO_STRUCT(devmode_ctr);
1656 ZERO_STRUCT(secdesc_ctr);
1660 union spoolss_PrinterInfo info;
1661 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1662 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1665 info_ctr.info = sinfo;
1670 struct spoolss_SetPrinterInfo3 info3;
1672 info3.sec_desc_ptr = 0;
1675 info_ctr.info.info3 = &info3;
1683 secdesc_ctr.sd = sd;
1685 torture_assert(tctx,
1686 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1691 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1692 struct dcerpc_binding_handle *b,
1693 struct policy_handle *handle)
1695 union spoolss_PrinterInfo info;
1696 struct security_descriptor *sd1, *sd2;
1699 /* just compare level 2 and level 3 */
1701 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1703 sd1 = info.info2.secdesc;
1705 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1707 sd2 = info.info3.secdesc;
1709 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1710 "SD level 2 != SD level 3");
1713 /* query level 2, set level 2, query level 2 */
1715 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1717 sd1 = info.info2.secdesc;
1719 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1721 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1723 sd2 = info.info2.secdesc;
1724 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1725 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1726 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1729 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1730 "SD level 2 != SD level 2 after SD has been set via level 2");
1733 /* query level 2, set level 3, query level 2 */
1735 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1737 sd1 = info.info2.secdesc;
1739 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1741 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1743 sd2 = info.info2.secdesc;
1745 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1746 "SD level 2 != SD level 2 after SD has been set via level 3");
1748 /* set modified sd level 3, query level 2 */
1750 for (i=0; i < 93; i++) {
1751 struct security_ace a;
1752 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1753 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1755 a.size = 0; /* autogenerated */
1757 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1758 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1761 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1763 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1764 sd2 = info.info2.secdesc;
1766 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1767 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1768 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1771 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1772 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1779 * wrapper call that saves original sd, runs tests, and restores sd
1782 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1783 struct dcerpc_binding_handle *b,
1784 struct policy_handle *handle)
1786 union spoolss_PrinterInfo info;
1787 struct security_descriptor *sd;
1790 torture_comment(tctx, "Testing Printer Security Descriptors\n");
1792 /* save original sd */
1794 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
1795 "failed to get initial security descriptor");
1797 sd = security_descriptor_copy(tctx, info.info2.secdesc);
1801 ret = test_PrinterInfo_SDs(tctx, b, handle);
1803 /* restore original sd */
1805 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
1806 "failed to restore initial security descriptor");
1808 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
1809 ret ? "succeeded" : "failed");
1815 static bool test_devmode_set_level(struct torture_context *tctx,
1816 struct dcerpc_binding_handle *b,
1817 struct policy_handle *handle,
1819 struct spoolss_DeviceMode *devmode)
1821 struct spoolss_SetPrinterInfoCtr info_ctr;
1822 struct spoolss_DevmodeContainer devmode_ctr;
1823 struct sec_desc_buf secdesc_ctr;
1824 union spoolss_SetPrinterInfo sinfo;
1826 ZERO_STRUCT(devmode_ctr);
1827 ZERO_STRUCT(secdesc_ctr);
1831 union spoolss_PrinterInfo info;
1832 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1833 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1836 info_ctr.info = sinfo;
1841 struct spoolss_SetPrinterInfo8 info8;
1843 info8.devmode_ptr = 0;
1846 info_ctr.info.info8 = &info8;
1854 devmode_ctr.devmode = devmode;
1856 torture_assert(tctx,
1857 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1863 static bool test_devicemode_equal(struct torture_context *tctx,
1864 const struct spoolss_DeviceMode *d1,
1865 const struct spoolss_DeviceMode *d2)
1872 torture_comment(tctx, "%s\n", __location__);
1875 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
1876 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
1877 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
1878 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
1879 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
1880 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
1881 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
1882 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
1883 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
1884 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
1885 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
1886 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
1887 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
1888 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
1889 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
1890 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
1891 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
1892 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
1893 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
1894 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
1895 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
1896 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
1897 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
1898 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
1899 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
1900 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
1901 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
1902 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
1903 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
1904 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
1905 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
1906 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
1907 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
1908 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
1909 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
1914 static bool test_devicemode_full(struct torture_context *tctx,
1915 struct dcerpc_binding_handle *b,
1916 struct policy_handle *handle)
1918 struct spoolss_SetPrinter s;
1919 struct spoolss_GetPrinter q;
1920 struct spoolss_GetPrinter q0;
1921 struct spoolss_SetPrinterInfoCtr info_ctr;
1922 struct spoolss_SetPrinterInfo8 info8;
1923 union spoolss_PrinterInfo info;
1924 struct spoolss_DevmodeContainer devmode_ctr;
1925 struct sec_desc_buf secdesc_ctr;
1930 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1931 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1932 q.in.level = lvl1; \
1933 TESTGETCALL(GetPrinter, q) \
1934 info_ctr.level = lvl1; \
1936 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1937 } else if (lvl1 == 8) {\
1938 info_ctr.info.info ## lvl1 = &info8; \
1940 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
1941 devmode_ctr.devmode->field1 = value; \
1942 TESTSETCALL(SetPrinter, s) \
1943 TESTGETCALL(GetPrinter, q) \
1944 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
1945 q.in.level = lvl2; \
1946 TESTGETCALL(GetPrinter, q) \
1947 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
1950 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
1951 TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1954 ZERO_STRUCT(devmode_ctr);
1955 ZERO_STRUCT(secdesc_ctr);
1958 s.in.handle = handle;
1960 s.in.info_ctr = &info_ctr;
1961 s.in.devmode_ctr = &devmode_ctr;
1962 s.in.secdesc_ctr = &secdesc_ctr;
1964 q.in.handle = handle;
1969 const char *devicename;/* [charset(UTF16)] */
1970 enum spoolss_DeviceModeSpecVersion specversion;
1971 uint16_t driverversion;
1973 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
1977 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
1978 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
1979 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
1980 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
1981 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
1982 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
1983 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
1984 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
1985 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
1986 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
1987 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
1988 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
1989 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
1991 const char *formname;/* [charset(UTF16)] */
1993 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
1994 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
1995 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
1996 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
1997 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
1998 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
1999 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
2000 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
2001 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
2002 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
2003 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
2004 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
2005 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
2006 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
2011 static bool call_OpenPrinterEx(struct torture_context *tctx,
2012 struct dcerpc_pipe *p,
2014 struct spoolss_DeviceMode *devmode,
2015 struct policy_handle *handle);
2017 static bool test_ClosePrinter(struct torture_context *tctx,
2018 struct dcerpc_binding_handle *b,
2019 struct policy_handle *handle);
2021 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2022 struct dcerpc_pipe *p,
2023 struct policy_handle *handle,
2026 union spoolss_PrinterInfo info;
2027 struct spoolss_DeviceMode *devmode;
2028 struct spoolss_DeviceMode *devmode2;
2029 struct policy_handle handle_devmode;
2030 struct dcerpc_binding_handle *b = p->binding_handle;
2032 /* simply compare level8 and level2 devmode */
2034 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2036 devmode = info.info8.devmode;
2038 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2040 devmode2 = info.info2.devmode;
2042 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2043 "DM level 8 != DM level 2");
2046 /* set devicemode level 8 and see if it persists */
2048 devmode->copies = 93;
2049 devmode->formname = talloc_strdup(tctx, "Legal");
2051 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2053 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2055 devmode2 = info.info8.devmode;
2057 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2058 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2060 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2062 devmode2 = info.info2.devmode;
2064 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2065 "modified DM level 8 != DM level 2");
2068 /* set devicemode level 2 and see if it persists */
2070 devmode->copies = 39;
2071 devmode->formname = talloc_strdup(tctx, "Executive");
2073 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2075 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2077 devmode2 = info.info8.devmode;
2079 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2080 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2082 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2084 devmode2 = info.info2.devmode;
2086 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2087 "modified DM level 8 != DM level 2");
2090 /* check every single bit in public part of devicemode */
2092 torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2093 "failed to set every single devicemode component");
2096 /* change formname upon open and see if it persists in getprinter calls */
2098 devmode->formname = talloc_strdup(tctx, "A4");
2099 devmode->copies = 42;
2101 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2102 "failed to open printer handle");
2104 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2106 devmode2 = info.info8.devmode;
2108 if (strequal(devmode->devicename, devmode2->devicename)) {
2109 torture_warning(tctx, "devicenames are the same\n");
2111 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2112 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2115 if (strequal(devmode->formname, devmode2->formname)) {
2116 torture_warning(tctx, "formname are the same\n");
2118 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2119 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2122 if (devmode->copies == devmode2->copies) {
2123 torture_warning(tctx, "copies are the same\n");
2125 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2126 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2129 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2131 devmode2 = info.info2.devmode;
2133 if (strequal(devmode->devicename, devmode2->devicename)) {
2134 torture_warning(tctx, "devicenames are the same\n");
2136 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2137 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2140 if (strequal(devmode->formname, devmode2->formname)) {
2141 torture_warning(tctx, "formname is the same\n");
2143 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2144 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2147 if (devmode->copies == devmode2->copies) {
2148 torture_warning(tctx, "copies are the same\n");
2150 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2151 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2154 test_ClosePrinter(tctx, b, &handle_devmode);
2160 * wrapper call that saves original devmode, runs tests, and restores devmode
2163 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2164 struct dcerpc_pipe *p,
2165 struct policy_handle *handle,
2168 union spoolss_PrinterInfo info;
2169 struct spoolss_DeviceMode *devmode;
2171 struct dcerpc_binding_handle *b = p->binding_handle;
2173 torture_comment(tctx, "Testing Printer Devicemodes\n");
2175 /* save original devmode */
2177 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2178 "failed to get initial global devicemode");
2180 devmode = info.info8.devmode;
2184 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2186 /* restore original devmode */
2188 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2189 "failed to restore initial global device mode");
2191 torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2192 ret ? "succeeded" : "failed");
2198 static bool test_ClosePrinter(struct torture_context *tctx,
2199 struct dcerpc_binding_handle *b,
2200 struct policy_handle *handle)
2203 struct spoolss_ClosePrinter r;
2205 r.in.handle = handle;
2206 r.out.handle = handle;
2208 torture_comment(tctx, "Testing ClosePrinter\n");
2210 status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2211 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2212 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2217 static bool test_GetForm_args(struct torture_context *tctx,
2218 struct dcerpc_binding_handle *b,
2219 struct policy_handle *handle,
2220 const char *form_name,
2222 union spoolss_FormInfo *info_p)
2225 struct spoolss_GetForm r;
2228 r.in.handle = handle;
2229 r.in.form_name = form_name;
2233 r.out.needed = &needed;
2235 torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2237 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2238 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2240 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2241 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2242 data_blob_clear(&blob);
2243 r.in.buffer = &blob;
2244 r.in.offered = needed;
2245 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2246 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2248 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2250 torture_assert(tctx, r.out.info, "No form info returned");
2253 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2255 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2258 *info_p = *r.out.info;
2264 static bool test_GetForm(struct torture_context *tctx,
2265 struct dcerpc_binding_handle *b,
2266 struct policy_handle *handle,
2267 const char *form_name,
2270 return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2273 static bool test_EnumForms(struct torture_context *tctx,
2274 struct dcerpc_binding_handle *b,
2275 struct policy_handle *handle,
2279 union spoolss_FormInfo **info_p)
2281 struct spoolss_EnumForms r;
2284 union spoolss_FormInfo *info;
2286 r.in.handle = handle;
2290 r.out.needed = &needed;
2291 r.out.count = &count;
2294 torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2296 torture_assert_ntstatus_ok(tctx,
2297 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2298 "EnumForms failed");
2300 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2301 torture_skip(tctx, "EnumForms level 2 not supported");
2304 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2305 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2308 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2309 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2310 data_blob_clear(&blob);
2311 r.in.buffer = &blob;
2312 r.in.offered = needed;
2314 torture_assert_ntstatus_ok(tctx,
2315 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2316 "EnumForms failed");
2318 torture_assert(tctx, info, "No forms returned");
2321 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2323 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2335 static bool test_EnumForms_all(struct torture_context *tctx,
2336 struct dcerpc_binding_handle *b,
2337 struct policy_handle *handle,
2340 uint32_t levels[] = { 1, 2 };
2343 for (i=0; i<ARRAY_SIZE(levels); i++) {
2346 union spoolss_FormInfo *info = NULL;
2348 torture_assert(tctx,
2349 test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2350 "failed to enum forms");
2352 for (j = 0; j < count; j++) {
2353 if (!print_server) {
2354 torture_assert(tctx,
2355 test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2356 "failed to get form");
2364 static bool test_EnumForms_find_one(struct torture_context *tctx,
2365 struct dcerpc_binding_handle *b,
2366 struct policy_handle *handle,
2368 const char *form_name)
2370 union spoolss_FormInfo *info;
2375 torture_assert(tctx,
2376 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2377 "failed to enumerate forms");
2379 for (i=0; i<count; i++) {
2380 if (strequal(form_name, info[i].info1.form_name)) {
2389 static bool test_DeleteForm(struct torture_context *tctx,
2390 struct dcerpc_binding_handle *b,
2391 struct policy_handle *handle,
2392 const char *form_name)
2394 struct spoolss_DeleteForm r;
2396 r.in.handle = handle;
2397 r.in.form_name = form_name;
2399 torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2401 torture_assert_ntstatus_ok(tctx,
2402 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2403 "DeleteForm failed");
2404 torture_assert_werr_ok(tctx, r.out.result,
2405 "DeleteForm failed");
2406 torture_assert_ntstatus_ok(tctx,
2407 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2408 "2nd DeleteForm failed");
2409 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2410 "2nd DeleteForm failed");
2415 static bool test_AddForm(struct torture_context *tctx,
2416 struct dcerpc_binding_handle *b,
2417 struct policy_handle *handle,
2419 union spoolss_AddFormInfo *info)
2421 struct spoolss_AddForm r;
2424 torture_skip(tctx, "only level 1 supported");
2427 r.in.handle = handle;
2431 torture_comment(tctx, "Testing AddForm(%s) level %d\n",
2432 r.in.info.info1->form_name, r.in.level);
2434 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2436 if (W_ERROR_EQUAL(r.out.result, WERR_FILE_EXISTS)) {
2437 test_DeleteForm(tctx, b, handle, r.in.info.info1->form_name);
2438 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2442 torture_assert_werr_ok(tctx, r.out.result,
2445 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2446 "2nd AddForm failed");
2447 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2448 "2nd AddForm gave unexpected result");
2453 static bool test_SetForm(struct torture_context *tctx,
2454 struct dcerpc_binding_handle *b,
2455 struct policy_handle *handle,
2456 const char *form_name,
2458 union spoolss_AddFormInfo *info)
2460 struct spoolss_SetForm r;
2462 r.in.handle = handle;
2463 r.in.form_name = form_name;
2467 torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2468 form_name, r.in.level);
2470 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2473 torture_assert_werr_ok(tctx, r.out.result,
2479 static bool test_GetForm_winreg(struct torture_context *tctx,
2480 struct dcerpc_binding_handle *b,
2481 struct policy_handle *handle,
2482 const char *key_name,
2483 const char *form_name,
2484 enum winreg_Type *w_type,
2489 static bool test_Forms(struct torture_context *tctx,
2490 struct dcerpc_binding_handle *b,
2491 struct policy_handle *handle,
2493 const char *printer_name,
2494 struct dcerpc_binding_handle *winreg_handle,
2495 struct policy_handle *hive_handle)
2497 union spoolss_FormInfo info;
2498 const char *form_name = "testform3";
2500 union spoolss_AddFormInfo add_info;
2501 struct spoolss_AddFormInfo1 info1;
2503 enum winreg_Type w_type;
2508 info1.flags = SPOOLSS_FORM_USER;
2509 info1.form_name = form_name;
2510 info1.size.width = 50;
2511 info1.size.height = 25;
2512 info1.area.left = 5;
2513 info1.area.top = 10;
2514 info1.area.right = 45;
2515 info1.area.bottom = 15;
2517 add_info.info1 = &info1;
2519 torture_assert(tctx,
2520 test_AddForm(tctx, b, handle, 1, &add_info),
2521 "failed to add form");
2523 if (winreg_handle && hive_handle) {
2525 torture_assert(tctx,
2526 test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2527 "failed to get form via winreg");
2529 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2530 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2531 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2532 torture_assert_mem_equal(tctx, &w_data[0], &add_info.info1->size.width, 4, "width mismatch");
2533 torture_assert_mem_equal(tctx, &w_data[4], &add_info.info1->size.height, 4, "height mismatch");
2534 torture_assert_mem_equal(tctx, &w_data[8], &add_info.info1->area.left, 4, "left mismatch");
2535 torture_assert_mem_equal(tctx, &w_data[12], &add_info.info1->area.top, 4, "top mismatch");
2536 torture_assert_mem_equal(tctx, &w_data[16], &add_info.info1->area.right, 4, "right mismatch");
2537 torture_assert_mem_equal(tctx, &w_data[20], &add_info.info1->area.bottom, 4, "bottom mismatch");
2538 /* skip index here */
2539 torture_assert_mem_equal(tctx, &w_data[28], &add_info.info1->flags, 4, "flags mismatch");
2542 if (!print_server) {
2543 torture_assert(tctx,
2544 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2545 "failed to get added form");
2547 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2548 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2549 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2550 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2551 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2552 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2553 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2555 if (winreg_handle && hive_handle) {
2556 torture_assert_mem_equal(tctx, &w_data[0], &info.info1.size.width, 4, "width mismatch");
2557 torture_assert_mem_equal(tctx, &w_data[4], &info.info1.size.height, 4, "height mismatch");
2558 torture_assert_mem_equal(tctx, &w_data[8], &info.info1.area.left, 4, "left mismatch");
2559 torture_assert_mem_equal(tctx, &w_data[12], &info.info1.area.top, 4, "top mismatch");
2560 torture_assert_mem_equal(tctx, &w_data[16], &info.info1.area.right, 4, "right mismatch");
2561 torture_assert_mem_equal(tctx, &w_data[20], &info.info1.area.bottom, 4, "bottom mismatch");
2562 /* skip index here */
2563 torture_assert_mem_equal(tctx, &w_data[28], &info.info1.flags, 4, "flags mismatch");
2566 add_info.info1->size.width = 1234;
2568 torture_assert(tctx,
2569 test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2570 "failed to set form");
2571 torture_assert(tctx,
2572 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2573 "failed to get setted form");
2575 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2578 torture_assert(tctx,
2579 test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2580 "Newly added form not found in enum call");
2582 torture_assert(tctx,
2583 test_DeleteForm(tctx, b, handle, form_name),
2584 "failed to delete form");
2589 static bool test_EnumPorts_old(struct torture_context *tctx,
2590 struct dcerpc_pipe *p)
2593 struct spoolss_EnumPorts r;
2596 union spoolss_PortInfo *info;
2597 struct dcerpc_binding_handle *b = p->binding_handle;
2599 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2600 dcerpc_server_name(p));
2604 r.out.needed = &needed;
2605 r.out.count = &count;
2608 torture_comment(tctx, "Testing EnumPorts\n");
2610 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2612 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2614 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2615 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2616 data_blob_clear(&blob);
2617 r.in.buffer = &blob;
2618 r.in.offered = needed;
2620 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2621 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2622 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2624 torture_assert(tctx, info, "No ports returned");
2627 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
2629 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2634 static bool test_AddPort(struct torture_context *tctx,
2635 struct dcerpc_pipe *p)
2638 struct spoolss_AddPort r;
2639 struct dcerpc_binding_handle *b = p->binding_handle;
2641 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
2642 dcerpc_server_name(p));
2644 r.in.monitor_name = "foo";
2646 torture_comment(tctx, "Testing AddPort\n");
2648 status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
2650 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
2652 /* win2k3 returns WERR_NOT_SUPPORTED */
2656 if (!W_ERROR_IS_OK(r.out.result)) {
2657 printf("AddPort failed - %s\n", win_errstr(r.out.result));
2666 static bool test_GetJob_args(struct torture_context *tctx,
2667 struct dcerpc_binding_handle *b,
2668 struct policy_handle *handle,
2671 union spoolss_JobInfo *info_p)
2674 struct spoolss_GetJob r;
2675 union spoolss_JobInfo info;
2678 r.in.handle = handle;
2679 r.in.job_id = job_id;
2683 r.out.needed = &needed;
2686 torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
2688 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
2689 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2691 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
2694 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2695 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2696 data_blob_clear(&blob);
2697 r.in.buffer = &blob;
2698 r.in.offered = needed;
2700 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
2701 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
2702 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
2703 torture_assert(tctx, r.out.info, "No job info returned");
2705 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2709 *info_p = *r.out.info;
2715 static bool test_GetJob(struct torture_context *tctx,
2716 struct dcerpc_binding_handle *b,
2717 struct policy_handle *handle,
2720 uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
2723 for (i=0; i < ARRAY_SIZE(levels); i++) {
2724 torture_assert(tctx,
2725 test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
2732 static bool test_SetJob(struct torture_context *tctx,
2733 struct dcerpc_binding_handle *b,
2734 struct policy_handle *handle, uint32_t job_id,
2735 enum spoolss_JobControl command)
2738 struct spoolss_SetJob r;
2740 r.in.handle = handle;
2741 r.in.job_id = job_id;
2743 r.in.command = command;
2746 case SPOOLSS_JOB_CONTROL_PAUSE:
2747 torture_comment(tctx, "Testing SetJob(%d) SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
2749 case SPOOLSS_JOB_CONTROL_RESUME:
2750 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
2752 case SPOOLSS_JOB_CONTROL_CANCEL:
2753 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
2755 case SPOOLSS_JOB_CONTROL_RESTART:
2756 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
2758 case SPOOLSS_JOB_CONTROL_DELETE:
2759 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
2761 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
2762 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
2764 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
2765 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
2767 case SPOOLSS_JOB_CONTROL_RETAIN:
2768 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
2770 case SPOOLSS_JOB_CONTROL_RELEASE:
2771 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
2774 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
2778 status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
2779 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
2780 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
2785 static bool test_AddJob(struct torture_context *tctx,
2786 struct dcerpc_binding_handle *b,
2787 struct policy_handle *handle)
2790 struct spoolss_AddJob r;
2794 r.in.handle = handle;
2796 r.out.needed = &needed;
2797 r.in.buffer = r.out.buffer = NULL;
2799 torture_comment(tctx, "Testing AddJob\n");
2801 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
2802 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
2806 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
2807 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
2813 static bool test_EnumJobs_args(struct torture_context *tctx,
2814 struct dcerpc_binding_handle *b,
2815 struct policy_handle *handle,
2818 union spoolss_JobInfo **info_p)
2821 struct spoolss_EnumJobs r;
2824 union spoolss_JobInfo *info;
2826 r.in.handle = handle;
2828 r.in.numjobs = 0xffffffff;
2832 r.out.needed = &needed;
2833 r.out.count = &count;
2836 torture_comment(tctx, "Testing EnumJobs level %d\n", level);
2838 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
2840 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
2842 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2843 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2844 data_blob_clear(&blob);
2845 r.in.buffer = &blob;
2846 r.in.offered = needed;
2848 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
2850 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
2851 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
2852 torture_assert(tctx, info, "No jobs returned");
2854 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
2857 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
2870 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
2871 struct dcerpc_binding_handle *b,
2872 struct policy_handle *handle,
2876 struct spoolss_StartDocPrinter s;
2877 struct spoolss_DocumentInfo1 info1;
2878 struct spoolss_StartPagePrinter sp;
2879 struct spoolss_WritePrinter w;
2880 struct spoolss_EndPagePrinter ep;
2881 struct spoolss_EndDocPrinter e;
2883 uint32_t num_written;
2885 torture_comment(tctx, "Testing StartDocPrinter\n");
2887 s.in.handle = handle;
2889 s.in.info.info1 = &info1;
2890 s.out.job_id = job_id;
2891 info1.document_name = "TorturePrintJob";
2892 info1.output_file = NULL;
2893 info1.datatype = "RAW";
2895 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
2896 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
2897 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
2899 for (i=1; i < 4; i++) {
2900 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
2902 sp.in.handle = handle;
2904 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
2905 torture_assert_ntstatus_ok(tctx, status,
2906 "dcerpc_spoolss_StartPagePrinter failed");
2907 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
2909 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
2911 w.in.handle = handle;
2912 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
2913 w.out.num_written = &num_written;
2915 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
2916 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
2917 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
2919 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
2921 ep.in.handle = handle;
2923 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
2924 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
2925 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
2928 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
2930 e.in.handle = handle;
2932 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
2933 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
2934 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
2939 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
2940 struct dcerpc_binding_handle *b,
2941 struct policy_handle *handle,
2946 union spoolss_JobInfo *info = NULL;
2949 torture_assert(tctx,
2950 test_AddJob(tctx, b, handle),
2953 torture_assert(tctx,
2954 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
2955 "EnumJobs level 1 failed");
2957 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
2959 for (i=0; i < num_jobs; i++) {
2960 union spoolss_JobInfo ginfo;
2962 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
2964 torture_assert(tctx,
2965 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
2966 "failed to call test_GetJob");
2968 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
2971 for (i=0; i < num_jobs; i++) {
2972 torture_assert(tctx,
2973 test_SetJob(tctx, b, handle, info[i].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE),
2974 "failed to pause printjob");
2975 torture_assert(tctx,
2976 test_SetJob(tctx, b, handle, info[i].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME),
2977 "failed to resume printjob");
2983 static bool test_DoPrintTest(struct torture_context *tctx,
2984 struct dcerpc_binding_handle *b,
2985 struct policy_handle *handle)
2988 uint32_t num_jobs = 8;
2992 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
2994 for (i=0; i < num_jobs; i++) {
2995 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, &job_ids[i]);
2998 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3000 for (i=0; i < num_jobs; i++) {
3001 ret &= test_SetJob(tctx, b, handle, job_ids[i], SPOOLSS_JOB_CONTROL_DELETE);
3007 static bool test_PausePrinter(struct torture_context *tctx,
3008 struct dcerpc_binding_handle *b,
3009 struct policy_handle *handle)
3012 struct spoolss_SetPrinter r;
3013 struct spoolss_SetPrinterInfoCtr info_ctr;
3014 struct spoolss_DevmodeContainer devmode_ctr;
3015 struct sec_desc_buf secdesc_ctr;
3018 info_ctr.info.info0 = NULL;
3020 ZERO_STRUCT(devmode_ctr);
3021 ZERO_STRUCT(secdesc_ctr);
3023 r.in.handle = handle;
3024 r.in.info_ctr = &info_ctr;
3025 r.in.devmode_ctr = &devmode_ctr;
3026 r.in.secdesc_ctr = &secdesc_ctr;
3027 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3029 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3031 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3033 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3035 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3040 static bool test_ResumePrinter(struct torture_context *tctx,
3041 struct dcerpc_binding_handle *b,
3042 struct policy_handle *handle)
3045 struct spoolss_SetPrinter r;
3046 struct spoolss_SetPrinterInfoCtr info_ctr;
3047 struct spoolss_DevmodeContainer devmode_ctr;
3048 struct sec_desc_buf secdesc_ctr;
3051 info_ctr.info.info0 = NULL;
3053 ZERO_STRUCT(devmode_ctr);
3054 ZERO_STRUCT(secdesc_ctr);
3056 r.in.handle = handle;
3057 r.in.info_ctr = &info_ctr;
3058 r.in.devmode_ctr = &devmode_ctr;
3059 r.in.secdesc_ctr = &secdesc_ctr;
3060 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3062 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3064 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3066 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3068 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3073 static bool test_GetPrinterData(struct torture_context *tctx,
3074 struct dcerpc_binding_handle *b,
3075 struct policy_handle *handle,
3076 const char *value_name,
3077 enum winreg_Type *type_p,
3082 struct spoolss_GetPrinterData r;
3084 enum winreg_Type type;
3085 union spoolss_PrinterData data;
3087 r.in.handle = handle;
3088 r.in.value_name = value_name;
3090 r.out.needed = &needed;
3092 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3094 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3096 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3097 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3099 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3100 r.in.offered = needed;
3101 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3102 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3103 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3106 torture_assert_werr_ok(tctx, r.out.result,
3107 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3109 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3116 *data_p = r.out.data;
3126 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3127 struct dcerpc_pipe *p,
3128 struct policy_handle *handle,
3129 const char *key_name,
3130 const char *value_name,
3131 enum winreg_Type *type_p,
3136 struct spoolss_GetPrinterDataEx r;
3137 enum winreg_Type type;
3139 union spoolss_PrinterData data;
3140 struct dcerpc_binding_handle *b = p->binding_handle;
3142 r.in.handle = handle;
3143 r.in.key_name = key_name;
3144 r.in.value_name = value_name;
3147 r.out.needed = &needed;
3148 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3150 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3151 r.in.key_name, r.in.value_name);
3153 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3154 if (!NT_STATUS_IS_OK(status)) {
3155 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
3156 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
3157 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3159 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3162 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3163 r.in.offered = needed;
3164 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3165 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3166 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3169 torture_assert_werr_ok(tctx, r.out.result,
3170 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3172 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3179 *data_p = r.out.data;
3189 static bool test_GetPrinterData_list(struct torture_context *tctx,
3190 struct dcerpc_pipe *p,
3191 struct policy_handle *handle,
3192 const char **architecture)
3194 struct dcerpc_binding_handle *b = p->binding_handle;
3195 const char *list[] = {
3199 /* "NetPopup", not on w2k8 */
3200 /* "NetPopupToComputer", not on w2k8 */
3203 "DefaultSpoolDirectory",
3207 /* "OSVersionEx", not on s3 */
3212 for (i=0; i < ARRAY_SIZE(list); i++) {
3213 enum winreg_Type type, type_ex;
3214 uint8_t *data, *data_ex;
3215 uint32_t needed, needed_ex;
3217 torture_assert(tctx, test_GetPrinterData(tctx, b, handle, list[i], &type, &data, &needed),
3218 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
3219 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
3220 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
3221 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
3222 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
3223 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3225 if (strequal(list[i], "Architecture")) {
3227 DATA_BLOB blob = data_blob_const(data, needed);
3228 *architecture = reg_val_data_string(tctx, lp_iconv_convenience(tctx->lp_ctx), REG_SZ, blob);
3236 static bool test_EnumPrinterData(struct torture_context *tctx,
3237 struct dcerpc_pipe *p,
3238 struct policy_handle *handle,
3239 uint32_t enum_index,
3240 uint32_t value_offered,
3241 uint32_t data_offered,
3242 enum winreg_Type *type_p,
3243 uint32_t *value_needed_p,
3244 uint32_t *data_needed_p,
3245 const char **value_name_p,
3249 struct spoolss_EnumPrinterData r;
3250 uint32_t data_needed;
3251 uint32_t value_needed;
3252 enum winreg_Type type;
3253 struct dcerpc_binding_handle *b = p->binding_handle;
3255 r.in.handle = handle;
3256 r.in.enum_index = enum_index;
3257 r.in.value_offered = value_offered;
3258 r.in.data_offered = data_offered;
3259 r.out.data_needed = &data_needed;
3260 r.out.value_needed = &value_needed;
3262 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3263 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3265 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3267 torture_assert_ntstatus_ok(tctx,
3268 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
3269 "EnumPrinterData failed");
3274 if (value_needed_p) {
3275 *value_needed_p = value_needed;
3277 if (data_needed_p) {
3278 *data_needed_p = data_needed;
3281 *value_name_p = r.out.value_name;
3284 *data_p = r.out.data;
3287 *result_p = r.out.result;
3294 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3295 struct dcerpc_pipe *p,
3296 struct policy_handle *handle)
3298 uint32_t enum_index = 0;
3299 enum winreg_Type type;
3300 uint32_t value_needed;
3301 uint32_t data_needed;
3303 const char *value_name;
3306 torture_comment(tctx, "Testing EnumPrinterData\n");
3309 torture_assert(tctx,
3310 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3311 &type, &value_needed, &data_needed,
3312 &value_name, &data, &result),
3313 "EnumPrinterData failed");
3315 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3319 torture_assert(tctx,
3320 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3321 &type, &value_needed, &data_needed,
3322 &value_name, &data, &result),
3323 "EnumPrinterData failed");
3325 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3331 } while (W_ERROR_IS_OK(result));
3333 torture_comment(tctx, "EnumPrinterData test succeeded\n");
3338 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3339 struct dcerpc_binding_handle *b,
3340 struct policy_handle *handle,
3341 const char *key_name,
3343 struct spoolss_PrinterEnumValues **info_p)
3345 struct spoolss_EnumPrinterDataEx r;
3346 struct spoolss_PrinterEnumValues *info;
3350 r.in.handle = handle;
3351 r.in.key_name = key_name;
3353 r.out.needed = &needed;
3354 r.out.count = &count;
3357 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3359 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3360 "EnumPrinterDataEx failed");
3361 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3362 r.in.offered = needed;
3363 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3364 "EnumPrinterDataEx failed");
3367 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3369 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, lp_iconv_convenience(tctx->lp_ctx), needed, 1);
3381 static bool test_SetPrinterData(struct torture_context *tctx,
3382 struct dcerpc_binding_handle *b,
3383 struct policy_handle *handle,
3384 const char *value_name,
3385 enum winreg_Type type,
3388 static bool test_DeletePrinterData(struct torture_context *tctx,
3389 struct dcerpc_binding_handle *b,
3390 struct policy_handle *handle,
3391 const char *value_name);
3393 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3394 struct dcerpc_pipe *p,
3395 struct policy_handle *handle)
3398 struct spoolss_PrinterEnumValues *info;
3400 uint32_t value_needed, data_needed;
3401 uint32_t value_offered, data_offered;
3403 struct dcerpc_binding_handle *b = p->binding_handle;
3405 enum winreg_Type type;
3408 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3410 torture_assert(tctx,
3411 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3412 "REG_SZ", "torture_data1", &type, &blob), "");
3414 torture_assert(tctx,
3415 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
3416 "SetPrinterData failed");
3418 blob = data_blob_string_const("torture_data2");
3420 torture_assert(tctx,
3421 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3422 "SetPrinterData failed");
3424 blob = data_blob_talloc(tctx, NULL, 4);
3425 SIVAL(blob.data, 0, 0x11223344);
3427 torture_assert(tctx,
3428 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
3429 "SetPrinterData failed");
3431 torture_assert(tctx,
3432 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
3433 "failed to call EnumPrinterDataEx");
3435 /* get the max sizes for value and data */
3437 torture_assert(tctx,
3438 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3439 NULL, &value_needed, &data_needed,
3440 NULL, NULL, &result),
3441 "EnumPrinterData failed");
3442 torture_assert_werr_ok(tctx, result, "unexpected result");
3444 /* check if the reply from the EnumPrinterData really matches max values */
3446 for (i=0; i < count; i++) {
3447 if (info[i].value_name_len > value_needed) {
3449 talloc_asprintf(tctx,
3450 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3451 info[i].value_name_len, value_needed));
3453 if (info[i].data_length > data_needed) {
3455 talloc_asprintf(tctx,
3456 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3457 info[i].data_length, data_needed));
3461 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3462 * sort or not sort the replies by value name, we should be able to do
3463 * the following entry comparison */
3465 data_offered = data_needed;
3466 value_offered = value_needed;
3468 for (i=0; i < count; i++) {
3470 const char *value_name;
3473 torture_assert(tctx,
3474 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3475 &type, &value_needed, &data_needed,
3476 &value_name, &data, &result),
3477 "EnumPrinterData failed");
3479 if (i -1 == count) {
3480 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3481 "unexpected result");
3484 torture_assert_werr_ok(tctx, result, "unexpected result");
3487 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3488 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3489 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
3490 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
3491 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
3494 torture_assert(tctx,
3495 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
3496 "DeletePrinterData failed");
3497 torture_assert(tctx,
3498 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
3499 "DeletePrinterData failed");
3500 torture_assert(tctx,
3501 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
3502 "DeletePrinterData failed");
3504 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
3509 static bool test_DeletePrinterData(struct torture_context *tctx,
3510 struct dcerpc_binding_handle *b,
3511 struct policy_handle *handle,
3512 const char *value_name)
3515 struct spoolss_DeletePrinterData r;
3517 r.in.handle = handle;
3518 r.in.value_name = value_name;
3520 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
3523 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
3525 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
3526 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
3531 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
3532 struct dcerpc_binding_handle *b,
3533 struct policy_handle *handle,
3534 const char *key_name,
3535 const char *value_name)
3537 struct spoolss_DeletePrinterDataEx r;
3539 r.in.handle = handle;
3540 r.in.key_name = key_name;
3541 r.in.value_name = value_name;
3543 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
3544 r.in.key_name, r.in.value_name);
3546 torture_assert_ntstatus_ok(tctx,
3547 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
3548 "DeletePrinterDataEx failed");
3549 torture_assert_werr_ok(tctx, r.out.result,
3550 "DeletePrinterDataEx failed");
3555 static bool test_DeletePrinterKey(struct torture_context *tctx,
3556 struct dcerpc_binding_handle *b,
3557 struct policy_handle *handle,
3558 const char *key_name)
3560 struct spoolss_DeletePrinterKey r;
3562 r.in.handle = handle;
3563 r.in.key_name = key_name;
3565 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
3567 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
3568 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
3572 torture_assert_ntstatus_ok(tctx,
3573 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
3574 "DeletePrinterKey failed");
3575 torture_assert_werr_ok(tctx, r.out.result,
3576 "DeletePrinterKey failed");
3581 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
3582 struct dcerpc_binding_handle *b,
3583 struct policy_handle *handle)
3585 struct winreg_OpenHKLM r;
3587 r.in.system_name = NULL;
3588 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3589 r.out.handle = handle;
3591 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
3593 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
3594 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
3599 static void init_winreg_String(struct winreg_String *name, const char *s)
3603 name->name_len = 2 * (strlen_m(s) + 1);
3604 name->name_size = name->name_len;
3607 name->name_size = 0;
3611 static bool test_winreg_OpenKey(struct torture_context *tctx,
3612 struct dcerpc_binding_handle *b,
3613 struct policy_handle *hive_handle,
3614 const char *keyname,
3615 struct policy_handle *key_handle)
3617 struct winreg_OpenKey r;
3619 r.in.parent_handle = hive_handle;
3620 init_winreg_String(&r.in.keyname, keyname);
3621 r.in.options = REG_KEYTYPE_NON_VOLATILE;
3622 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3623 r.out.handle = key_handle;
3625 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
3627 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
3628 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
3633 static bool test_winreg_CloseKey(struct torture_context *tctx,
3634 struct dcerpc_binding_handle *b,
3635 struct policy_handle *handle)
3637 struct winreg_CloseKey r;
3639 r.in.handle = handle;
3640 r.out.handle = handle;
3642 torture_comment(tctx, "Testing winreg_CloseKey\n");
3644 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
3645 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
3650 bool test_winreg_QueryValue(struct torture_context *tctx,
3651 struct dcerpc_binding_handle *b,
3652 struct policy_handle *handle,
3653 const char *value_name,
3654 enum winreg_Type *type_p,
3655 uint32_t *data_size_p,
3656 uint32_t *data_length_p,
3659 struct winreg_QueryValue r;
3660 enum winreg_Type type = REG_NONE;
3661 uint32_t data_size = 0;
3662 uint32_t data_length = 0;
3663 struct winreg_String valuename;
3664 uint8_t *data = NULL;
3666 init_winreg_String(&valuename, value_name);
3668 data = talloc_zero_array(tctx, uint8_t, 0);
3670 r.in.handle = handle;
3671 r.in.value_name = &valuename;
3673 r.in.data_size = &data_size;
3674 r.in.data_length = &data_length;
3678 r.out.data_size = &data_size;
3679 r.out.data_length = &data_length;
3681 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
3683 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
3684 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3685 *r.in.data_size = *r.out.data_size;
3686 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
3689 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
3691 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
3694 *type_p = *r.out.type;
3697 *data_size_p = *r.out.data_size;
3699 if (data_length_p) {
3700 *data_length_p = *r.out.data_length;
3703 *data_p = r.out.data;
3709 static bool test_winreg_query_printerdata(struct torture_context *tctx,
3710 struct dcerpc_binding_handle *b,
3711 struct policy_handle *handle,
3712 const char *printer_name,
3713 const char *key_name,
3714 const char *value_name,
3715 enum winreg_Type *w_type,
3720 const char *printer_key;
3721 struct policy_handle key_handle;
3723 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
3724 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
3726 torture_assert(tctx,
3727 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
3729 torture_assert(tctx,
3730 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
3732 torture_assert(tctx,
3733 test_winreg_CloseKey(tctx, b, &key_handle), "");
3738 static bool test_GetForm_winreg(struct torture_context *tctx,
3739 struct dcerpc_binding_handle *b,
3740 struct policy_handle *handle,
3741 const char *key_name,
3742 const char *form_name,
3743 enum winreg_Type *w_type,
3748 struct policy_handle key_handle;
3750 torture_assert(tctx,
3751 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
3753 torture_assert(tctx,
3754 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
3756 torture_assert(tctx,
3757 test_winreg_CloseKey(tctx, b, &key_handle), "");
3762 static bool test_SetPrinterData(struct torture_context *tctx,
3763 struct dcerpc_binding_handle *b,
3764 struct policy_handle *handle,
3765 const char *value_name,
3766 enum winreg_Type type,
3770 struct spoolss_SetPrinterData r;
3772 r.in.handle = handle;
3773 r.in.value_name = value_name;
3776 r.in.offered = offered;
3778 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
3781 torture_assert_ntstatus_ok(tctx,
3782 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
3783 "SetPrinterData failed");
3784 torture_assert_werr_ok(tctx, r.out.result,
3785 "SetPrinterData failed");
3790 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
3791 struct dcerpc_binding_handle *b,
3792 struct policy_handle *handle,
3793 const char *printer_name,
3794 struct dcerpc_binding_handle *winreg_handle,
3795 struct policy_handle *hive_handle)
3797 const char *values[] = {
3801 /* FIXME: not working with s3 atm. */
3807 /* FIXME: not working with s3 atm. */
3814 for (i=0; i < ARRAY_SIZE(values); i++) {
3816 enum winreg_Type type;
3821 torture_assert(tctx,
3822 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3823 "REG_SZ", "dog", &type, &blob), "");
3825 torture_assert(tctx,
3826 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
3827 "SetPrinterData failed");
3829 torture_assert(tctx,
3830 test_GetPrinterData(tctx, b, handle, values[i], &type, &data, &needed),
3831 "GetPrinterData failed");
3833 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
3834 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
3835 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
3837 if (winreg_handle && hive_handle) {
3839 enum winreg_Type w_type;
3844 torture_assert(tctx,
3845 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
3846 printer_name, "PrinterDriverData", values[i],
3847 &w_type, &w_size, &w_length, &w_data), "");
3849 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
3850 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
3851 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
3852 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
3855 torture_assert(tctx,
3856 test_DeletePrinterData(tctx, b, handle, values[i]),
3857 "DeletePrinterData failed");
3864 static bool test_EnumPrinterKey(struct torture_context *tctx,
3865 struct dcerpc_binding_handle *b,
3866 struct policy_handle *handle,
3867 const char *key_name,
3868 const char ***array);
3870 static bool test_SetPrinterDataEx(struct torture_context *tctx,
3871 struct dcerpc_binding_handle *b,
3872 struct policy_handle *handle,
3873 const char *key_name,
3874 const char *value_name,
3875 enum winreg_Type type,
3880 struct spoolss_SetPrinterDataEx r;
3882 r.in.handle = handle;
3883 r.in.key_name = key_name;
3884 r.in.value_name = value_name;
3887 r.in.offered = offered;
3889 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
3890 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
3892 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
3894 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
3895 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
3900 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
3901 struct dcerpc_pipe *p,
3902 struct policy_handle *handle,
3903 const char *printername,
3904 struct dcerpc_binding_handle *winreg_handle,
3905 struct policy_handle *hive_handle)
3907 struct dcerpc_binding_handle *b = p->binding_handle;
3908 const char *value_name = "dog";
3909 const char *keys[] = {
3913 /* FIXME: not working with s3 atm. */
3914 "torturedataex_with_subkey\\subkey",
3915 "torturedataex_with_subkey\\subkey:0",
3916 "torturedataex_with_subkey\\subkey:1",
3917 "torturedataex_with_subkey\\subkey\\subsubkey",
3918 "torturedataex_with_subkey\\subkey\\subsubkey:0",
3919 "torturedataex_with_subkey\\subkey\\subsubkey:1",
3923 /* FIXME: not working with s3 atm. */
3930 enum winreg_Type types[] = {
3936 const char *str = "abcdefghijklmnopqrstuvwxzy";
3940 for (i=0; i < ARRAY_SIZE(keys); i++) {
3941 for (t=0; t < ARRAY_SIZE(types); t++) {
3942 for (s=0; s < strlen(str); s++) {
3946 enum winreg_Type type;
3947 const char *string = talloc_strndup(tctx, str, s);
3948 DATA_BLOB blob = data_blob_string_const(string);
3949 const char **subkeys;
3952 uint32_t needed, offered = 0;
3954 struct spoolss_PrinterEnumValues *einfo;
3956 if (types[t] == REG_DWORD) {
3960 if (torture_setting_bool(tctx, "samba3", false)) {
3961 if ((types[t] == REG_MULTI_SZ) && s == 0) {
3962 torture_warning(tctx, "samba3 does not handle 4 byte emtpy REG_MULTI_SZ buffers");
3970 offered = blob.length;
3973 data = data_blob_talloc(tctx, NULL, 4);
3974 SIVAL(data.data, 0, 0x12345678);
3978 torture_assert(tctx,
3979 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3980 "REG_SZ", string, &type, &data), "");
3981 offered = data.length;
3982 /*strlen_m_term(data.string)*2;*/
3985 torture_assert(tctx,
3986 reg_string_to_val(tctx, lp_iconv_convenience(tctx->lp_ctx),
3987 "REG_SZ", string, &type, &data), "");
3988 torture_assert(tctx, data_blob_realloc(tctx, &data, data.length + 2), "");
3989 memset(&data.data[data.length - 2], '\0', 2);
3990 offered = data.length;
3993 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
3996 torture_assert(tctx,
3997 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, types[t], data.data, offered),
3998 "failed to call SetPrinterDataEx");
4000 torture_assert(tctx,
4001 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &data_out, &needed),
4002 "failed to call GetPrinterDataEx");
4004 torture_assert(tctx,
4005 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
4006 "failed to call EnumPrinterDataEx");
4008 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
4009 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
4010 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
4012 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
4013 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
4014 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
4015 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
4016 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
4017 if (einfo[0].data_length > 0) {
4018 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
4021 if (winreg_handle && hive_handle) {
4022 enum winreg_Type w_type;
4027 torture_assert(tctx,
4028 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4029 printername, keys[i], value_name,
4030 &w_type, &w_size, &w_length, &w_data), "");
4032 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
4033 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
4034 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
4035 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
4038 key = talloc_strdup(tctx, keys[i]);
4040 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
4044 c = strchr(key, '\\');
4048 /* we have subkeys */
4052 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
4056 for (k=0; subkeys && subkeys[k]; k++) {
4058 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
4060 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
4065 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4070 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
4081 static bool test_PrinterData_winreg(struct torture_context *tctx,
4082 struct dcerpc_pipe *p,
4083 struct policy_handle *handle,
4084 const char *printer_name)
4086 struct dcerpc_binding_handle *b = p->binding_handle;
4087 struct dcerpc_pipe *p2;
4089 struct policy_handle hive_handle;
4090 struct dcerpc_binding_handle *b2;
4092 torture_assert_ntstatus_ok(tctx,
4093 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4094 "could not open winreg pipe");
4095 b2 = p2->binding_handle;
4097 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4099 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
4100 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
4102 test_winreg_CloseKey(tctx, b2, &hive_handle);
4109 static bool test_Forms_winreg(struct torture_context *tctx,
4110 struct dcerpc_binding_handle *b,
4111 struct policy_handle *handle,
4113 const char *printer_name)
4115 struct dcerpc_pipe *p2;
4117 struct policy_handle hive_handle;
4118 struct dcerpc_binding_handle *b2;
4120 torture_assert_ntstatus_ok(tctx,
4121 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
4122 "could not open winreg pipe");
4123 b2 = p2->binding_handle;
4125 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
4127 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
4129 test_winreg_CloseKey(tctx, b2, &hive_handle);
4136 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
4137 struct dcerpc_binding_handle *b,
4138 struct policy_handle *handle,
4139 uint32_t *change_id)
4141 enum winreg_Type type;
4145 torture_assert(tctx,
4146 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
4147 "failed to call GetPrinterData");
4149 torture_assert(tctx, type == REG_DWORD, "unexpected type");
4150 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
4152 *change_id = IVAL(data, 0);
4157 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
4158 struct dcerpc_pipe *p,
4159 struct policy_handle *handle,
4160 uint32_t *change_id)
4162 enum winreg_Type type;
4166 torture_assert(tctx,
4167 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
4168 "failed to call GetPrinterData");
4170 torture_assert(tctx, type == REG_DWORD, "unexpected type");
4171 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
4173 *change_id = IVAL(data, 0);
4178 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
4179 struct dcerpc_binding_handle *b,
4180 struct policy_handle *handle,
4181 uint32_t *change_id)
4183 union spoolss_PrinterInfo info;
4185 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
4186 "failed to query Printer level 0");
4188 *change_id = info.info0.change_id;
4193 static bool test_ChangeID(struct torture_context *tctx,
4194 struct dcerpc_pipe *p,
4195 struct policy_handle *handle)
4197 uint32_t change_id, change_id_ex, change_id_info;
4198 uint32_t change_id2, change_id_ex2, change_id_info2;
4199 union spoolss_PrinterInfo info;
4200 const char *comment;
4201 struct dcerpc_binding_handle *b = p->binding_handle;
4203 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
4205 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
4206 "failed to query for ChangeID");
4207 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
4208 "failed to query for ChangeID");
4209 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
4210 "failed to query for ChangeID");
4212 torture_assert_int_equal(tctx, change_id, change_id_ex,
4213 "change_ids should all be equal");
4214 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
4215 "change_ids should all be equal");
4218 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
4220 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
4221 "failed to query for ChangeID");
4222 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
4223 "failed to query Printer level 2");
4224 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
4225 "failed to query for ChangeID");
4226 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
4227 "failed to query for ChangeID");
4228 torture_assert_int_equal(tctx, change_id, change_id_ex,
4229 "change_id should not have changed");
4230 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
4231 "change_id should not have changed");
4234 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
4236 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
4237 "failed to query for ChangeID");
4238 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
4239 "failed to query for ChangeID");
4240 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
4241 "failed to query for ChangeID");
4242 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
4243 "failed to query Printer level 2");
4244 comment = talloc_strdup(tctx, info.info2.comment);
4247 struct spoolss_SetPrinterInfoCtr info_ctr;
4248 struct spoolss_DevmodeContainer devmode_ctr;
4249 struct sec_desc_buf secdesc_ctr;
4250 union spoolss_SetPrinterInfo sinfo;
4252 ZERO_STRUCT(info_ctr);
4253 ZERO_STRUCT(devmode_ctr);
4254 ZERO_STRUCT(secdesc_ctr);
4257 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
4258 sinfo.info2->comment = "torture_comment";
4261 info_ctr.info = sinfo;
4263 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
4264 "failed to call SetPrinter");
4266 sinfo.info2->comment = comment;
4268 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
4269 "failed to call SetPrinter");
4273 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
4274 "failed to query for ChangeID");
4275 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
4276 "failed to query for ChangeID");
4277 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
4278 "failed to query for ChangeID");
4280 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
4281 "change_ids should all be equal");
4282 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
4283 "change_ids should all be equal");
4285 torture_assert(tctx, (change_id < change_id2),
4286 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
4287 change_id2, change_id));
4288 torture_assert(tctx, (change_id_ex < change_id_ex2),
4289 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
4290 change_id_ex2, change_id_ex));
4291 torture_assert(tctx, (change_id_info < change_id_info2),
4292 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
4293 change_id_info2, change_id_info));
4295 torture_comment(tctx, "ChangeID tests succeeded\n\n");
4300 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
4301 struct dcerpc_pipe *p,
4302 struct policy_handle *handle)
4305 struct dcerpc_binding *b;
4306 struct dcerpc_pipe *p2;
4307 struct spoolss_ClosePrinter cp;
4309 /* only makes sense on SMB */
4310 if (p->conn->transport.transport != NCACN_NP) {
4314 torture_comment(tctx, "testing close on secondary pipe\n");
4316 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
4317 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
4319 status = dcerpc_secondary_connection(p, &p2, b);
4320 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
4322 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
4323 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
4325 cp.in.handle = handle;
4326 cp.out.handle = handle;
4328 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
4329 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
4330 "ERROR: Allowed close on secondary connection");
4332 torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
4333 "Unexpected fault code");
4340 static bool test_OpenPrinter_badname(struct torture_context *tctx,
4341 struct dcerpc_binding_handle *b, const char *name)
4344 struct spoolss_OpenPrinter op;
4345 struct spoolss_OpenPrinterEx opEx;
4346 struct policy_handle handle;
4349 op.in.printername = name;
4350 op.in.datatype = NULL;
4351 op.in.devmode_ctr.devmode= NULL;
4352 op.in.access_mask = 0;
4353 op.out.handle = &handle;
4355 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
4357 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
4358 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
4359 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
4360 "unexpected result");
4362 if (W_ERROR_IS_OK(op.out.result)) {
4363 ret &=test_ClosePrinter(tctx, b, &handle);
4366 opEx.in.printername = name;
4367 opEx.in.datatype = NULL;
4368 opEx.in.devmode_ctr.devmode = NULL;
4369 opEx.in.access_mask = 0;
4371 opEx.in.userlevel.level1 = NULL;
4372 opEx.out.handle = &handle;
4374 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
4376 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
4377 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
4378 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
4379 "unexpected result");
4381 if (W_ERROR_IS_OK(opEx.out.result)) {
4382 ret &=test_ClosePrinter(tctx, b, &handle);
4388 static bool test_OpenPrinter(struct torture_context *tctx,
4389 struct dcerpc_pipe *p,
4391 const char *environment)
4394 struct spoolss_OpenPrinter r;
4395 struct policy_handle handle;
4397 struct dcerpc_binding_handle *b = p->binding_handle;
4399 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
4400 r.in.datatype = NULL;
4401 r.in.devmode_ctr.devmode= NULL;
4402 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4403 r.out.handle = &handle;
4405 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
4407 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
4409 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
4411 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
4413 if (!test_GetPrinter(tctx, b, &handle, environment)) {
4417 if (!torture_setting_bool(tctx, "samba3", false)) {
4418 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
4423 if (!test_ClosePrinter(tctx, b, &handle)) {
4430 static bool call_OpenPrinterEx(struct torture_context *tctx,
4431 struct dcerpc_pipe *p,
4433 struct spoolss_DeviceMode *devmode,
4434 struct policy_handle *handle)
4436 struct spoolss_OpenPrinterEx r;
4437 struct spoolss_UserLevel1 userlevel1;
4439 struct dcerpc_binding_handle *b = p->binding_handle;
4441 if (name && name[0]) {
4442 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
4443 dcerpc_server_name(p), name);
4445 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
4446 dcerpc_server_name(p));
4449 r.in.datatype = NULL;
4450 r.in.devmode_ctr.devmode= devmode;
4451 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4453 r.in.userlevel.level1 = &userlevel1;
4454 r.out.handle = handle;
4456 userlevel1.size = 1234;
4457 userlevel1.client = "hello";
4458 userlevel1.user = "spottyfoot!";
4459 userlevel1.build = 1;
4460 userlevel1.major = 2;
4461 userlevel1.minor = 3;
4462 userlevel1.processor = 4;
4464 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
4466 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r);
4468 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
4470 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
4475 static bool test_printer_rename(struct torture_context *tctx,
4476 struct dcerpc_pipe *p,
4477 struct policy_handle *handle,
4481 union spoolss_PrinterInfo info;
4482 union spoolss_SetPrinterInfo sinfo;
4483 struct spoolss_SetPrinterInfoCtr info_ctr;
4484 struct spoolss_DevmodeContainer devmode_ctr;
4485 struct sec_desc_buf secdesc_ctr;
4486 const char *printer_name;
4487 const char *printer_name_orig;
4488 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
4489 struct policy_handle new_handle;
4491 struct dcerpc_binding_handle *b = p->binding_handle;
4493 ZERO_STRUCT(devmode_ctr);
4494 ZERO_STRUCT(secdesc_ctr);
4496 torture_comment(tctx, "Testing Printer rename operations\n");
4498 torture_assert(tctx,
4499 test_GetPrinter_level(tctx, b, handle, 2, &info),
4500 "failed to call GetPrinter level 2");
4502 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
4504 q = strrchr(info.info2.printername, '\\');
4506 torture_warning(tctx,
4507 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
4510 torture_assert(tctx,
4511 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
4513 sinfo.info2->printername = printer_name_new;
4516 info_ctr.info = sinfo;
4518 torture_assert(tctx,
4519 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
4520 "failed to call SetPrinter level 2");
4522 torture_assert(tctx,
4523 test_GetPrinter_level(tctx, b, handle, 2, &info),
4524 "failed to call GetPrinter level 2");
4526 printer_name = talloc_strdup(tctx, info.info2.printername);
4528 q = strrchr(info.info2.printername, '\\');
4530 torture_warning(tctx,
4531 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
4536 torture_assert_str_equal(tctx, printer_name, printer_name_new,
4537 "new printer name was not set");
4539 /* samba currently cannot fully rename printers */
4540 if (!torture_setting_bool(tctx, "samba3", false)) {
4541 torture_assert(tctx,
4542 test_OpenPrinter_badname(tctx, b, printer_name_orig),
4543 "still can open printer with oldname after rename");
4545 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
4548 torture_assert(tctx,
4549 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
4550 "failed to open printer with new name");
4552 torture_assert(tctx,
4553 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
4554 "failed to call GetPrinter level 2");
4556 /* FIXME: we openend with servername! */
4557 printer_name = talloc_asprintf(tctx, "\\\\%s\\%s",
4558 dcerpc_server_name(p), printer_name_new);
4560 torture_assert_str_equal(tctx, info.info2.printername, printer_name,
4561 "new printer name was not set");
4563 torture_assert(tctx,
4564 test_ClosePrinter(tctx, b, &new_handle),
4565 "failed to close printer");
4567 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
4573 static bool test_OpenPrinterEx(struct torture_context *tctx,
4574 struct dcerpc_pipe *p,
4576 const char *environment)
4578 struct policy_handle handle;
4580 struct dcerpc_binding_handle *b = p->binding_handle;
4582 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
4586 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
4590 if (!test_GetPrinter(tctx, b, &handle, environment)) {
4594 if (!test_EnumForms_all(tctx, b, &handle, false)) {
4598 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
4602 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
4606 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
4610 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
4614 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
4618 if (!test_printer_keys(tctx, b, &handle)) {
4622 if (!test_PausePrinter(tctx, b, &handle)) {
4626 if (!test_DoPrintTest(tctx, b, &handle)) {
4630 if (!test_ResumePrinter(tctx, b, &handle)) {
4634 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
4638 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
4642 if (!torture_setting_bool(tctx, "samba3", false)) {
4643 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
4648 if (!test_ClosePrinter(tctx, b, &handle)) {
4655 static bool test_EnumPrinters_old(struct torture_context *tctx,
4656 struct dcerpc_pipe *p,
4657 const char *environment)
4659 struct spoolss_EnumPrinters r;
4661 uint16_t levels[] = {1, 2, 4, 5};
4664 struct dcerpc_binding_handle *b = p->binding_handle;
4666 for (i=0;i<ARRAY_SIZE(levels);i++) {
4667 union spoolss_PrinterInfo *info;
4672 r.in.flags = PRINTER_ENUM_LOCAL;
4674 r.in.level = levels[i];
4677 r.out.needed = &needed;
4678 r.out.count = &count;
4681 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
4683 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
4684 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
4686 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4687 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4688 data_blob_clear(&blob);
4689 r.in.buffer = &blob;
4690 r.in.offered = needed;
4691 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
4694 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
4696 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
4698 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4701 torture_comment(tctx, "No printers returned\n");
4705 for (j=0;j<count;j++) {
4706 if (r.in.level == 1) {
4707 char *unc = talloc_strdup(tctx, info[j].info1.name);
4710 if (unc[0] == '\\' && unc[1] == '\\') {
4713 slash = strchr(unc, '\\');
4718 if (!test_OpenPrinter(tctx, p, name, environment)) {
4721 if (!test_OpenPrinterEx(tctx, p, name, environment)) {
4731 static bool test_GetPrinterDriver(struct torture_context *tctx,
4732 struct dcerpc_binding_handle *b,
4733 struct policy_handle *handle,
4734 const char *driver_name)
4736 struct spoolss_GetPrinterDriver r;
4739 r.in.handle = handle;
4740 r.in.architecture = "W32X86";
4744 r.out.needed = &needed;
4746 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
4748 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
4749 "failed to call GetPrinterDriver");
4750 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4751 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4752 data_blob_clear(&blob);
4753 r.in.buffer = &blob;
4754 r.in.offered = needed;
4755 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
4756 "failed to call GetPrinterDriver");
4759 torture_assert_werr_ok(tctx, r.out.result,
4760 "failed to call GetPrinterDriver");
4762 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4767 static bool test_GetPrinterDriver2(struct torture_context *tctx,
4768 struct dcerpc_binding_handle *b,
4769 struct policy_handle *handle,
4770 const char *driver_name,
4771 const char *architecture)
4773 struct spoolss_GetPrinterDriver2 r;
4774 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
4776 uint32_t server_major_version;
4777 uint32_t server_minor_version;
4780 r.in.handle = handle;
4781 r.in.architecture = architecture;
4782 r.in.client_major_version = 3;
4783 r.in.client_minor_version = 0;
4784 r.out.needed = &needed;
4785 r.out.server_major_version = &server_major_version;
4786 r.out.server_minor_version = &server_minor_version;
4788 for (i=0;i<ARRAY_SIZE(levels);i++) {
4792 r.in.level = levels[i];
4794 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
4795 driver_name, r.in.level);
4797 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
4798 "failed to call GetPrinterDriver2");
4799 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4800 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4801 data_blob_clear(&blob);
4802 r.in.buffer = &blob;
4803 r.in.offered = needed;
4804 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
4805 "failed to call GetPrinterDriver2");
4808 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
4809 switch (r.in.level) {
4818 torture_assert_werr_ok(tctx, r.out.result,
4819 "failed to call GetPrinterDriver2");
4821 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4827 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
4828 struct dcerpc_pipe *p,
4829 const char *environment)
4831 struct spoolss_EnumPrinterDrivers r;
4833 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
4835 struct dcerpc_binding_handle *b = p->binding_handle;
4837 for (i=0;i<ARRAY_SIZE(levels);i++) {
4841 union spoolss_DriverInfo *info;
4843 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
4844 r.in.environment = environment;
4845 r.in.level = levels[i];
4848 r.out.needed = &needed;
4849 r.out.count = &count;
4852 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
4854 status = dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r);
4856 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
4858 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
4859 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4860 data_blob_clear(&blob);
4861 r.in.buffer = &blob;
4862 r.in.offered = needed;
4863 status = dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r);
4866 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
4868 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
4871 torture_comment(tctx, "No printer drivers returned\n");
4875 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, lp_iconv_convenience(tctx->lp_ctx), needed, 4);
4881 static bool test_DeletePrinter(struct torture_context *tctx,
4882 struct dcerpc_binding_handle *b,
4883 struct policy_handle *handle)
4885 struct spoolss_DeletePrinter r;
4887 torture_comment(tctx, "Testing DeletePrinter\n");
4889 r.in.handle = handle;
4891 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
4892 "failed to delete printer");
4893 torture_assert_werr_ok(tctx, r.out.result,
4894 "failed to delete printer");
4899 static bool test_EnumPrinters_findname(struct torture_context *tctx,
4900 struct dcerpc_binding_handle *b,
4906 struct spoolss_EnumPrinters e;
4908 union spoolss_PrinterInfo *info;
4919 e.out.count = &count;
4921 e.out.needed = &needed;
4923 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
4924 "failed to enum printers");
4926 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
4927 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
4928 data_blob_clear(&blob);
4929 e.in.buffer = &blob;
4930 e.in.offered = needed;
4932 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
4933 "failed to enum printers");
4936 torture_assert_werr_ok(tctx, e.out.result,
4937 "failed to enum printers");
4939 for (i=0; i < count; i++) {
4941 const char *current = NULL;
4946 current = info[i].info1.name;
4950 if (strequal(current, name)) {
4955 q = strrchr(current, '\\');
4958 torture_warning(tctx,
4959 "server returns printername %s incl. servername although we did not set servername", current);
4962 if (strequal(q, name)) {
4972 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
4973 struct dcerpc_pipe *p,
4974 const char *printername,
4978 struct spoolss_AddPrinter r;
4979 struct spoolss_AddPrinterEx rex;
4980 struct spoolss_SetPrinterInfoCtr info_ctr;
4981 struct spoolss_SetPrinterInfo1 info1;
4982 struct spoolss_DevmodeContainer devmode_ctr;
4983 struct sec_desc_buf secdesc_ctr;
4984 struct spoolss_UserLevelCtr userlevel_ctr;
4985 struct policy_handle handle;
4987 struct dcerpc_binding_handle *b = p->binding_handle;
4989 ZERO_STRUCT(devmode_ctr);
4990 ZERO_STRUCT(secdesc_ctr);
4991 ZERO_STRUCT(userlevel_ctr);
4994 torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
4996 /* try to add printer to wellknown printer list (level 1) */
4998 userlevel_ctr.level = 1;
5000 info_ctr.info.info1 = &info1;
5003 rex.in.server = NULL;
5004 rex.in.info_ctr = &info_ctr;
5005 rex.in.devmode_ctr = &devmode_ctr;
5006 rex.in.secdesc_ctr = &secdesc_ctr;
5007 rex.in.userlevel_ctr = &userlevel_ctr;
5008 rex.out.handle = &handle;
5011 r.in.info_ctr = &info_ctr;
5012 r.in.devmode_ctr = &devmode_ctr;
5013 r.in.secdesc_ctr = &secdesc_ctr;
5014 r.out.handle = &handle;
5016 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5017 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5018 "failed to add printer");
5019 result = ex ? rex.out.result : r.out.result;
5020 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
5021 "unexpected result code");
5023 info1.name = printername;
5024 info1.flags = PRINTER_ATTRIBUTE_SHARED;
5026 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5027 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5028 "failed to add printer");
5029 result = ex ? rex.out.result : r.out.result;
5030 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
5031 "unexpected result code");
5033 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
5034 better do a real check to see the printer is really there */
5036 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
5037 PRINTER_ENUM_NETWORK, 1,
5040 "failed to enum printers");
5042 torture_assert(tctx, found, "failed to find newly added printer");
5046 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5047 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5048 "failed to add printer");
5049 result = ex ? rex.out.result : r.out.result;
5050 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
5051 "unexpected result code");
5053 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
5054 better do a real check to see the printer has really been removed
5055 from the well known printer list */
5059 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
5060 PRINTER_ENUM_NETWORK, 1,
5063 "failed to enum printers");
5065 torture_assert(tctx, !found, "printer still in well known printer list");
5070 static bool test_AddPrinter_normal(struct torture_context *tctx,
5071 struct dcerpc_pipe *p,
5072 struct policy_handle *handle_p,
5073 const char *printername,
5074 const char *drivername,
5075 const char *portname,
5079 struct spoolss_AddPrinter r;
5080 struct spoolss_AddPrinterEx rex;
5081 struct spoolss_SetPrinterInfoCtr info_ctr;
5082 struct spoolss_SetPrinterInfo2 info2;
5083 struct spoolss_DevmodeContainer devmode_ctr;
5084 struct sec_desc_buf secdesc_ctr;
5085 struct spoolss_UserLevelCtr userlevel_ctr;
5086 struct policy_handle handle;
5088 bool existing_printer_deleted = false;
5089 struct dcerpc_binding_handle *b = p->binding_handle;
5091 ZERO_STRUCT(devmode_ctr);
5092 ZERO_STRUCT(secdesc_ctr);
5093 ZERO_STRUCT(userlevel_ctr);
5095 torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
5097 userlevel_ctr.level = 1;
5099 rex.in.server = NULL;
5100 rex.in.info_ctr = &info_ctr;
5101 rex.in.devmode_ctr = &devmode_ctr;
5102 rex.in.secdesc_ctr = &secdesc_ctr;
5103 rex.in.userlevel_ctr = &userlevel_ctr;
5104 rex.out.handle = &handle;
5107 r.in.info_ctr = &info_ctr;
5108 r.in.devmode_ctr = &devmode_ctr;
5109 r.in.secdesc_ctr = &secdesc_ctr;
5110 r.out.handle = &handle;
5114 /* try to add printer to printer list (level 2) */
5118 info_ctr.info.info2 = &info2;
5121 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5122 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5123 "failed to add printer");
5124 result = ex ? rex.out.result : r.out.result;
5125 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
5126 "unexpected result code");
5128 info2.printername = printername;
5130 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5131 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5132 "failed to add printer");
5133 result = ex ? rex.out.result : r.out.result;
5135 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
5136 struct policy_handle printer_handle;
5138 if (existing_printer_deleted) {
5139 torture_fail(tctx, "already deleted printer still existing?");
5142 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
5143 "failed to open printer handle");
5145 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
5146 "failed to delete printer");
5148 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
5149 "failed to close server handle");
5151 existing_printer_deleted = true;
5156 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
5157 "unexpected result code");
5159 info2.portname = portname;
5161 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5162 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5163 "failed to add printer");
5164 result = ex ? rex.out.result : r.out.result;
5165 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
5166 "unexpected result code");
5168 info2.drivername = drivername;
5170 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5171 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5172 "failed to add printer");
5173 result = ex ? rex.out.result : r.out.result;
5175 /* w2k8r2 allows to add printer w/o defining printprocessor */
5177 if (!W_ERROR_IS_OK(result)) {
5178 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
5179 "unexpected result code");
5181 info2.printprocessor = "winprint";
5183 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5184 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5185 "failed to add printer");
5186 result = ex ? rex.out.result : r.out.result;
5187 torture_assert_werr_ok(tctx, result,
5188 "failed to add printer");
5193 /* we are paranoid, really check if the printer is there now */
5195 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
5196 PRINTER_ENUM_LOCAL, 1,
5199 "failed to enum printers");
5200 torture_assert(tctx, found, "failed to find newly added printer");
5202 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
5203 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
5204 "failed to add printer");
5205 result = ex ? rex.out.result : r.out.result;
5206 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
5207 "unexpected result code");
5212 static bool test_AddPrinterEx(struct torture_context *tctx,
5213 struct dcerpc_pipe *p,
5214 struct policy_handle *handle_p,
5215 const char *printername,
5216 const char *drivername,
5217 const char *portname)
5221 if (!torture_setting_bool(tctx, "samba3", false)) {
5222 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
5223 torture_comment(tctx, "failed to add printer to well known list\n");
5228 if (!test_AddPrinter_normal(tctx, p, handle_p,
5229 printername, drivername, portname,
5231 torture_comment(tctx, "failed to add printer to printer list\n");
5238 static bool test_AddPrinter(struct torture_context *tctx,
5239 struct dcerpc_pipe *p,
5240 struct policy_handle *handle_p,
5241 const char *printername,
5242 const char *drivername,
5243 const char *portname)
5247 if (!torture_setting_bool(tctx, "samba3", false)) {
5248 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
5249 torture_comment(tctx, "failed to add printer to well known list\n");
5254 if (!test_AddPrinter_normal(tctx, p, handle_p,
5255 printername, drivername, portname,
5257 torture_comment(tctx, "failed to add printer to printer list\n");
5264 static bool test_printer_info(struct torture_context *tctx,
5265 struct dcerpc_binding_handle *b,
5266 struct policy_handle *handle)
5270 if (torture_setting_bool(tctx, "samba3", false)) {
5271 torture_skip(tctx, "skipping printer info cross tests against samba 3");
5274 if (!test_PrinterInfo(tctx, b, handle)) {
5278 if (!test_SetPrinter_errors(tctx, b, handle)) {
5285 static bool test_EnumPrinterKey(struct torture_context *tctx,
5286 struct dcerpc_binding_handle *b,
5287 struct policy_handle *handle,
5288 const char *key_name,
5289 const char ***array)
5291 struct spoolss_EnumPrinterKey r;
5292 uint32_t needed = 0;
5293 union spoolss_KeyNames key_buffer;
5294 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
5298 r.in.handle = handle;
5299 r.in.key_name = key_name;
5300 r.out.key_buffer = &key_buffer;
5301 r.out.needed = &needed;
5302 r.out._ndr_size = &_ndr_size;
5304 for (i=0; i < ARRAY_SIZE(offered); i++) {
5306 if (offered[i] < 0 && needed) {
5310 r.in.offered = needed + offered[i];
5312 r.in.offered = offered[i];
5315 ZERO_STRUCT(key_buffer);
5317 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
5319 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
5320 "failed to call EnumPrinterKey");
5321 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
5323 torture_assert(tctx, (_ndr_size == r.in.offered/2),
5324 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
5325 _ndr_size, r.in.offered/2));
5327 r.in.offered = needed;
5328 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
5329 "failed to call EnumPrinterKey");
5332 if (offered[i] > 0) {
5333 torture_assert_werr_ok(tctx, r.out.result,
5334 "failed to call EnumPrinterKey");
5337 torture_assert(tctx, (_ndr_size == r.in.offered/2),
5338 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
5339 _ndr_size, r.in.offered/2));
5341 torture_assert(tctx, (*r.out.needed <= r.in.offered),
5342 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
5344 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
5345 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
5347 if (key_buffer.string_array) {
5348 uint32_t calc_needed = 0;
5350 for (s=0; key_buffer.string_array[s]; s++) {
5351 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
5353 if (!key_buffer.string_array[0]) {
5358 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
5359 "EnumPrinterKey unexpected size");
5364 *array = key_buffer.string_array;
5370 bool test_printer_keys(struct torture_context *tctx,
5371 struct dcerpc_binding_handle *b,
5372 struct policy_handle *handle)
5374 const char **key_array = NULL;
5377 torture_comment(tctx, "Testing Printer Keys\n");
5379 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
5380 "failed to call test_EnumPrinterKey");
5382 for (i=0; key_array && key_array[i]; i++) {
5383 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
5384 "failed to call test_EnumPrinterKey");
5386 for (i=0; key_array && key_array[i]; i++) {
5387 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
5388 "failed to call test_EnumPrinterDataEx");
5391 torture_comment(tctx, "Printer Keys test succeeded\n\n");
5396 static bool test_one_printer(struct torture_context *tctx,
5397 struct dcerpc_pipe *p,
5398 struct policy_handle *handle,
5402 struct dcerpc_binding_handle *b = p->binding_handle;
5404 if (!test_PausePrinter(tctx, b, handle)) {
5408 if (!test_DoPrintTest(tctx, b, handle)) {
5412 if (!test_ResumePrinter(tctx, b, handle)) {
5416 if (!test_printer_info(tctx, b, handle)) {
5420 if (!test_PrinterInfo_SD(tctx, b, handle)) {
5424 if (!test_PrinterInfo_DevMode(tctx, p, handle, name)) {
5428 if (!test_ChangeID(tctx, p, handle)) {
5432 if (!test_printer_keys(tctx, b, handle)) {
5436 if (!test_EnumPrinterData_consistency(tctx, p, handle)) {
5440 if (!test_SetPrinterDataEx_matrix(tctx, p, handle, name, NULL, NULL)) {
5444 if (!test_PrinterData_winreg(tctx, p, handle, name)) {
5448 if (!test_printer_rename(tctx, p, handle, name)) {
5455 static bool test_printer(struct torture_context *tctx,
5456 struct dcerpc_pipe *p)
5459 struct policy_handle handle[2];
5461 const char *drivername = "Microsoft XPS Document Writer";
5462 const char *portname = "LPT1:";
5463 struct dcerpc_binding_handle *b = p->binding_handle;
5465 /* test printer created via AddPrinter */
5467 if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
5471 if (!test_one_printer(tctx, p, &handle[0], TORTURE_PRINTER)) {
5475 if (!test_DeletePrinter(tctx, b, &handle[0])) {
5479 if (!test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
5480 TORTURE_PRINTER, &found)) {
5484 torture_assert(tctx, !found, "deleted printer still there");
5486 /* test printer created via AddPrinterEx */
5488 if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
5492 if (!test_one_printer(tctx, p, &handle[1], TORTURE_PRINTER_EX)) {
5496 if (!test_DeletePrinter(tctx, b, &handle[1])) {
5500 if (!test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
5501 TORTURE_PRINTER_EX, &found)) {
5505 torture_assert(tctx, !found, "deleted printer still there");
5510 static bool test_architecture_buffer(struct torture_context *tctx,
5511 struct dcerpc_pipe *p)
5513 struct spoolss_OpenPrinterEx r;
5514 struct spoolss_UserLevel1 u1;
5515 struct policy_handle handle;
5516 uint32_t architectures[] = {
5517 PROCESSOR_ARCHITECTURE_INTEL,
5518 PROCESSOR_ARCHITECTURE_IA64,
5519 PROCESSOR_ARCHITECTURE_AMD64
5523 struct dcerpc_binding_handle *b = p->binding_handle;
5525 for (i=0; i < ARRAY_SIZE(architectures); i++) {
5527 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
5535 u1.processor = architectures[i];
5537 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
5538 r.in.datatype = NULL;
5539 r.in.devmode_ctr.devmode= NULL;
5540 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5542 r.in.userlevel.level1 = &u1;
5543 r.out.handle = &handle;
5545 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
5546 torture_assert_werr_ok(tctx, r.out.result, "");
5549 struct spoolss_EnumPrinters e;
5551 union spoolss_PrinterInfo *info;
5553 e.in.flags = PRINTER_ENUM_LOCAL;
5558 e.out.count = &count;
5560 e.out.needed = &needed[i];
5562 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
5564 torture_comment(tctx, "needed was %d\n", needed[i]);
5568 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
5571 for (i=1; i < ARRAY_SIZE(architectures); i++) {
5572 if (needed[i-1] != needed[i]) {
5574 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
5575 needed[i-1], architectures[i-1], needed[i], architectures[i]));
5582 bool torture_rpc_spoolss(struct torture_context *torture)
5585 struct dcerpc_pipe *p;
5586 struct dcerpc_binding_handle *b;
5588 struct test_spoolss_context *ctx;
5589 const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
5591 status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
5592 if (!NT_STATUS_IS_OK(status)) {
5595 b = p->binding_handle;
5597 ctx = talloc_zero(torture, struct test_spoolss_context);
5599 ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
5600 ret &= test_GetPrinterData_list(torture, p, &ctx->server_handle, &environment);
5601 ret &= test_EnumForms_all(torture, b, &ctx->server_handle, true);
5602 ret &= test_Forms(torture, b, &ctx->server_handle, true, NULL, NULL, NULL);
5603 ret &= test_Forms_winreg(torture, b, &ctx->server_handle, true, NULL);
5604 ret &= test_EnumPorts(torture, b, ctx);
5605 ret &= test_GetPrinterDriverDirectory(torture, p, ctx, environment);
5606 ret &= test_GetPrintProcessorDirectory(torture, p, ctx, environment);
5607 ret &= test_EnumPrinterDrivers(torture, p, ctx, environment);
5608 ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
5609 ret &= test_EnumMonitors(torture, b, ctx);
5610 ret &= test_EnumPrintProcessors(torture, b, ctx, environment);
5611 ret &= test_EnumPrintProcDataTypes(torture, b, ctx);
5612 ret &= test_EnumPrinters(torture, b, ctx);
5613 ret &= test_OpenPrinter_badname(torture, b, "__INVALID_PRINTER__");
5614 ret &= test_OpenPrinter_badname(torture, b, "\\\\__INVALID_HOST__");
5615 ret &= test_OpenPrinter_badname(torture, b, "");
5616 ret &= test_OpenPrinter_badname(torture, b, "\\\\\\");
5617 ret &= test_OpenPrinter_badname(torture, b, "\\\\\\__INVALID_PRINTER__");
5618 ret &= test_OpenPrinter_badname(torture, b, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
5619 ret &= test_OpenPrinter_badname(torture, b,
5620 talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
5623 ret &= test_AddPort(torture, p);
5624 ret &= test_EnumPorts_old(torture, p);
5625 ret &= test_EnumPrinters_old(torture, p, environment);
5626 ret &= test_EnumPrinterDrivers_old(torture, p, environment);
5627 ret &= test_architecture_buffer(torture, p);
5632 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
5634 struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
5636 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
5637 "printer", &ndr_table_spoolss);
5639 torture_rpc_tcase_add_test(tcase, "printer", test_printer);