smbd: Clarify smb2 lock checks
[Samba.git] / source4 / torture / rpc / spoolss.c
blob83933c520869c540e7010436dbef3b0ad5265df5
1 /*
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-2011,2013
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/>.
24 #include "includes.h"
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/torture_rpc.h"
33 #include "param/param.h"
34 #include "lib/registry/registry.h"
35 #include "libcli/libcli.h"
36 #include "libcli/raw/raw_proto.h"
37 #include "libcli/resolve/resolve.h"
38 #include "libcli/smb2/smb2.h"
39 #include "libcli/smb2/smb2_calls.h"
40 #include "lib/cmdline/popt_common.h"
41 #include "system/filesys.h"
42 #include "torture/ndr/ndr.h"
43 #include "torture/smb2/proto.h"
45 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
46 #define TORTURE_PRINTER "torture_printer"
47 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
48 #define TORTURE_PRINTER_EX "torture_printer_ex"
49 #define TORTURE_DRIVER "torture_driver"
50 #define TORTURE_DRIVER_EX "torture_driver_ex"
51 #define TORTURE_DRIVER_ADOBE "torture_driver_adobe"
52 #define TORTURE_DRIVER_EX_ADOBE "torture_driver_ex_adobe"
53 #define TORTURE_DRIVER_ADOBE_CUPSADDSMB "torture_driver_adobe_cupsaddsmb"
54 #define TORTURE_DRIVER_TIMESTAMPS "torture_driver_timestamps"
55 #define TORTURE_DRIVER_DELETER "torture_driver_deleter"
56 #define TORTURE_DRIVER_DELETERIN "torture_driver_deleterin"
57 #define TORTURE_PRINTER_STATIC1 "print1"
59 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
60 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
61 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
62 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
63 #define TOP_LEVEL_CONTROL_PRINTERS_KEY TOP_LEVEL_CONTROL_KEY "\\Printers"
64 #define TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY TOP_LEVEL_CONTROL_KEY "\\Environments"
66 struct test_spoolss_context {
67 struct dcerpc_pipe *spoolss_pipe;
69 /* server environment */
70 const char *environment;
72 /* print server handle */
73 struct policy_handle server_handle;
75 /* for EnumPorts */
76 uint32_t port_count[3];
77 union spoolss_PortInfo *ports[3];
79 /* for EnumPrinterDrivers */
80 uint32_t driver_count[9];
81 union spoolss_DriverInfo *drivers[9];
83 /* for EnumMonitors */
84 uint32_t monitor_count[3];
85 union spoolss_MonitorInfo *monitors[3];
87 /* for EnumPrintProcessors */
88 uint32_t print_processor_count[2];
89 union spoolss_PrintProcessorInfo *print_processors[2];
91 /* for EnumPrinters */
92 uint32_t printer_count[6];
93 union spoolss_PrinterInfo *printers[6];
96 struct torture_driver_context {
97 struct {
98 const char *driver_directory;
99 const char *environment;
100 } local;
101 struct {
102 const char *driver_directory;
103 const char *environment;
104 } remote;
105 struct spoolss_AddDriverInfo8 info8;
106 bool ex;
109 struct torture_printer_context {
110 struct dcerpc_pipe *spoolss_pipe;
111 struct spoolss_SetPrinterInfo2 info2;
112 struct torture_driver_context driver;
113 bool ex;
114 bool wellknown;
115 bool added_driver;
116 bool have_driver;
117 struct spoolss_DeviceMode *devmode;
118 struct policy_handle handle;
121 static bool upload_printer_driver(struct torture_context *tctx,
122 const char *server_name,
123 struct torture_driver_context *d);
124 static bool remove_printer_driver(struct torture_context *tctx,
125 const char *server_name,
126 struct torture_driver_context *d);
127 static bool fillup_printserver_info(struct torture_context *tctx,
128 struct dcerpc_pipe *p,
129 struct torture_driver_context *d);
130 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
131 struct dcerpc_binding_handle *b,
132 const char *server_name,
133 struct spoolss_AddDriverInfo8 *r,
134 uint32_t flags,
135 bool ex,
136 const char *remote_driver_dir);
138 #define COMPARE_STRING(tctx, c,r,e) \
139 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
141 /* not every compiler supports __typeof__() */
142 #if (__GNUC__ >= 3)
143 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
144 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
145 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
147 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
148 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
150 } while(0)
151 #else
152 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
153 #endif
155 #define COMPARE_UINT32(tctx, c, r, e) do {\
156 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
157 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
158 } while(0)
160 #define COMPARE_UINT64(tctx, c, r, e) do {\
161 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
162 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
163 } while(0)
166 #define COMPARE_NTTIME(tctx, c, r, e) do {\
167 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
168 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
169 } while(0)
171 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
172 int __i; \
173 if (!c.e && !r.e) { \
174 break; \
176 if (c.e && !r.e) { \
177 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
179 if (!c.e && r.e) { \
180 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
182 for (__i=0;c.e[__i] != NULL; __i++) { \
183 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
185 } while(0)
187 #define CHECK_ALIGN(size, n) do {\
188 if (size % n) {\
189 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
190 size, n, size + n - (size % n));\
192 } while(0)
194 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
196 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, needed, align) do { \
197 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
198 uint32_t size = ndr_size_##fn##_info(tctx, level, count, info);\
199 uint32_t round_size = DO_ROUND(size, align);\
200 if (round_size != needed) {\
201 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
202 CHECK_ALIGN(size, align);\
205 } while(0)
207 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, needed, align) do { \
208 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
209 uint32_t size = ndr_size_##fn##_info(tctx, count, info);\
210 uint32_t round_size = DO_ROUND(size, align);\
211 if (round_size != needed) {\
212 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
213 CHECK_ALIGN(size, align);\
216 } while(0)
218 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, needed, align) do { \
219 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
220 uint32_t size = ndr_size_##fn(info, level, 0);\
221 uint32_t round_size = DO_ROUND(size, align);\
222 if (round_size != needed) {\
223 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
224 CHECK_ALIGN(size, align);\
227 } while(0)
229 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context *tctx,
230 const union spoolss_PrinterInfo *i,
231 uint32_t level,
232 union spoolss_SetPrinterInfo *s)
234 switch (level) {
235 case 0:
236 s->info0 = talloc(tctx, struct spoolss_SetPrinterInfo0);
237 break;
238 case 2:
239 s->info2 = talloc(tctx, struct spoolss_SetPrinterInfo2);
240 s->info2->servername = i->info2.servername;
241 s->info2->printername = i->info2.printername;
242 s->info2->sharename = i->info2.sharename;
243 s->info2->portname = i->info2.portname;
244 s->info2->drivername = i->info2.drivername;
245 s->info2->comment = i->info2.comment;
246 s->info2->location = i->info2.location;
247 s->info2->devmode_ptr = NULL;
248 s->info2->sepfile = i->info2.sepfile;
249 s->info2->printprocessor = i->info2.printprocessor;
250 s->info2->datatype = i->info2.datatype;
251 s->info2->parameters = i->info2.parameters;
252 s->info2->secdesc_ptr = NULL;
253 s->info2->attributes = i->info2.attributes;
254 s->info2->priority = i->info2.priority;
255 s->info2->defaultpriority = i->info2.defaultpriority;
256 s->info2->starttime = i->info2.starttime;
257 s->info2->untiltime = i->info2.untiltime;
258 s->info2->status = i->info2.status;
259 s->info2->cjobs = i->info2.cjobs;
260 s->info2->averageppm = i->info2.averageppm;
261 break;
262 case 3:
263 case 4:
264 case 5:
265 case 6:
266 case 7:
267 case 8:
268 case 9:
269 default:
270 return false;
273 return true;
276 static bool test_OpenPrinter_server(struct torture_context *tctx,
277 struct dcerpc_pipe *p,
278 struct policy_handle *server_handle)
280 NTSTATUS status;
281 struct spoolss_OpenPrinter op;
282 struct dcerpc_binding_handle *b = p->binding_handle;
284 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
285 op.in.datatype = NULL;
286 op.in.devmode_ctr.devmode= NULL;
287 op.in.access_mask = 0;
288 op.out.handle = server_handle;
290 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
292 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
293 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
294 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
296 return true;
299 static bool test_EnumPorts(struct torture_context *tctx,
300 void *private_data)
302 struct test_spoolss_context *ctx =
303 talloc_get_type_abort(private_data, struct test_spoolss_context);
304 struct dcerpc_pipe *p = ctx->spoolss_pipe;
305 struct dcerpc_binding_handle *b = p->binding_handle;
306 NTSTATUS status;
307 struct spoolss_EnumPorts r;
308 uint16_t levels[] = { 1, 2 };
309 int i, j;
311 for (i=0;i<ARRAY_SIZE(levels);i++) {
312 int level = levels[i];
313 DATA_BLOB blob;
314 uint32_t needed;
315 uint32_t count;
316 union spoolss_PortInfo *info;
318 r.in.servername = "";
319 r.in.level = level;
320 r.in.buffer = NULL;
321 r.in.offered = 0;
322 r.out.needed = &needed;
323 r.out.count = &count;
324 r.out.info = &info;
326 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
328 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
329 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
330 if (W_ERROR_IS_OK(r.out.result)) {
331 /* TODO: do some more checks here */
332 continue;
334 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
335 "EnumPorts unexpected return code");
337 blob = data_blob_talloc_zero(ctx, needed);
338 r.in.buffer = &blob;
339 r.in.offered = needed;
341 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
342 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
344 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
346 torture_assert(tctx, info, "EnumPorts returned no info");
348 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, needed, 4);
350 ctx->port_count[level] = count;
351 ctx->ports[level] = info;
354 for (i=1;i<ARRAY_SIZE(levels);i++) {
355 int level = levels[i];
356 int old_level = levels[i-1];
357 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
358 "EnumPorts invalid value");
360 /* if the array sizes are not the same we would maybe segfault in the following code */
362 for (i=0;i<ARRAY_SIZE(levels);i++) {
363 int level = levels[i];
364 for (j=0;j<ctx->port_count[level];j++) {
365 union spoolss_PortInfo *cur = &ctx->ports[level][j];
366 union spoolss_PortInfo *ref = &ctx->ports[2][j];
367 switch (level) {
368 case 1:
369 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
370 break;
371 case 2:
372 /* level 2 is our reference, and it makes no sense to compare it to itself */
373 break;
378 return true;
381 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
382 void *private_data)
384 struct test_spoolss_context *ctx =
385 talloc_get_type_abort(private_data, struct test_spoolss_context);
387 NTSTATUS status;
388 struct dcerpc_pipe *p = ctx->spoolss_pipe;
389 struct dcerpc_binding_handle *b = p->binding_handle;
390 struct spoolss_GetPrintProcessorDirectory r;
391 struct {
392 uint16_t level;
393 const char *server;
394 } levels[] = {{
395 .level = 1,
396 .server = NULL
398 .level = 1,
399 .server = ""
401 .level = 78,
402 .server = ""
404 .level = 1,
405 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
407 .level = 1024,
408 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
411 int i;
412 uint32_t needed;
414 for (i=0;i<ARRAY_SIZE(levels);i++) {
415 int level = levels[i].level;
416 DATA_BLOB blob;
418 r.in.server = levels[i].server;
419 r.in.environment = ctx->environment;
420 r.in.level = level;
421 r.in.buffer = NULL;
422 r.in.offered = 0;
423 r.out.needed = &needed;
425 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
427 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
428 torture_assert_ntstatus_ok(tctx, status,
429 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
430 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
431 "GetPrintProcessorDirectory unexpected return code");
433 blob = data_blob_talloc_zero(tctx, needed);
434 r.in.buffer = &blob;
435 r.in.offered = needed;
437 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
438 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
440 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
442 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, needed, 2);
445 return true;
449 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
450 void *private_data)
452 struct test_spoolss_context *ctx =
453 talloc_get_type_abort(private_data, struct test_spoolss_context);
455 NTSTATUS status;
456 struct dcerpc_pipe *p = ctx->spoolss_pipe;
457 struct dcerpc_binding_handle *b = p->binding_handle;
458 struct spoolss_GetPrinterDriverDirectory r;
459 struct {
460 uint16_t level;
461 const char *server;
462 } levels[] = {{
463 .level = 1,
464 .server = NULL
466 .level = 1,
467 .server = ""
469 .level = 78,
470 .server = ""
472 .level = 1,
473 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
475 .level = 1024,
476 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
479 int i;
480 uint32_t needed;
482 for (i=0;i<ARRAY_SIZE(levels);i++) {
483 int level = levels[i].level;
484 DATA_BLOB blob;
486 r.in.server = levels[i].server;
487 r.in.environment = ctx->environment;
488 r.in.level = level;
489 r.in.buffer = NULL;
490 r.in.offered = 0;
491 r.out.needed = &needed;
493 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
495 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
496 torture_assert_ntstatus_ok(tctx, status,
497 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
498 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
499 "GetPrinterDriverDirectory unexpected return code");
501 blob = data_blob_talloc_zero(tctx, needed);
502 r.in.buffer = &blob;
503 r.in.offered = needed;
505 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
506 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
508 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
510 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, needed, 2);
513 return true;
516 static bool test_EnumPrinterDrivers_buffers(struct torture_context *tctx,
517 struct dcerpc_binding_handle *b,
518 const char *server_name,
519 const char *environment,
520 uint32_t level,
521 uint32_t offered,
522 uint32_t *count_p,
523 union spoolss_DriverInfo **info_p)
525 struct spoolss_EnumPrinterDrivers r;
526 uint32_t needed;
527 uint32_t count;
528 union spoolss_DriverInfo *info;
529 DATA_BLOB buffer;
531 if (offered > 0) {
532 buffer = data_blob_talloc_zero(tctx, offered);
535 r.in.server = server_name;
536 r.in.environment = environment;
537 r.in.level = level;
538 r.in.buffer = offered ? &buffer : NULL;
539 r.in.offered = offered;
540 r.out.needed = &needed;
541 r.out.count = &count;
542 r.out.info = &info;
544 torture_comment(tctx, "Testing EnumPrinterDrivers(%s) level %u, offered: %u\n",
545 r.in.environment, r.in.level, r.in.offered);
547 torture_assert_ntstatus_ok(tctx,
548 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
549 "EnumPrinterDrivers failed");
550 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
551 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
552 r.in.buffer = &blob;
553 r.in.offered = needed;
555 torture_assert_ntstatus_ok(tctx,
556 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
557 "EnumPrinterDrivers failed");
560 torture_assert_werr_ok(tctx, r.out.result,
561 "EnumPrinterDrivers failed");
563 if (count_p) {
564 *count_p = count;
566 if (info_p) {
567 *info_p = info;
570 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, needed, 4);
572 return true;
577 static bool test_EnumPrinterDrivers_args(struct torture_context *tctx,
578 struct dcerpc_binding_handle *b,
579 const char *server_name,
580 const char *environment,
581 uint32_t level,
582 uint32_t *count_p,
583 union spoolss_DriverInfo **info_p)
585 return test_EnumPrinterDrivers_buffers(tctx, b, server_name,
586 environment, level, 0,
587 count_p, info_p);
590 static bool test_EnumPrinterDrivers_findone(struct torture_context *tctx,
591 struct dcerpc_binding_handle *b,
592 const char *server_name,
593 const char *environment,
594 uint32_t level,
595 const char *driver_name,
596 union spoolss_DriverInfo *info_p)
598 uint32_t count;
599 union spoolss_DriverInfo *info;
600 int i;
601 const char *environment_ret = NULL;
603 torture_assert(tctx,
604 test_EnumPrinterDrivers_args(tctx, b, server_name, environment, level, &count, &info),
605 "failed to enumerate printer drivers");
607 for (i=0; i < count; i++) {
608 const char *driver_name_ret = "";
609 switch (level) {
610 case 1:
611 driver_name_ret = info[i].info1.driver_name;
612 break;
613 case 2:
614 driver_name_ret = info[i].info2.driver_name;
615 environment_ret = info[i].info2.architecture;
616 break;
617 case 3:
618 driver_name_ret = info[i].info3.driver_name;
619 environment_ret = info[i].info3.architecture;
620 break;
621 case 4:
622 driver_name_ret = info[i].info4.driver_name;
623 environment_ret = info[i].info4.architecture;
624 break;
625 case 5:
626 driver_name_ret = info[i].info5.driver_name;
627 environment_ret = info[i].info5.architecture;
628 break;
629 case 6:
630 driver_name_ret = info[i].info6.driver_name;
631 environment_ret = info[i].info6.architecture;
632 break;
633 case 7:
634 driver_name_ret = info[i].info7.driver_name;
635 break;
636 case 8:
637 driver_name_ret = info[i].info8.driver_name;
638 environment_ret = info[i].info8.architecture;
639 break;
640 default:
641 break;
643 if (environment_ret) {
644 torture_assert_str_equal(tctx, environment, environment_ret, "architecture mismatch");
646 if (strequal(driver_name, driver_name_ret)) {
647 if (info_p) {
648 *info_p = info[i];
650 return true;
654 return false;
657 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
658 void *private_data)
660 struct test_spoolss_context *ctx =
661 talloc_get_type_abort(private_data, struct test_spoolss_context);
662 struct dcerpc_pipe *p = ctx->spoolss_pipe;
663 struct dcerpc_binding_handle *b = p->binding_handle;
664 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
665 uint16_t buffer_sizes[] = { 0, 1024, 6040, 0xffff };
666 int i, j, a;
668 /* FIXME: gd, come back and fix "" as server, and handle
669 * priority of returned error codes in torture test and samba 3
670 * server */
671 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
672 const char *environments[2];
674 environments[0] = SPOOLSS_ARCHITECTURE_ALL;
675 environments[1] = ctx->environment;
677 for (a=0;a<ARRAY_SIZE(environments);a++) {
679 for (i=0;i<ARRAY_SIZE(buffer_sizes);i++) {
680 torture_assert(tctx,
681 test_EnumPrinterDrivers_buffers(tctx, b, server_name,
682 environments[a], 3,
683 buffer_sizes[i],
684 NULL, NULL),
685 "failed to enumerate drivers");
688 for (i=0;i<ARRAY_SIZE(levels);i++) {
689 int level = levels[i];
690 uint32_t count;
691 union spoolss_DriverInfo *info;
693 torture_assert(tctx,
694 test_EnumPrinterDrivers_args(tctx, b, server_name, environments[a], level, &count, &info),
695 "failed to enumerate drivers");
697 ctx->driver_count[level] = count;
698 ctx->drivers[level] = info;
701 for (i=1;i<ARRAY_SIZE(levels);i++) {
702 int level = levels[i];
703 int old_level = levels[i-1];
705 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
706 "EnumPrinterDrivers invalid value");
709 for (i=0;i<ARRAY_SIZE(levels);i++) {
710 int level = levels[i];
712 for (j=0;j<ctx->driver_count[level - 1];j++) {
713 union spoolss_DriverInfo *cur = &ctx->drivers[level - 1][j];
714 union spoolss_DriverInfo *ref = &ctx->drivers[7][j];
716 switch (level) {
717 case 1:
718 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
719 break;
720 case 2:
721 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
722 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
723 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
724 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
725 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
726 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
727 break;
728 case 3:
729 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
730 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
731 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
732 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
733 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
734 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
735 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
736 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
737 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
738 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
739 break;
740 case 4:
741 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
742 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
743 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
744 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
745 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
746 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
747 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
748 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
749 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
750 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
751 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
752 break;
753 case 5:
754 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
755 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
756 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
757 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
758 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
759 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
760 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
761 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
762 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
763 break;
764 case 6:
765 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
766 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
767 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
768 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
769 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
770 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
771 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
772 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
773 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
774 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
775 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
776 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
777 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
778 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
779 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
780 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
781 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
782 break;
783 case 8:
784 /* level 8 is our reference, and it makes no sense to compare it to itself */
785 break;
791 return true;
794 static bool test_EnumMonitors(struct torture_context *tctx,
795 void *private_data)
797 struct test_spoolss_context *ctx =
798 talloc_get_type_abort(private_data, struct test_spoolss_context);
799 struct dcerpc_pipe *p = ctx->spoolss_pipe;
800 struct dcerpc_binding_handle *b = p->binding_handle;
801 NTSTATUS status;
802 struct spoolss_EnumMonitors r;
803 uint16_t levels[] = { 1, 2 };
804 int i, j;
806 for (i=0;i<ARRAY_SIZE(levels);i++) {
807 int level = levels[i];
808 DATA_BLOB blob;
809 uint32_t needed;
810 uint32_t count;
811 union spoolss_MonitorInfo *info;
813 r.in.servername = "";
814 r.in.level = level;
815 r.in.buffer = NULL;
816 r.in.offered = 0;
817 r.out.needed = &needed;
818 r.out.count = &count;
819 r.out.info = &info;
821 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
823 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
824 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
825 if (W_ERROR_IS_OK(r.out.result)) {
826 /* TODO: do some more checks here */
827 continue;
829 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
830 "EnumMonitors failed");
832 blob = data_blob_talloc_zero(ctx, needed);
833 r.in.buffer = &blob;
834 r.in.offered = needed;
836 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
837 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
839 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
841 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, needed, 4);
843 ctx->monitor_count[level] = count;
844 ctx->monitors[level] = info;
847 for (i=1;i<ARRAY_SIZE(levels);i++) {
848 int level = levels[i];
849 int old_level = levels[i-1];
850 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
851 "EnumMonitors invalid value");
854 for (i=0;i<ARRAY_SIZE(levels);i++) {
855 int level = levels[i];
856 for (j=0;j<ctx->monitor_count[level];j++) {
857 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
858 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
859 switch (level) {
860 case 1:
861 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
862 break;
863 case 2:
864 /* level 2 is our reference, and it makes no sense to compare it to itself */
865 break;
870 return true;
873 static bool test_EnumPrintProcessors_level(struct torture_context *tctx,
874 struct dcerpc_binding_handle *b,
875 const char *environment,
876 uint32_t level,
877 uint32_t *count_p,
878 union spoolss_PrintProcessorInfo **info_p,
879 WERROR expected_result)
881 struct spoolss_EnumPrintProcessors r;
882 DATA_BLOB blob;
883 uint32_t needed;
884 uint32_t count;
885 union spoolss_PrintProcessorInfo *info;
887 r.in.servername = "";
888 r.in.environment = environment;
889 r.in.level = level;
890 r.in.buffer = NULL;
891 r.in.offered = 0;
892 r.out.needed = &needed;
893 r.out.count = &count;
894 r.out.info = &info;
896 torture_comment(tctx, "Testing EnumPrintProcessors(%s) level %u\n",
897 r.in.environment, r.in.level);
899 torture_assert_ntstatus_ok(tctx,
900 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
901 "EnumPrintProcessors failed");
902 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
903 blob = data_blob_talloc_zero(tctx, needed);
904 r.in.buffer = &blob;
905 r.in.offered = needed;
906 torture_assert_ntstatus_ok(tctx,
907 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
908 "EnumPrintProcessors failed");
910 torture_assert_werr_equal(tctx, r.out.result, expected_result,
911 "EnumPrintProcessors failed");
913 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, level, count, needed, 4);
915 if (count_p) {
916 *count_p = count;
918 if (info_p) {
919 *info_p = info;
922 return true;
925 static bool test_EnumPrintProcessors(struct torture_context *tctx,
926 void *private_data)
928 struct test_spoolss_context *ctx =
929 talloc_get_type_abort(private_data, struct test_spoolss_context);
931 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
932 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
933 int i;
934 struct dcerpc_pipe *p = ctx->spoolss_pipe;
935 struct dcerpc_binding_handle *b = p->binding_handle;
937 torture_assert(tctx,
938 test_EnumPrintProcessors_level(tctx, b, "phantasy", 1, NULL, NULL, WERR_INVALID_ENVIRONMENT),
939 "test_EnumPrintProcessors_level failed");
941 for (i=0;i<ARRAY_SIZE(levels);i++) {
942 union spoolss_PrintProcessorInfo *info;
943 uint32_t count;
944 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
946 torture_assert(tctx,
947 test_EnumPrintProcessors_level(tctx, b, ctx->environment, levels[i], &count, &info, expected_result),
948 "test_EnumPrintProcessors_level failed");
951 return true;
954 static bool test_EnumPrintProcDataTypes_level(struct torture_context *tctx,
955 struct dcerpc_binding_handle *b,
956 const char *print_processor_name,
957 uint32_t level,
958 uint32_t *count_p,
959 union spoolss_PrintProcDataTypesInfo **info_p,
960 WERROR expected_result)
962 struct spoolss_EnumPrintProcDataTypes r;
963 DATA_BLOB blob;
964 uint32_t needed;
965 uint32_t count;
966 union spoolss_PrintProcDataTypesInfo *info;
968 r.in.servername = "";
969 r.in.print_processor_name = print_processor_name;
970 r.in.level = level;
971 r.in.buffer = NULL;
972 r.in.offered = 0;
973 r.out.needed = &needed;
974 r.out.count = &count;
975 r.out.info = &info;
977 torture_comment(tctx, "Testing EnumPrintProcDataTypes(%s) level %u\n",
978 r.in.print_processor_name, r.in.level);
980 torture_assert_ntstatus_ok(tctx,
981 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
982 "EnumPrintProcDataTypes failed");
983 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
984 blob = data_blob_talloc_zero(tctx, needed);
985 r.in.buffer = &blob;
986 r.in.offered = needed;
987 torture_assert_ntstatus_ok(tctx,
988 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
989 "EnumPrintProcDataTypes failed");
991 torture_assert_werr_equal(tctx, r.out.result, expected_result,
992 "EnumPrintProcDataTypes failed");
994 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, level, count, needed, 4);
996 if (count_p) {
997 *count_p = count;
999 if (info_p) {
1000 *info_p = info;
1003 return true;
1006 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
1007 void *private_data)
1009 struct test_spoolss_context *ctx =
1010 talloc_get_type_abort(private_data, struct test_spoolss_context);
1012 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
1013 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
1014 int i;
1015 struct dcerpc_pipe *p = ctx->spoolss_pipe;
1016 struct dcerpc_binding_handle *b = p->binding_handle;
1018 torture_assert(tctx,
1019 test_EnumPrintProcDataTypes_level(tctx, b, NULL, 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
1020 "test_EnumPrintProcDataTypes_level failed");
1022 torture_assert(tctx,
1023 test_EnumPrintProcDataTypes_level(tctx, b, "nonexisting", 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
1024 "test_EnumPrintProcDataTypes_level failed");
1026 for (i=0;i<ARRAY_SIZE(levels);i++) {
1027 int level = levels[i];
1028 uint32_t count;
1029 union spoolss_PrintProcDataTypesInfo *info;
1030 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
1032 torture_assert(tctx,
1033 test_EnumPrintProcDataTypes_level(tctx, b, "winprint", level, &count, &info, expected_result),
1034 "test_EnumPrintProcDataTypes_level failed");
1038 union spoolss_PrintProcessorInfo *info;
1039 uint32_t count;
1041 torture_assert(tctx,
1042 test_EnumPrintProcessors_level(tctx, b, ctx->environment, 1, &count, &info, WERR_OK),
1043 "test_EnumPrintProcessors_level failed");
1045 for (i=0; i < count; i++) {
1046 torture_assert(tctx,
1047 test_EnumPrintProcDataTypes_level(tctx, b, info[i].info1.print_processor_name, 1, NULL, NULL, WERR_OK),
1048 "test_EnumPrintProcDataTypes_level failed");
1053 return true;
1056 static bool test_EnumPrinters(struct torture_context *tctx,
1057 void *private_data)
1059 struct test_spoolss_context *ctx =
1060 talloc_get_type_abort(private_data, struct test_spoolss_context);
1061 struct dcerpc_pipe *p = ctx->spoolss_pipe;
1062 struct dcerpc_binding_handle *b = p->binding_handle;
1063 struct spoolss_EnumPrinters r;
1064 NTSTATUS status;
1065 uint16_t levels[] = { 0, 1, 2, 4, 5 };
1066 int i, j;
1068 for (i=0;i<ARRAY_SIZE(levels);i++) {
1069 int level = levels[i];
1070 DATA_BLOB blob;
1071 uint32_t needed;
1072 uint32_t count;
1073 union spoolss_PrinterInfo *info;
1075 r.in.flags = PRINTER_ENUM_LOCAL;
1076 r.in.server = "";
1077 r.in.level = level;
1078 r.in.buffer = NULL;
1079 r.in.offered = 0;
1080 r.out.needed = &needed;
1081 r.out.count = &count;
1082 r.out.info = &info;
1084 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1086 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1087 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1088 if (W_ERROR_IS_OK(r.out.result)) {
1089 /* TODO: do some more checks here */
1090 continue;
1092 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
1093 "EnumPrinters unexpected return code");
1095 blob = data_blob_talloc_zero(ctx, needed);
1096 r.in.buffer = &blob;
1097 r.in.offered = needed;
1099 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1100 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1102 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1104 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
1106 ctx->printer_count[level] = count;
1107 ctx->printers[level] = info;
1110 for (i=1;i<ARRAY_SIZE(levels);i++) {
1111 int level = levels[i];
1112 int old_level = levels[i-1];
1113 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
1114 "EnumPrinters invalid value");
1117 for (i=0;i<ARRAY_SIZE(levels);i++) {
1118 int level = levels[i];
1119 for (j=0;j<ctx->printer_count[level];j++) {
1120 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
1121 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
1122 switch (level) {
1123 case 0:
1124 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
1125 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
1126 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
1127 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
1128 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
1129 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
1130 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
1131 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
1132 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
1133 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
1134 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
1135 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
1136 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
1137 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
1138 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
1139 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
1140 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
1141 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
1142 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
1143 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
1144 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
1145 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
1146 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
1147 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
1148 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
1149 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
1150 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
1151 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
1152 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
1153 break;
1154 case 1:
1155 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
1156 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
1157 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
1158 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
1159 break;
1160 case 2:
1161 /* level 2 is our reference, and it makes no sense to compare it to itself */
1162 break;
1163 case 4:
1164 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
1165 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
1166 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
1167 break;
1168 case 5:
1169 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
1170 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
1171 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
1172 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
1173 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
1174 break;
1179 /* TODO:
1180 * - verify that the port of a printer was in the list returned by EnumPorts
1183 return true;
1186 static bool test_GetPrinterDriver2(struct torture_context *tctx,
1187 struct dcerpc_binding_handle *b,
1188 struct policy_handle *handle,
1189 const char *driver_name,
1190 const char *environment);
1192 bool test_GetPrinter_level(struct torture_context *tctx,
1193 struct dcerpc_binding_handle *b,
1194 struct policy_handle *handle,
1195 uint32_t level,
1196 union spoolss_PrinterInfo *info)
1198 struct spoolss_GetPrinter r;
1199 uint32_t needed;
1201 r.in.handle = handle;
1202 r.in.level = level;
1203 r.in.buffer = NULL;
1204 r.in.offered = 0;
1205 r.out.needed = &needed;
1207 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
1209 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1210 "GetPrinter failed");
1212 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1213 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
1214 r.in.buffer = &blob;
1215 r.in.offered = needed;
1217 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1218 "GetPrinter failed");
1221 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
1223 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, needed, 4);
1225 if (info && r.out.info) {
1226 *info = *r.out.info;
1229 return true;
1233 static bool test_GetPrinter(struct torture_context *tctx,
1234 struct dcerpc_binding_handle *b,
1235 struct policy_handle *handle,
1236 const char *environment)
1238 uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1239 int i;
1241 for (i=0;i<ARRAY_SIZE(levels);i++) {
1243 union spoolss_PrinterInfo info;
1245 ZERO_STRUCT(info);
1247 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
1248 "failed to call GetPrinter");
1250 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
1251 torture_assert(tctx,
1252 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
1253 "failed to call test_GetPrinterDriver2");
1257 return true;
1260 static bool test_SetPrinter(struct torture_context *tctx,
1261 struct dcerpc_binding_handle *b,
1262 struct policy_handle *handle,
1263 struct spoolss_SetPrinterInfoCtr *info_ctr,
1264 struct spoolss_DevmodeContainer *devmode_ctr,
1265 struct sec_desc_buf *secdesc_ctr,
1266 enum spoolss_PrinterControl command)
1268 struct spoolss_SetPrinter r;
1270 r.in.handle = handle;
1271 r.in.info_ctr = info_ctr;
1272 r.in.devmode_ctr = devmode_ctr;
1273 r.in.secdesc_ctr = secdesc_ctr;
1274 r.in.command = command;
1276 torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1278 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1279 "failed to call SetPrinter");
1280 torture_assert(tctx, (W_ERROR_EQUAL(r.out.result, WERR_OK)
1281 || W_ERROR_EQUAL(r.out.result, WERR_IO_PENDING)),
1282 "SetPrinter failed");
1284 return true;
1287 static bool test_SetPrinter_errors(struct torture_context *tctx,
1288 struct dcerpc_binding_handle *b,
1289 struct policy_handle *handle)
1291 struct spoolss_SetPrinter r;
1292 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1293 int i;
1295 struct spoolss_SetPrinterInfoCtr info_ctr;
1296 struct spoolss_DevmodeContainer devmode_ctr;
1297 struct sec_desc_buf secdesc_ctr;
1299 info_ctr.level = 0;
1300 info_ctr.info.info0 = NULL;
1302 ZERO_STRUCT(devmode_ctr);
1303 ZERO_STRUCT(secdesc_ctr);
1305 r.in.handle = handle;
1306 r.in.info_ctr = &info_ctr;
1307 r.in.devmode_ctr = &devmode_ctr;
1308 r.in.secdesc_ctr = &secdesc_ctr;
1309 r.in.command = 0;
1311 torture_comment(tctx, "Testing SetPrinter all zero\n");
1313 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1314 "failed to call SetPrinter");
1315 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1316 "failed to call SetPrinter");
1318 again:
1319 for (i=0; i < ARRAY_SIZE(levels); i++) {
1321 struct spoolss_SetPrinterInfo0 info0;
1322 struct spoolss_SetPrinterInfo1 info1;
1323 struct spoolss_SetPrinterInfo2 info2;
1324 struct spoolss_SetPrinterInfo3 info3;
1325 struct spoolss_SetPrinterInfo4 info4;
1326 struct spoolss_SetPrinterInfo5 info5;
1327 struct spoolss_SetPrinterInfo6 info6;
1328 struct spoolss_SetPrinterInfo7 info7;
1329 struct spoolss_SetPrinterInfo8 info8;
1330 struct spoolss_SetPrinterInfo9 info9;
1333 info_ctr.level = levels[i];
1334 switch (levels[i]) {
1335 case 0:
1336 ZERO_STRUCT(info0);
1337 info_ctr.info.info0 = &info0;
1338 break;
1339 case 1:
1340 ZERO_STRUCT(info1);
1341 info_ctr.info.info1 = &info1;
1342 break;
1343 case 2:
1344 ZERO_STRUCT(info2);
1345 info_ctr.info.info2 = &info2;
1346 break;
1347 case 3:
1348 ZERO_STRUCT(info3);
1349 info_ctr.info.info3 = &info3;
1350 break;
1351 case 4:
1352 ZERO_STRUCT(info4);
1353 info_ctr.info.info4 = &info4;
1354 break;
1355 case 5:
1356 ZERO_STRUCT(info5);
1357 info_ctr.info.info5 = &info5;
1358 break;
1359 case 6:
1360 ZERO_STRUCT(info6);
1361 info_ctr.info.info6 = &info6;
1362 break;
1363 case 7:
1364 ZERO_STRUCT(info7);
1365 info_ctr.info.info7 = &info7;
1366 break;
1367 case 8:
1368 ZERO_STRUCT(info8);
1369 info_ctr.info.info8 = &info8;
1370 break;
1371 case 9:
1372 ZERO_STRUCT(info9);
1373 info_ctr.info.info9 = &info9;
1374 break;
1377 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1378 info_ctr.level, r.in.command);
1380 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1381 "failed to call SetPrinter");
1383 switch (r.in.command) {
1384 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1385 /* is ignored for all levels other then 0 */
1386 if (info_ctr.level > 0) {
1387 /* ignored then */
1388 break;
1390 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1391 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1392 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1393 if (info_ctr.level > 0) {
1394 /* is invalid for all levels other then 0 */
1395 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1396 "unexpected error code returned");
1397 continue;
1398 } else {
1399 torture_assert_werr_ok(tctx, r.out.result,
1400 "failed to call SetPrinter with non 0 command");
1401 continue;
1403 break;
1405 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1406 /* FIXME: gd needs further investigation */
1407 default:
1408 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1409 "unexpected error code returned");
1410 continue;
1413 switch (info_ctr.level) {
1414 case 1:
1415 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1416 "unexpected error code returned");
1417 break;
1418 case 2:
1419 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1420 "unexpected error code returned");
1421 break;
1422 case 3:
1423 case 4:
1424 case 5:
1425 case 7:
1426 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1427 "unexpected error code returned");
1428 break;
1429 case 9:
1430 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1431 "unexpected error code returned");
1432 break;
1433 default:
1434 torture_assert_werr_ok(tctx, r.out.result,
1435 "failed to call SetPrinter");
1436 break;
1440 if (r.in.command < 5) {
1441 r.in.command++;
1442 goto again;
1445 return true;
1448 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1450 if ((r->level == 2) && (r->info.info2)) {
1451 r->info.info2->secdesc_ptr = NULL;
1452 r->info.info2->devmode_ptr = NULL;
1456 static bool test_PrinterInfo(struct torture_context *tctx,
1457 struct dcerpc_binding_handle *b,
1458 struct policy_handle *handle)
1460 NTSTATUS status;
1461 struct spoolss_SetPrinter s;
1462 struct spoolss_GetPrinter q;
1463 struct spoolss_GetPrinter q0;
1464 struct spoolss_SetPrinterInfoCtr info_ctr;
1465 union spoolss_PrinterInfo info;
1466 struct spoolss_DevmodeContainer devmode_ctr;
1467 struct sec_desc_buf secdesc_ctr;
1468 uint32_t needed;
1469 bool ret = true;
1470 int i;
1472 uint32_t status_list[] = {
1473 /* these do not stick
1474 PRINTER_STATUS_PAUSED,
1475 PRINTER_STATUS_ERROR,
1476 PRINTER_STATUS_PENDING_DELETION, */
1477 PRINTER_STATUS_PAPER_JAM,
1478 PRINTER_STATUS_PAPER_OUT,
1479 PRINTER_STATUS_MANUAL_FEED,
1480 PRINTER_STATUS_PAPER_PROBLEM,
1481 PRINTER_STATUS_OFFLINE,
1482 PRINTER_STATUS_IO_ACTIVE,
1483 PRINTER_STATUS_BUSY,
1484 PRINTER_STATUS_PRINTING,
1485 PRINTER_STATUS_OUTPUT_BIN_FULL,
1486 PRINTER_STATUS_NOT_AVAILABLE,
1487 PRINTER_STATUS_WAITING,
1488 PRINTER_STATUS_PROCESSING,
1489 PRINTER_STATUS_INITIALIZING,
1490 PRINTER_STATUS_WARMING_UP,
1491 PRINTER_STATUS_TONER_LOW,
1492 PRINTER_STATUS_NO_TONER,
1493 PRINTER_STATUS_PAGE_PUNT,
1494 PRINTER_STATUS_USER_INTERVENTION,
1495 PRINTER_STATUS_OUT_OF_MEMORY,
1496 PRINTER_STATUS_DOOR_OPEN,
1497 PRINTER_STATUS_SERVER_UNKNOWN,
1498 PRINTER_STATUS_POWER_SAVE,
1499 /* these do not stick
1500 0x02000000,
1501 0x04000000,
1502 0x08000000,
1503 0x10000000,
1504 0x20000000,
1505 0x40000000,
1506 0x80000000 */
1508 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1509 uint32_t attribute_list[] = {
1510 PRINTER_ATTRIBUTE_QUEUED,
1511 /* fails with WERR_INVALID_DATATYPE:
1512 PRINTER_ATTRIBUTE_DIRECT, */
1513 /* does not stick
1514 PRINTER_ATTRIBUTE_DEFAULT, */
1515 PRINTER_ATTRIBUTE_SHARED,
1516 /* does not stick
1517 PRINTER_ATTRIBUTE_NETWORK, */
1518 PRINTER_ATTRIBUTE_HIDDEN,
1519 PRINTER_ATTRIBUTE_LOCAL,
1520 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1521 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1522 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1523 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1524 /* does not stick
1525 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1526 /* fails with WERR_INVALID_DATATYPE:
1527 PRINTER_ATTRIBUTE_RAW_ONLY, */
1528 /* these do not stick
1529 PRINTER_ATTRIBUTE_PUBLISHED,
1530 PRINTER_ATTRIBUTE_FAX,
1531 PRINTER_ATTRIBUTE_TS,
1532 0x00010000,
1533 0x00020000,
1534 0x00040000,
1535 0x00080000,
1536 0x00100000,
1537 0x00200000,
1538 0x00400000,
1539 0x00800000,
1540 0x01000000,
1541 0x02000000,
1542 0x04000000,
1543 0x08000000,
1544 0x10000000,
1545 0x20000000,
1546 0x40000000,
1547 0x80000000 */
1550 torture_skip(tctx, "Printer Info test is currently broken, skipping");
1553 ZERO_STRUCT(devmode_ctr);
1554 ZERO_STRUCT(secdesc_ctr);
1556 s.in.handle = handle;
1557 s.in.command = 0;
1558 s.in.info_ctr = &info_ctr;
1559 s.in.devmode_ctr = &devmode_ctr;
1560 s.in.secdesc_ctr = &secdesc_ctr;
1562 q.in.handle = handle;
1563 q.out.info = &info;
1564 q0 = q;
1566 #define TESTGETCALL(call, r) \
1567 r.in.buffer = NULL; \
1568 r.in.offered = 0;\
1569 r.out.needed = &needed; \
1570 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1571 if (!NT_STATUS_IS_OK(status)) { \
1572 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1573 r.in.level, nt_errstr(status), __location__); \
1574 ret = false; \
1575 break; \
1577 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1578 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1579 r.in.buffer = &blob; \
1580 r.in.offered = needed; \
1582 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1583 if (!NT_STATUS_IS_OK(status)) { \
1584 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1585 r.in.level, nt_errstr(status), __location__); \
1586 ret = false; \
1587 break; \
1589 if (!W_ERROR_IS_OK(r.out.result)) { \
1590 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1591 r.in.level, win_errstr(r.out.result), __location__); \
1592 ret = false; \
1593 break; \
1597 #define TESTSETCALL_EXP(call, r, err) \
1598 clear_info2(&info_ctr);\
1599 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1600 if (!NT_STATUS_IS_OK(status)) { \
1601 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1602 r.in.info_ctr->level, nt_errstr(status), __location__); \
1603 ret = false; \
1604 break; \
1606 if (!W_ERROR_IS_OK(err)) { \
1607 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1608 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1609 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1610 ret = false; \
1612 break; \
1614 if (!W_ERROR_IS_OK(r.out.result)) { \
1615 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1616 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1617 ret = false; \
1618 break; \
1621 #define TESTSETCALL(call, r) \
1622 TESTSETCALL_EXP(call, r, WERR_OK)
1624 #define STRING_EQUAL(s1, s2, field) \
1625 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1626 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1627 #field, s2, __location__); \
1628 ret = false; \
1629 break; \
1632 #define MEM_EQUAL(s1, s2, length, field) \
1633 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1634 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1635 #field, (const char *)s2, __location__); \
1636 ret = false; \
1637 break; \
1640 #define INT_EQUAL(i1, i2, field) \
1641 if (i1 != i2) { \
1642 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1643 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1644 ret = false; \
1645 break; \
1648 #define SD_EQUAL(sd1, sd2, field) \
1649 if (!security_descriptor_equal(sd1, sd2)) { \
1650 torture_comment(tctx, "Failed to set %s (%s)\n", \
1651 #field, __location__); \
1652 ret = false; \
1653 break; \
1656 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1657 void *p; \
1658 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1659 q.in.level = lvl1; \
1660 TESTGETCALL(GetPrinter, q) \
1661 info_ctr.level = lvl1; \
1662 p = (void *)&q.out.info->info ## lvl1; \
1663 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
1664 info_ctr.info.info ## lvl1->field1 = value;\
1665 TESTSETCALL_EXP(SetPrinter, s, err) \
1666 info_ctr.info.info ## lvl1->field1 = ""; \
1667 TESTGETCALL(GetPrinter, q) \
1668 info_ctr.info.info ## lvl1->field1 = value; \
1669 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1670 q.in.level = lvl2; \
1671 TESTGETCALL(GetPrinter, q) \
1672 p = (void *)&q.out.info->info ## lvl2; \
1673 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)p; \
1674 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1675 } while (0)
1677 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1678 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1679 } while (0);
1681 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1682 void *p; \
1683 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1684 q.in.level = lvl1; \
1685 TESTGETCALL(GetPrinter, q) \
1686 info_ctr.level = lvl1; \
1687 p = (void *)&q.out.info->info ## lvl1; \
1688 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
1689 info_ctr.info.info ## lvl1->field1 = value; \
1690 TESTSETCALL(SetPrinter, s) \
1691 info_ctr.info.info ## lvl1->field1 = 0; \
1692 TESTGETCALL(GetPrinter, q) \
1693 p = (void *)&q.out.info->info ## lvl1; \
1694 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
1695 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1696 q.in.level = lvl2; \
1697 TESTGETCALL(GetPrinter, q) \
1698 p = (void *)&q.out.info->info ## lvl2; \
1699 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)p; \
1700 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1701 } while (0)
1703 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1704 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1705 } while (0)
1707 q0.in.level = 0;
1708 do { TESTGETCALL(GetPrinter, q0) } while (0);
1710 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1711 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1713 /* level 0 printername does not stick */
1714 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1715 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1716 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1717 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1718 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1719 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1720 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1721 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1722 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1723 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1724 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1725 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1726 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1727 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1728 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1730 /* servername can be set but does not stick
1731 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1732 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1733 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1736 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1737 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1738 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1739 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1740 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1742 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1743 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1744 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1745 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1746 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1747 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1748 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1749 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1750 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1751 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1753 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1754 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1755 attribute_list[i],
1756 (attribute_list[i] | default_attribute)
1757 ); */
1758 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1759 attribute_list[i],
1760 (attribute_list[i] | default_attribute)
1762 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1763 attribute_list[i],
1764 (attribute_list[i] | default_attribute)
1766 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1767 attribute_list[i],
1768 (attribute_list[i] | default_attribute)
1770 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1771 attribute_list[i],
1772 (attribute_list[i] | default_attribute)
1773 ); */
1774 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1775 attribute_list[i],
1776 (attribute_list[i] | default_attribute)
1778 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1779 attribute_list[i],
1780 (attribute_list[i] | default_attribute)
1782 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1783 attribute_list[i],
1784 (attribute_list[i] | default_attribute)
1786 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1787 attribute_list[i],
1788 (attribute_list[i] | default_attribute)
1789 ); */
1790 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1791 attribute_list[i],
1792 (attribute_list[i] | default_attribute)
1794 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1795 attribute_list[i],
1796 (attribute_list[i] | default_attribute)
1798 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1799 attribute_list[i],
1800 (attribute_list[i] | default_attribute)
1804 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1805 /* level 2 sets do not stick
1806 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1807 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1808 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1809 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1810 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1811 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1814 /* priorities need to be between 0 and 99
1815 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1816 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1817 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1818 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1819 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1820 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1821 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1822 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1823 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1825 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1826 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1828 /* does not stick
1829 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1830 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1832 /* does not stick
1833 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1834 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1836 /* FIXME: gd also test devmode and secdesc behavior */
1839 /* verify composition of level 1 description field */
1840 const char *description;
1841 const char *tmp;
1843 q0.in.level = 1;
1844 do { TESTGETCALL(GetPrinter, q0) } while (0);
1846 description = talloc_strdup(tctx, q0.out.info->info1.description);
1848 q0.in.level = 2;
1849 do { TESTGETCALL(GetPrinter, q0) } while (0);
1851 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1852 q0.out.info->info2.printername,
1853 q0.out.info->info2.drivername,
1854 q0.out.info->info2.location);
1856 do { STRING_EQUAL(description, tmp, "description")} while (0);
1859 return ret;
1862 static bool test_security_descriptor_equal(struct torture_context *tctx,
1863 const struct security_descriptor *sd1,
1864 const struct security_descriptor *sd2)
1866 if (sd1 == sd2) {
1867 return true;
1870 if (!sd1 || !sd2) {
1871 torture_comment(tctx, "%s\n", __location__);
1872 return false;
1875 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1876 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1878 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1879 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1881 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1882 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1883 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1884 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1885 return false;
1887 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1888 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1889 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1890 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1891 return false;
1894 return true;
1897 static bool test_sd_set_level(struct torture_context *tctx,
1898 struct dcerpc_binding_handle *b,
1899 struct policy_handle *handle,
1900 uint32_t level,
1901 struct security_descriptor *sd)
1903 struct spoolss_SetPrinterInfoCtr info_ctr;
1904 struct spoolss_DevmodeContainer devmode_ctr;
1905 struct sec_desc_buf secdesc_ctr;
1906 union spoolss_SetPrinterInfo sinfo;
1907 union spoolss_PrinterInfo info;
1908 struct spoolss_SetPrinterInfo3 info3;
1910 ZERO_STRUCT(devmode_ctr);
1911 ZERO_STRUCT(secdesc_ctr);
1913 switch (level) {
1914 case 2: {
1915 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1916 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1918 info_ctr.level = 2;
1919 info_ctr.info = sinfo;
1921 break;
1923 case 3: {
1925 info3.sec_desc_ptr = NULL;
1927 info_ctr.level = 3;
1928 info_ctr.info.info3 = &info3;
1930 break;
1932 default:
1933 return false;
1936 secdesc_ctr.sd = sd;
1938 torture_assert(tctx,
1939 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1941 return true;
1944 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1945 struct dcerpc_binding_handle *b,
1946 struct policy_handle *handle)
1948 union spoolss_PrinterInfo info;
1949 struct security_descriptor *sd1, *sd2;
1950 int i;
1952 /* just compare level 2 and level 3 */
1954 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1956 sd1 = info.info2.secdesc;
1958 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1960 sd2 = info.info3.secdesc;
1962 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1963 "SD level 2 != SD level 3");
1966 /* query level 2, set level 2, query level 2 */
1968 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1970 sd1 = info.info2.secdesc;
1972 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1974 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1976 sd2 = info.info2.secdesc;
1977 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1978 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1979 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1982 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1983 "SD level 2 != SD level 2 after SD has been set via level 2");
1986 /* query level 2, set level 3, query level 2 */
1988 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1990 sd1 = info.info2.secdesc;
1992 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1994 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1996 sd2 = info.info2.secdesc;
1998 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1999 "SD level 2 != SD level 2 after SD has been set via level 3");
2001 /* set modified sd level 3, query level 2 */
2003 for (i=0; i < 93; i++) {
2004 struct security_ace a;
2005 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
2006 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
2007 a.flags = 0;
2008 a.size = 0; /* autogenerated */
2009 a.access_mask = 0;
2010 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
2011 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
2014 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
2016 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2017 sd2 = info.info2.secdesc;
2019 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
2020 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
2021 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
2024 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
2025 "modified SD level 2 != SD level 2 after SD has been set via level 3");
2028 return true;
2032 * wrapper call that saves original sd, runs tests, and restores sd
2035 static bool test_PrinterInfo_SD(struct torture_context *tctx,
2036 struct dcerpc_binding_handle *b,
2037 struct policy_handle *handle)
2039 union spoolss_PrinterInfo info;
2040 struct security_descriptor *sd;
2041 bool ret = true;
2043 torture_comment(tctx, "Testing Printer Security Descriptors\n");
2045 /* save original sd */
2047 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
2048 "failed to get initial security descriptor");
2050 sd = security_descriptor_copy(tctx, info.info2.secdesc);
2052 /* run tests */
2054 ret = test_PrinterInfo_SDs(tctx, b, handle);
2056 /* restore original sd */
2058 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
2059 "failed to restore initial security descriptor");
2061 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
2062 ret ? "succeeded" : "failed");
2065 return ret;
2068 static bool test_devmode_set_level(struct torture_context *tctx,
2069 struct dcerpc_binding_handle *b,
2070 struct policy_handle *handle,
2071 uint32_t level,
2072 struct spoolss_DeviceMode *devmode)
2074 struct spoolss_SetPrinterInfoCtr info_ctr;
2075 struct spoolss_DevmodeContainer devmode_ctr;
2076 struct sec_desc_buf secdesc_ctr;
2077 union spoolss_SetPrinterInfo sinfo;
2079 ZERO_STRUCT(devmode_ctr);
2080 ZERO_STRUCT(secdesc_ctr);
2082 switch (level) {
2083 case 2: {
2084 union spoolss_PrinterInfo info;
2085 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2086 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
2088 info_ctr.level = 2;
2089 info_ctr.info = sinfo;
2091 break;
2093 case 8: {
2094 struct spoolss_SetPrinterInfo8 info8;
2096 info8.devmode_ptr = NULL;
2098 info_ctr.level = 8;
2099 info_ctr.info.info8 = &info8;
2101 break;
2103 default:
2104 return false;
2107 devmode_ctr.devmode = devmode;
2109 torture_assert(tctx,
2110 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
2112 return true;
2116 static bool test_devicemode_equal(struct torture_context *tctx,
2117 const struct spoolss_DeviceMode *d1,
2118 const struct spoolss_DeviceMode *d2)
2120 if (d1 == d2) {
2121 return true;
2124 if (!d1 || !d2) {
2125 torture_comment(tctx, "%s\n", __location__);
2126 return false;
2128 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
2129 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
2130 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
2131 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
2132 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
2133 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
2134 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
2135 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
2136 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
2137 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
2138 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
2139 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
2140 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
2141 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2142 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2143 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2144 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2145 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2146 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2147 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2148 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2149 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2150 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2151 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2152 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2153 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2154 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2155 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2156 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2157 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2158 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2159 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2160 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2161 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2162 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2164 return true;
2167 static bool test_devicemode_full(struct torture_context *tctx,
2168 struct dcerpc_binding_handle *b,
2169 struct policy_handle *handle)
2171 struct spoolss_SetPrinter s;
2172 struct spoolss_GetPrinter q;
2173 struct spoolss_SetPrinterInfoCtr info_ctr;
2174 struct spoolss_SetPrinterInfo8 info8;
2175 union spoolss_PrinterInfo info;
2176 struct spoolss_DevmodeContainer devmode_ctr;
2177 struct sec_desc_buf secdesc_ctr;
2178 uint32_t needed;
2179 bool ret = true;
2180 NTSTATUS status;
2182 #define TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, exp_value, expected_result) do { \
2183 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2184 q.in.level = lvl1; \
2185 TESTGETCALL(GetPrinter, q) \
2186 info_ctr.level = lvl1; \
2187 if (lvl1 == 2) {\
2188 void *p = (void *)&q.out.info->info ## lvl1; \
2189 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
2190 } else if (lvl1 == 8) {\
2191 info_ctr.info.info ## lvl1 = &info8; \
2193 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2194 devmode_ctr.devmode->field1 = value; \
2195 TESTSETCALL_EXP(SetPrinter, s, expected_result) \
2196 if (W_ERROR_IS_OK(expected_result)) { \
2197 TESTGETCALL(GetPrinter, q) \
2198 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2199 q.in.level = lvl2; \
2200 TESTGETCALL(GetPrinter, q) \
2201 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2203 } while (0)
2205 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, expected_result) do { \
2206 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, expected_result); \
2207 } while (0)
2209 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2210 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, WERR_OK); \
2211 } while (0)
2213 ZERO_STRUCT(devmode_ctr);
2214 ZERO_STRUCT(secdesc_ctr);
2215 ZERO_STRUCT(info8);
2217 s.in.handle = handle;
2218 s.in.command = 0;
2219 s.in.info_ctr = &info_ctr;
2220 s.in.devmode_ctr = &devmode_ctr;
2221 s.in.secdesc_ctr = &secdesc_ctr;
2223 q.in.handle = handle;
2224 q.out.info = &info;
2226 #if 0
2227 const char *devicename;/* [charset(UTF16)] */
2228 enum spoolss_DeviceModeSpecVersion specversion;
2229 uint16_t driverversion;
2230 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2231 uint32_t fields;
2232 #endif
2233 TEST_DEVMODE_INT_EXP(8, size, 8, size, __LINE__, WERR_INVALID_PARAM);
2234 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0, WERR_INVALID_PARAM);
2235 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0xffff, WERR_INVALID_PARAM);
2236 TEST_DEVMODE_INT_EXP(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), (devmode_ctr.devmode->__driverextra_length > 0 ) ? WERR_INVALID_PARAM : WERR_OK);
2237 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2239 devmode_ctr.devmode->driverextra_data = data_blob_string_const("foobar");
2240 torture_assert(tctx,
2241 test_devmode_set_level(tctx, b, handle, 8, devmode_ctr.devmode),
2242 "failed to set devmode");
2244 TEST_DEVMODE_INT_EXP(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), (devmode_ctr.devmode->__driverextra_length > 0 ) ? WERR_INVALID_PARAM : WERR_OK);
2245 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2247 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
2248 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
2249 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
2250 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
2251 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
2252 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
2253 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
2254 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
2255 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
2256 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
2257 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
2258 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
2259 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
2260 #if 0
2261 const char *formname;/* [charset(UTF16)] */
2262 #endif
2263 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
2264 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
2265 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
2266 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
2267 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
2268 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
2269 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
2270 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
2271 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
2272 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
2273 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
2274 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
2275 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
2276 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
2278 return ret;
2281 static bool call_OpenPrinterEx(struct torture_context *tctx,
2282 struct dcerpc_pipe *p,
2283 const char *name,
2284 struct spoolss_DeviceMode *devmode,
2285 struct policy_handle *handle);
2287 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2288 struct dcerpc_pipe *p,
2289 struct policy_handle *handle,
2290 const char *name)
2292 union spoolss_PrinterInfo info;
2293 struct spoolss_DeviceMode *devmode;
2294 struct spoolss_DeviceMode *devmode2;
2295 struct policy_handle handle_devmode;
2296 struct dcerpc_binding_handle *b = p->binding_handle;
2298 /* simply compare level8 and level2 devmode */
2300 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2302 devmode = info.info8.devmode;
2304 if (devmode && devmode->size == 0) {
2305 torture_fail(tctx,
2306 "devmode of zero size!");
2309 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2311 devmode2 = info.info2.devmode;
2313 if (devmode2 && devmode2->size == 0) {
2314 torture_fail(tctx,
2315 "devmode of zero size!");
2318 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2319 "DM level 8 != DM level 2");
2322 /* set devicemode level 8 and see if it persists */
2324 devmode->copies = 93;
2325 devmode->formname = talloc_strdup(tctx, "Legal");
2327 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2329 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2331 devmode2 = info.info8.devmode;
2333 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2334 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2336 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2338 devmode2 = info.info2.devmode;
2340 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2341 "modified DM level 8 != DM level 2");
2344 /* set devicemode level 2 and see if it persists */
2346 devmode->copies = 39;
2347 devmode->formname = talloc_strdup(tctx, "Executive");
2349 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2351 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2353 devmode2 = info.info8.devmode;
2355 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2356 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2358 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2360 devmode2 = info.info2.devmode;
2362 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2363 "modified DM level 8 != DM level 2");
2366 /* check every single bit in public part of devicemode */
2368 torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2369 "failed to set every single devicemode component");
2372 /* change formname upon open and see if it persists in getprinter calls */
2374 devmode->formname = talloc_strdup(tctx, "A4");
2375 devmode->copies = 42;
2377 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2378 "failed to open printer handle");
2380 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2382 devmode2 = info.info8.devmode;
2384 if (strequal(devmode->devicename, devmode2->devicename)) {
2385 torture_warning(tctx, "devicenames are the same\n");
2386 } else {
2387 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2388 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2391 if (strequal(devmode->formname, devmode2->formname)) {
2392 torture_warning(tctx, "formname are the same\n");
2393 } else {
2394 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2395 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2398 if (devmode->copies == devmode2->copies) {
2399 torture_warning(tctx, "copies are the same\n");
2400 } else {
2401 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2402 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2405 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2407 devmode2 = info.info2.devmode;
2409 if (strequal(devmode->devicename, devmode2->devicename)) {
2410 torture_warning(tctx, "devicenames are the same\n");
2411 } else {
2412 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2413 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2416 if (strequal(devmode->formname, devmode2->formname)) {
2417 torture_warning(tctx, "formname is the same\n");
2418 } else {
2419 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2420 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2423 if (devmode->copies == devmode2->copies) {
2424 torture_warning(tctx, "copies are the same\n");
2425 } else {
2426 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2427 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2430 test_ClosePrinter(tctx, b, &handle_devmode);
2432 return true;
2436 * wrapper call that saves original devmode, runs tests, and restores devmode
2439 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2440 struct dcerpc_pipe *p,
2441 struct policy_handle *handle,
2442 const char *name,
2443 struct spoolss_DeviceMode *addprinter_devmode)
2445 union spoolss_PrinterInfo info;
2446 struct spoolss_DeviceMode *devmode;
2447 bool ret = true;
2448 struct dcerpc_binding_handle *b = p->binding_handle;
2450 torture_comment(tctx, "Testing Printer Devicemodes\n");
2452 /* save original devmode */
2454 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2455 "failed to get initial global devicemode");
2457 devmode = info.info8.devmode;
2459 if (devmode && devmode->size == 0) {
2460 torture_fail(tctx,
2461 "devmode of zero size!");
2464 if (addprinter_devmode) {
2465 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
2466 torture_warning(tctx, "current global DM is != DM provided in addprinter");
2470 /* run tests */
2472 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2474 /* restore original devmode */
2476 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2477 "failed to restore initial global device mode");
2479 torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2480 ret ? "succeeded" : "failed");
2483 return ret;
2486 bool test_ClosePrinter(struct torture_context *tctx,
2487 struct dcerpc_binding_handle *b,
2488 struct policy_handle *handle)
2490 NTSTATUS status;
2491 struct spoolss_ClosePrinter r;
2493 r.in.handle = handle;
2494 r.out.handle = handle;
2496 torture_comment(tctx, "Testing ClosePrinter\n");
2498 status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2499 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2500 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2502 return true;
2505 static bool test_GetForm_args(struct torture_context *tctx,
2506 struct dcerpc_binding_handle *b,
2507 struct policy_handle *handle,
2508 const char *form_name,
2509 uint32_t level,
2510 union spoolss_FormInfo *info_p)
2512 NTSTATUS status;
2513 struct spoolss_GetForm r;
2514 uint32_t needed;
2516 r.in.handle = handle;
2517 r.in.form_name = form_name;
2518 r.in.level = level;
2519 r.in.buffer = NULL;
2520 r.in.offered = 0;
2521 r.out.needed = &needed;
2523 torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2525 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2526 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2528 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2529 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2530 r.in.buffer = &blob;
2531 r.in.offered = needed;
2532 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2533 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2535 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2537 torture_assert(tctx, r.out.info, "No form info returned");
2540 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2542 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
2544 if (info_p) {
2545 *info_p = *r.out.info;
2548 return true;
2551 static bool test_GetForm(struct torture_context *tctx,
2552 struct dcerpc_binding_handle *b,
2553 struct policy_handle *handle,
2554 const char *form_name,
2555 uint32_t level)
2557 return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2560 static bool test_EnumForms(struct torture_context *tctx,
2561 struct dcerpc_binding_handle *b,
2562 struct policy_handle *handle,
2563 bool print_server,
2564 uint32_t level,
2565 uint32_t *count_p,
2566 union spoolss_FormInfo **info_p)
2568 struct spoolss_EnumForms r;
2569 uint32_t needed;
2570 uint32_t count;
2571 union spoolss_FormInfo *info;
2573 r.in.handle = handle;
2574 r.in.level = level;
2575 r.in.buffer = NULL;
2576 r.in.offered = 0;
2577 r.out.needed = &needed;
2578 r.out.count = &count;
2579 r.out.info = &info;
2581 torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2583 torture_assert_ntstatus_ok(tctx,
2584 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2585 "EnumForms failed");
2587 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2588 torture_skip(tctx, "EnumForms level 2 not supported");
2591 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2592 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2595 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2596 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2597 r.in.buffer = &blob;
2598 r.in.offered = needed;
2600 torture_assert_ntstatus_ok(tctx,
2601 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2602 "EnumForms failed");
2604 torture_assert(tctx, info, "No forms returned");
2607 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2609 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
2611 if (info_p) {
2612 *info_p = info;
2614 if (count_p) {
2615 *count_p = count;
2618 return true;
2621 static bool test_EnumForms_all(struct torture_context *tctx,
2622 struct dcerpc_binding_handle *b,
2623 struct policy_handle *handle,
2624 bool print_server)
2626 uint32_t levels[] = { 1, 2 };
2627 int i, j;
2629 for (i=0; i<ARRAY_SIZE(levels); i++) {
2631 uint32_t count = 0;
2632 union spoolss_FormInfo *info = NULL;
2634 torture_assert(tctx,
2635 test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2636 "failed to enum forms");
2638 for (j = 0; j < count; j++) {
2639 if (!print_server) {
2640 torture_assert(tctx,
2641 test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2642 "failed to get form");
2647 return true;
2650 static bool test_EnumForms_find_one(struct torture_context *tctx,
2651 struct dcerpc_binding_handle *b,
2652 struct policy_handle *handle,
2653 bool print_server,
2654 const char *form_name)
2656 union spoolss_FormInfo *info;
2657 uint32_t count;
2658 bool found = false;
2659 int i;
2661 torture_assert(tctx,
2662 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2663 "failed to enumerate forms");
2665 for (i=0; i<count; i++) {
2666 if (strequal(form_name, info[i].info1.form_name)) {
2667 found = true;
2668 break;
2672 return found;
2675 static bool test_DeleteForm(struct torture_context *tctx,
2676 struct dcerpc_binding_handle *b,
2677 struct policy_handle *handle,
2678 const char *form_name,
2679 WERROR expected_result)
2681 struct spoolss_DeleteForm r;
2683 r.in.handle = handle;
2684 r.in.form_name = form_name;
2686 torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2688 torture_assert_ntstatus_ok(tctx,
2689 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2690 "DeleteForm failed");
2691 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2692 "DeleteForm gave unexpected result");
2693 if (W_ERROR_IS_OK(r.out.result)) {
2694 torture_assert_ntstatus_ok(tctx,
2695 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2696 "2nd DeleteForm failed");
2697 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2698 "2nd DeleteForm failed");
2701 return true;
2704 static bool test_AddForm(struct torture_context *tctx,
2705 struct dcerpc_binding_handle *b,
2706 struct policy_handle *handle,
2707 uint32_t level,
2708 union spoolss_AddFormInfo *info,
2709 WERROR expected_result)
2711 struct spoolss_AddForm r;
2712 struct spoolss_AddFormInfoCtr info_ctr;
2714 info_ctr.level = level;
2715 info_ctr.info = *info;
2717 if (level != 1) {
2718 torture_skip(tctx, "only level 1 supported");
2721 r.in.handle = handle;
2722 r.in.info_ctr = &info_ctr;
2724 torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2725 r.in.info_ctr->info.info1->form_name, level,
2726 r.in.info_ctr->info.info1->flags);
2728 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2729 "AddForm failed");
2730 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2731 "AddForm gave unexpected result");
2733 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2734 "2nd AddForm failed");
2735 if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2736 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2737 "2nd AddForm gave unexpected result");
2738 } else {
2739 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2740 "2nd AddForm gave unexpected result");
2743 return true;
2746 static bool test_SetForm(struct torture_context *tctx,
2747 struct dcerpc_binding_handle *b,
2748 struct policy_handle *handle,
2749 const char *form_name,
2750 uint32_t level,
2751 union spoolss_AddFormInfo *info)
2753 struct spoolss_SetForm r;
2754 struct spoolss_AddFormInfoCtr info_ctr;
2756 info_ctr.level = level;
2757 info_ctr.info = *info;
2759 r.in.handle = handle;
2760 r.in.form_name = form_name;
2761 r.in.info_ctr = &info_ctr;
2763 torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2764 form_name, level);
2766 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2767 "SetForm failed");
2769 torture_assert_werr_ok(tctx, r.out.result,
2770 "SetForm failed");
2772 return true;
2775 static bool test_GetForm_winreg(struct torture_context *tctx,
2776 struct dcerpc_binding_handle *b,
2777 struct policy_handle *handle,
2778 const char *key_name,
2779 const char *form_name,
2780 enum winreg_Type *w_type,
2781 uint32_t *w_size,
2782 uint32_t *w_length,
2783 uint8_t **w_data);
2785 static bool test_Forms_args(struct torture_context *tctx,
2786 struct dcerpc_binding_handle *b,
2787 struct policy_handle *handle,
2788 bool print_server,
2789 const char *printer_name,
2790 struct dcerpc_binding_handle *winreg_handle,
2791 struct policy_handle *hive_handle,
2792 const char *form_name,
2793 struct spoolss_AddFormInfo1 *info1,
2794 WERROR expected_add_result,
2795 WERROR expected_delete_result)
2797 union spoolss_FormInfo info;
2798 union spoolss_AddFormInfo add_info;
2800 enum winreg_Type w_type;
2801 uint32_t w_size;
2802 uint32_t w_length;
2803 uint8_t *w_data;
2805 add_info.info1 = info1;
2807 torture_assert(tctx,
2808 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2809 "failed to add form");
2811 if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2813 struct spoolss_FormInfo1 i1;
2815 torture_assert(tctx,
2816 test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2817 "failed to get form via winreg");
2819 i1.size.width = IVAL(w_data, 0);
2820 i1.size.height = IVAL(w_data, 4);
2821 i1.area.left = IVAL(w_data, 8);
2822 i1.area.top = IVAL(w_data, 12);
2823 i1.area.right = IVAL(w_data, 16);
2824 i1.area.bottom = IVAL(w_data, 20);
2825 /* skip index here */
2826 i1.flags = IVAL(w_data, 28);
2828 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2829 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2830 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2831 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
2832 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
2833 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
2834 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
2835 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
2836 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2837 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
2840 if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2841 torture_assert(tctx,
2842 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2843 "failed to get added form");
2845 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2846 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2847 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2848 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2849 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2850 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2851 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2853 if (winreg_handle && hive_handle) {
2855 struct spoolss_FormInfo1 i1;
2857 i1.size.width = IVAL(w_data, 0);
2858 i1.size.height = IVAL(w_data, 4);
2859 i1.area.left = IVAL(w_data, 8);
2860 i1.area.top = IVAL(w_data, 12);
2861 i1.area.right = IVAL(w_data, 16);
2862 i1.area.bottom = IVAL(w_data, 20);
2863 /* skip index here */
2864 i1.flags = IVAL(w_data, 28);
2866 torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
2867 torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
2868 torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
2869 torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
2870 torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
2871 torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
2872 torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
2875 add_info.info1->size.width = 1234;
2877 torture_assert(tctx,
2878 test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2879 "failed to set form");
2880 torture_assert(tctx,
2881 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2882 "failed to get setted form");
2884 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2887 if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2888 torture_assert(tctx,
2889 test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2890 "Newly added form not found in enum call");
2893 torture_assert(tctx,
2894 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2895 "failed to delete form");
2897 return true;
2900 static bool test_Forms(struct torture_context *tctx,
2901 struct dcerpc_binding_handle *b,
2902 struct policy_handle *handle,
2903 bool print_server,
2904 const char *printer_name,
2905 struct dcerpc_binding_handle *winreg_handle,
2906 struct policy_handle *hive_handle)
2908 const struct spoolss_FormSize size = {
2909 .width = 50,
2910 .height = 25
2912 const struct spoolss_FormArea area = {
2913 .left = 5,
2914 .top = 10,
2915 .right = 45,
2916 .bottom = 15
2918 int i;
2920 struct {
2921 struct spoolss_AddFormInfo1 info1;
2922 WERROR expected_add_result;
2923 WERROR expected_delete_result;
2924 } forms[] = {
2926 .info1 = {
2927 .flags = SPOOLSS_FORM_USER,
2928 .form_name = "testform_user",
2929 .size = size,
2930 .area = area,
2932 .expected_add_result = WERR_OK,
2933 .expected_delete_result = WERR_OK
2936 weird, we can add a builtin form but we can never remove it
2937 again - gd
2940 .info1 = {
2941 .flags = SPOOLSS_FORM_BUILTIN,
2942 .form_name = "testform_builtin",
2943 .size = size,
2944 .area = area,
2946 .expected_add_result = WERR_OK,
2947 .expected_delete_result = WERR_INVALID_PARAM,
2951 .info1 = {
2952 .flags = SPOOLSS_FORM_PRINTER,
2953 .form_name = "testform_printer",
2954 .size = size,
2955 .area = area,
2957 .expected_add_result = WERR_OK,
2958 .expected_delete_result = WERR_OK
2961 .info1 = {
2962 .flags = SPOOLSS_FORM_USER,
2963 .form_name = "Letter",
2964 .size = size,
2965 .area = area,
2967 .expected_add_result = WERR_FILE_EXISTS,
2968 .expected_delete_result = WERR_INVALID_PARAM
2971 .info1 = {
2972 .flags = SPOOLSS_FORM_BUILTIN,
2973 .form_name = "Letter",
2974 .size = size,
2975 .area = area,
2977 .expected_add_result = WERR_FILE_EXISTS,
2978 .expected_delete_result = WERR_INVALID_PARAM
2981 .info1 = {
2982 .flags = SPOOLSS_FORM_PRINTER,
2983 .form_name = "Letter",
2984 .size = size,
2985 .area = area,
2987 .expected_add_result = WERR_FILE_EXISTS,
2988 .expected_delete_result = WERR_INVALID_PARAM
2991 .info1 = {
2992 .flags = 12345,
2993 .form_name = "invalid_flags",
2994 .size = size,
2995 .area = area,
2997 .expected_add_result = WERR_INVALID_PARAM,
2998 .expected_delete_result = WERR_INVALID_FORM_NAME
3003 for (i=0; i < ARRAY_SIZE(forms); i++) {
3004 torture_assert(tctx,
3005 test_Forms_args(tctx, b, handle, print_server, printer_name,
3006 winreg_handle, hive_handle,
3007 forms[i].info1.form_name,
3008 &forms[i].info1,
3009 forms[i].expected_add_result,
3010 forms[i].expected_delete_result),
3011 talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
3014 return true;
3017 static bool test_EnumPorts_old(struct torture_context *tctx,
3018 void *private_data)
3020 struct test_spoolss_context *ctx =
3021 talloc_get_type_abort(private_data, struct test_spoolss_context);
3023 NTSTATUS status;
3024 struct spoolss_EnumPorts r;
3025 uint32_t needed;
3026 uint32_t count;
3027 union spoolss_PortInfo *info;
3028 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3029 struct dcerpc_binding_handle *b = p->binding_handle;
3031 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
3032 dcerpc_server_name(p));
3033 r.in.level = 2;
3034 r.in.buffer = NULL;
3035 r.in.offered = 0;
3036 r.out.needed = &needed;
3037 r.out.count = &count;
3038 r.out.info = &info;
3040 torture_comment(tctx, "Testing EnumPorts\n");
3042 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3044 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3046 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3047 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3048 r.in.buffer = &blob;
3049 r.in.offered = needed;
3051 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3052 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3053 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3055 torture_assert(tctx, info, "No ports returned");
3058 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3060 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
3062 return true;
3065 static bool test_AddPort(struct torture_context *tctx,
3066 void *private_data)
3068 struct test_spoolss_context *ctx =
3069 talloc_get_type_abort(private_data, struct test_spoolss_context);
3071 NTSTATUS status;
3072 struct spoolss_AddPort r;
3073 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3074 struct dcerpc_binding_handle *b = p->binding_handle;
3076 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
3077 dcerpc_server_name(p));
3078 r.in.unknown = 0;
3079 r.in.monitor_name = "foo";
3081 torture_comment(tctx, "Testing AddPort\n");
3083 status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
3085 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
3087 /* win2k3 returns WERR_NOT_SUPPORTED */
3089 #if 0
3091 if (!W_ERROR_IS_OK(r.out.result)) {
3092 printf("AddPort failed - %s\n", win_errstr(r.out.result));
3093 return false;
3096 #endif
3098 return true;
3101 static bool test_GetJob_args(struct torture_context *tctx,
3102 struct dcerpc_binding_handle *b,
3103 struct policy_handle *handle,
3104 uint32_t job_id,
3105 uint32_t level,
3106 union spoolss_JobInfo *info_p)
3108 NTSTATUS status;
3109 struct spoolss_GetJob r;
3110 union spoolss_JobInfo info;
3111 uint32_t needed;
3113 r.in.handle = handle;
3114 r.in.job_id = job_id;
3115 r.in.level = level;
3116 r.in.buffer = NULL;
3117 r.in.offered = 0;
3118 r.out.needed = &needed;
3119 r.out.info = &info;
3121 torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
3123 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3124 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3125 if (level == 0) {
3126 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
3129 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3130 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3131 r.in.buffer = &blob;
3132 r.in.offered = needed;
3134 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3135 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3138 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
3139 torture_assert(tctx, r.out.info, "No job info returned");
3141 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
3143 if (info_p) {
3144 *info_p = *r.out.info;
3147 return true;
3150 #if 0
3151 static bool test_GetJob(struct torture_context *tctx,
3152 struct dcerpc_binding_handle *b,
3153 struct policy_handle *handle,
3154 uint32_t job_id)
3156 uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
3157 uint32_t i;
3159 for (i=0; i < ARRAY_SIZE(levels); i++) {
3160 torture_assert(tctx,
3161 test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
3162 "GetJob failed");
3165 return true;
3167 #endif
3169 static bool test_SetJob(struct torture_context *tctx,
3170 struct dcerpc_binding_handle *b,
3171 struct policy_handle *handle,
3172 uint32_t job_id,
3173 struct spoolss_JobInfoContainer *ctr,
3174 enum spoolss_JobControl command)
3176 NTSTATUS status;
3177 struct spoolss_SetJob r;
3179 r.in.handle = handle;
3180 r.in.job_id = job_id;
3181 r.in.ctr = ctr;
3182 r.in.command = command;
3184 switch (command) {
3185 case SPOOLSS_JOB_CONTROL_PAUSE:
3186 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3187 break;
3188 case SPOOLSS_JOB_CONTROL_RESUME:
3189 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3190 break;
3191 case SPOOLSS_JOB_CONTROL_CANCEL:
3192 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3193 break;
3194 case SPOOLSS_JOB_CONTROL_RESTART:
3195 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3196 break;
3197 case SPOOLSS_JOB_CONTROL_DELETE:
3198 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3199 break;
3200 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3201 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3202 break;
3203 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3204 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3205 break;
3206 case SPOOLSS_JOB_CONTROL_RETAIN:
3207 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3208 break;
3209 case SPOOLSS_JOB_CONTROL_RELEASE:
3210 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3211 break;
3212 default:
3213 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3214 break;
3217 status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3218 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3219 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3221 return true;
3224 static bool test_AddJob(struct torture_context *tctx,
3225 struct dcerpc_binding_handle *b,
3226 struct policy_handle *handle)
3228 NTSTATUS status;
3229 struct spoolss_AddJob r;
3230 uint32_t needed;
3232 r.in.level = 0;
3233 r.in.handle = handle;
3234 r.in.offered = 0;
3235 r.out.needed = &needed;
3236 r.in.buffer = r.out.buffer = NULL;
3238 torture_comment(tctx, "Testing AddJob\n");
3240 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3241 torture_assert_ntstatus_ok(tctx, status, "AddJob failed");
3242 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3244 r.in.level = 1;
3246 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3247 torture_assert_ntstatus_ok(tctx, status, "AddJob failed");
3248 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3250 return true;
3254 static bool test_EnumJobs_args(struct torture_context *tctx,
3255 struct dcerpc_binding_handle *b,
3256 struct policy_handle *handle,
3257 uint32_t level,
3258 uint32_t *count_p,
3259 union spoolss_JobInfo **info_p)
3261 NTSTATUS status;
3262 struct spoolss_EnumJobs r;
3263 uint32_t needed;
3264 uint32_t count;
3265 union spoolss_JobInfo *info;
3267 r.in.handle = handle;
3268 r.in.firstjob = 0;
3269 r.in.numjobs = 0xffffffff;
3270 r.in.level = level;
3271 r.in.buffer = NULL;
3272 r.in.offered = 0;
3273 r.out.needed = &needed;
3274 r.out.count = &count;
3275 r.out.info = &info;
3277 torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3279 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3281 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3283 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3284 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3285 r.in.buffer = &blob;
3286 r.in.offered = needed;
3288 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3290 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3291 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3292 torture_assert(tctx, info, "No jobs returned");
3294 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3296 } else {
3297 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3300 if (count_p) {
3301 *count_p = count;
3303 if (info_p) {
3304 *info_p = info;
3307 return true;
3310 static bool test_JobPropertiesEnum(struct torture_context *tctx,
3311 struct dcerpc_binding_handle *b,
3312 struct policy_handle *handle,
3313 uint32_t job_id)
3315 struct spoolss_RpcEnumJobNamedProperties r;
3316 uint32_t pcProperties = 0;
3317 struct RPC_PrintNamedProperty *ppProperties = NULL;
3319 r.in.hPrinter = handle;
3320 r.in.JobId = job_id;
3321 r.out.pcProperties = &pcProperties;
3322 r.out.ppProperties = &ppProperties;
3324 torture_comment(tctx, "Testing RpcEnumJobNamedProperties(%d)\n", job_id);
3326 torture_assert_ntstatus_ok(tctx,
3327 dcerpc_spoolss_RpcEnumJobNamedProperties_r(b, tctx, &r),
3328 "spoolss_RpcEnumJobNamedProperties failed");
3329 torture_assert_werr_ok(tctx, r.out.result,
3330 "spoolss_RpcEnumJobNamedProperties failed");
3332 return true;
3335 static bool test_JobPropertySet(struct torture_context *tctx,
3336 struct dcerpc_binding_handle *b,
3337 struct policy_handle *handle,
3338 uint32_t job_id,
3339 struct RPC_PrintNamedProperty *property)
3341 struct spoolss_RpcSetJobNamedProperty r;
3343 r.in.hPrinter = handle;
3344 r.in.JobId = job_id;
3345 r.in.pProperty = property;
3347 torture_comment(tctx, "Testing RpcSetJobNamedProperty(%d) %s - %d\n",
3348 job_id, property->propertyName,
3349 property->propertyValue.ePropertyType);
3351 torture_assert_ntstatus_ok(tctx,
3352 dcerpc_spoolss_RpcSetJobNamedProperty_r(b, tctx, &r),
3353 "spoolss_RpcSetJobNamedProperty failed");
3354 torture_assert_werr_ok(tctx, r.out.result,
3355 "spoolss_RpcSetJobNamedProperty failed");
3357 return true;
3360 static bool test_JobPropertyGetValue(struct torture_context *tctx,
3361 struct dcerpc_binding_handle *b,
3362 struct policy_handle *handle,
3363 uint32_t job_id,
3364 const char *property_name,
3365 struct RPC_PrintPropertyValue *value)
3367 struct spoolss_RpcGetJobNamedPropertyValue r;
3369 r.in.hPrinter = handle;
3370 r.in.JobId = job_id;
3371 r.in.pszName = property_name;
3372 r.out.pValue = value;
3374 torture_comment(tctx, "Testing RpcGetJobNamedPropertyValue(%d) %s\n",
3375 job_id, property_name);
3377 torture_assert_ntstatus_ok(tctx,
3378 dcerpc_spoolss_RpcGetJobNamedPropertyValue_r(b, tctx, &r),
3379 "spoolss_RpcGetJobNamedPropertyValue failed");
3380 torture_assert_werr_ok(tctx, r.out.result,
3381 "spoolss_RpcGetJobNamedPropertyValue failed");
3383 return true;
3386 static bool test_JobPropertyDelete(struct torture_context *tctx,
3387 struct dcerpc_binding_handle *b,
3388 struct policy_handle *handle,
3389 uint32_t job_id,
3390 const char *property_name)
3392 struct spoolss_RpcDeleteJobNamedProperty r;
3394 r.in.hPrinter = handle;
3395 r.in.JobId = job_id;
3396 r.in.pszName = property_name;
3398 torture_comment(tctx, "Testing RpcDeleteJobNamedProperty(%d) %s\n",
3399 job_id, property_name);
3401 torture_assert_ntstatus_ok(tctx,
3402 dcerpc_spoolss_RpcDeleteJobNamedProperty_r(b, tctx, &r),
3403 "spoolss_RpcDeleteJobNamedProperty failed");
3404 torture_assert_werr_ok(tctx, r.out.result,
3405 "spoolss_RpcDeleteJobNamedProperty failed");
3407 return true;
3410 static bool test_DoPrintTest_add_one_job_common(struct torture_context *tctx,
3411 struct dcerpc_binding_handle *b,
3412 struct policy_handle *handle,
3413 const char *document_name,
3414 const char *datatype,
3415 uint32_t *job_id)
3417 NTSTATUS status;
3418 struct spoolss_StartDocPrinter s;
3419 struct spoolss_DocumentInfoCtr info_ctr;
3420 struct spoolss_DocumentInfo1 info1;
3421 struct spoolss_StartPagePrinter sp;
3422 struct spoolss_WritePrinter w;
3423 struct spoolss_EndPagePrinter ep;
3424 struct spoolss_EndDocPrinter e;
3425 int i;
3426 uint32_t num_written;
3428 torture_comment(tctx, "Testing StartDocPrinter\n");
3430 s.in.handle = handle;
3431 s.in.info_ctr = &info_ctr;
3432 s.out.job_id = job_id;
3434 info1.document_name = document_name;
3435 info1.output_file = NULL;
3436 info1.datatype = datatype;
3438 info_ctr.level = 1;
3439 info_ctr.info.info1 = &info1;
3441 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3442 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3443 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3445 for (i=1; i < 4; i++) {
3446 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3448 sp.in.handle = handle;
3450 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3451 torture_assert_ntstatus_ok(tctx, status,
3452 "dcerpc_spoolss_StartPagePrinter failed");
3453 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3455 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3457 w.in.handle = handle;
3458 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3459 w.out.num_written = &num_written;
3461 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3462 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3463 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3465 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3467 ep.in.handle = handle;
3469 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3470 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3471 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3474 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3476 e.in.handle = handle;
3478 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3479 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3480 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3482 return true;
3485 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3486 struct dcerpc_binding_handle *b,
3487 struct policy_handle *handle,
3488 const char *document_name,
3489 uint32_t *job_id)
3491 test_DoPrintTest_add_one_job_common(tctx, b, handle, document_name, "RAW", job_id);
3493 return true;
3496 static bool test_DoPrintTest_add_one_job_v4(struct torture_context *tctx,
3497 struct dcerpc_binding_handle *b,
3498 struct policy_handle *handle,
3499 const char *document_name,
3500 uint32_t *job_id)
3502 test_DoPrintTest_add_one_job_common(tctx, b, handle, document_name, "XPS_PASS", job_id);
3504 return true;
3508 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3509 struct dcerpc_binding_handle *b,
3510 struct policy_handle *handle,
3511 uint32_t num_jobs,
3512 uint32_t *job_ids)
3514 uint32_t count;
3515 union spoolss_JobInfo *info = NULL;
3516 int i;
3518 torture_assert(tctx,
3519 test_AddJob(tctx, b, handle),
3520 "AddJob failed");
3522 torture_assert(tctx,
3523 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3524 "EnumJobs level 1 failed");
3526 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3528 for (i=0; i < num_jobs; i++) {
3529 union spoolss_JobInfo ginfo;
3530 const char *document_name;
3531 const char *new_document_name = "any_other_docname";
3532 struct spoolss_JobInfoContainer ctr;
3533 struct spoolss_SetJobInfo1 info1;
3535 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3537 torture_assert(tctx,
3538 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3539 "failed to call test_GetJob");
3541 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3543 document_name = ginfo.info1.document_name;
3545 info1.job_id = ginfo.info1.job_id;
3546 info1.printer_name = ginfo.info1.printer_name;
3547 info1.server_name = ginfo.info1.server_name;
3548 info1.user_name = ginfo.info1.user_name;
3549 info1.document_name = new_document_name;
3550 info1.data_type = ginfo.info1.data_type;
3551 info1.text_status = ginfo.info1.text_status;
3552 info1.status = ginfo.info1.status;
3553 info1.priority = ginfo.info1.priority;
3554 info1.position = ginfo.info1.position;
3555 info1.total_pages = ginfo.info1.total_pages;
3556 info1.pages_printed = ginfo.info1.pages_printed;
3557 info1.submitted = ginfo.info1.submitted;
3559 ctr.level = 1;
3560 ctr.info.info1 = &info1;
3562 torture_assert(tctx,
3563 test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3564 "failed to call test_SetJob level 1");
3566 torture_assert(tctx,
3567 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3568 "failed to call test_GetJob");
3570 if (strequal(ginfo.info1.document_name, document_name)) {
3571 torture_warning(tctx,
3572 "document_name did *NOT* change from '%s' to '%s'\n",
3573 document_name, new_document_name);
3577 for (i=0; i < num_jobs; i++) {
3578 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3579 torture_warning(tctx, "failed to pause printjob\n");
3581 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3582 torture_warning(tctx, "failed to resume printjob\n");
3586 return true;
3589 static bool test_DoPrintTest(struct torture_context *tctx,
3590 struct dcerpc_binding_handle *b,
3591 struct policy_handle *handle)
3593 bool ret = true;
3594 uint32_t num_jobs = 8;
3595 uint32_t *job_ids;
3596 int i;
3598 torture_comment(tctx, "Testing real print operations\n");
3600 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3602 for (i=0; i < num_jobs; i++) {
3603 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3606 for (i=0; i < num_jobs; i++) {
3607 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3610 for (i=0; i < num_jobs; i++) {
3611 ret &= test_DoPrintTest_add_one_job_v4(tctx, b, handle, "TorturePrintJob v4", &job_ids[i]);
3614 for (i=0; i < num_jobs; i++) {
3615 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3618 if (ret == true) {
3619 torture_comment(tctx, "real print operations test succeeded\n\n");
3622 return ret;
3625 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3626 struct dcerpc_binding_handle *b,
3627 struct policy_handle *handle)
3629 bool ret = true;
3630 uint32_t num_jobs = 8;
3631 uint32_t *job_ids;
3632 int i;
3633 torture_comment(tctx, "Testing real print operations (extended)\n");
3635 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3637 for (i=0; i < num_jobs; i++) {
3638 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3641 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3643 for (i=0; i < num_jobs; i++) {
3644 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3647 if (ret == true) {
3648 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3651 return ret;
3654 static bool test_JobPrintProperties_equal(struct torture_context *tctx,
3655 struct RPC_PrintPropertyValue *got,
3656 struct RPC_PrintNamedProperty *exp)
3658 torture_assert_int_equal(tctx,
3659 got->ePropertyType,
3660 exp->propertyValue.ePropertyType,
3661 "ePropertyType");
3663 switch (exp->propertyValue.ePropertyType) {
3664 case kRpcPropertyTypeString:
3665 torture_assert_str_equal(tctx,
3666 got->value.propertyString,
3667 exp->propertyValue.value.propertyString,
3668 "propertyString");
3669 break;
3670 case kRpcPropertyTypeInt32:
3671 torture_assert_int_equal(tctx,
3672 got->value.propertyInt32,
3673 exp->propertyValue.value.propertyInt32,
3674 "propertyInt32");
3675 break;
3676 case kRpcPropertyTypeInt64:
3677 torture_assert_u64_equal(tctx,
3678 got->value.propertyInt64,
3679 exp->propertyValue.value.propertyInt64,
3680 "propertyInt64");
3681 break;
3682 case kRpcPropertyTypeByte:
3683 torture_assert_int_equal(tctx,
3684 got->value.propertyByte,
3685 exp->propertyValue.value.propertyByte,
3686 "propertyByte");
3687 break;
3688 case kRpcPropertyTypeBuffer:
3689 torture_assert_int_equal(tctx,
3690 got->value.propertyBlob.cbBuf,
3691 exp->propertyValue.value.propertyBlob.cbBuf,
3692 "propertyBlob.cbBuf");
3693 torture_assert_mem_equal(tctx,
3694 got->value.propertyBlob.pBuf,
3695 exp->propertyValue.value.propertyBlob.pBuf,
3696 exp->propertyValue.value.propertyBlob.cbBuf,
3697 "propertyBlob.pBuf");
3699 break;
3703 return true;
3706 static bool test_JobPrintProperties(struct torture_context *tctx,
3707 struct dcerpc_binding_handle *b,
3708 struct policy_handle *handle,
3709 uint32_t job_id)
3711 struct RPC_PrintNamedProperty in;
3712 struct RPC_PrintPropertyValue out;
3713 int i;
3714 DATA_BLOB blob = data_blob_string_const("blob");
3715 struct {
3716 const char *property_name;
3717 enum RPC_EPrintPropertyType type;
3718 union RPC_PrintPropertyValueUnion value;
3719 WERROR expected_result;
3720 } tests[] = {
3722 .property_name = "torture_property_string",
3723 .type = kRpcPropertyTypeString,
3724 .value.propertyString = "torture_property_value_string",
3726 .property_name = "torture_property_int32",
3727 .type = kRpcPropertyTypeInt32,
3728 .value.propertyInt32 = 42,
3730 .property_name = "torture_property_int64",
3731 .type = kRpcPropertyTypeInt64,
3732 .value.propertyInt64 = 0xaffe,
3734 .property_name = "torture_property_byte",
3735 .type = kRpcPropertyTypeByte,
3736 .value.propertyByte = 0xab,
3738 .property_name = "torture_property_buffer",
3739 .type = kRpcPropertyTypeBuffer,
3740 .value.propertyBlob.cbBuf = blob.length,
3741 .value.propertyBlob.pBuf = blob.data,
3745 torture_assert(tctx,
3746 test_JobPropertiesEnum(tctx, b, handle, job_id),
3747 "failed to enum properties");
3749 for (i=0; i <ARRAY_SIZE(tests); i++) {
3751 in.propertyName = tests[i].property_name;
3752 in.propertyValue.ePropertyType = tests[i].type;
3753 in.propertyValue.value = tests[i].value;
3755 torture_assert(tctx,
3756 test_JobPropertySet(tctx, b, handle, job_id, &in),
3757 "failed to set property");
3759 torture_assert(tctx,
3760 test_JobPropertyGetValue(tctx, b, handle, job_id, in.propertyName, &out),
3761 "failed to get property");
3763 torture_assert(tctx,
3764 test_JobPrintProperties_equal(tctx, &out, &in),
3765 "property unequal");
3767 torture_assert(tctx,
3768 test_JobPropertiesEnum(tctx, b, handle, job_id),
3769 "failed to enum properties");
3771 torture_assert(tctx,
3772 test_JobPropertyDelete(tctx, b, handle, job_id, in.propertyName),
3773 "failed to delete job property");
3776 torture_assert(tctx,
3777 test_JobPropertiesEnum(tctx, b, handle, job_id),
3778 "failed to enum properties");
3780 return true;
3783 static bool test_DoPrintTest_properties(struct torture_context *tctx,
3784 struct dcerpc_binding_handle *b,
3785 struct policy_handle *handle)
3787 uint32_t num_jobs = 8;
3788 uint32_t *job_ids;
3789 int i;
3790 torture_comment(tctx, "Testing real print operations (properties)\n");
3792 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3794 for (i=0; i < num_jobs; i++) {
3795 torture_assert(tctx,
3796 test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]),
3797 "failed to create print job");
3800 for (i=0; i < num_jobs; i++) {
3801 torture_assert(tctx,
3802 test_JobPrintProperties(tctx, b, handle, job_ids[i]),
3803 "failed to test job properties");
3807 for (i=0; i < num_jobs; i++) {
3808 torture_assert(tctx,
3809 test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE),
3810 "failed to delete printjob");
3813 torture_comment(tctx, "real print operations (properties) test succeeded\n\n");
3815 return true;
3818 static bool test_PausePrinter(struct torture_context *tctx,
3819 struct dcerpc_binding_handle *b,
3820 struct policy_handle *handle)
3822 NTSTATUS status;
3823 struct spoolss_SetPrinter r;
3824 struct spoolss_SetPrinterInfoCtr info_ctr;
3825 struct spoolss_DevmodeContainer devmode_ctr;
3826 struct sec_desc_buf secdesc_ctr;
3828 info_ctr.level = 0;
3829 info_ctr.info.info0 = NULL;
3831 ZERO_STRUCT(devmode_ctr);
3832 ZERO_STRUCT(secdesc_ctr);
3834 r.in.handle = handle;
3835 r.in.info_ctr = &info_ctr;
3836 r.in.devmode_ctr = &devmode_ctr;
3837 r.in.secdesc_ctr = &secdesc_ctr;
3838 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3840 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3842 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3844 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3846 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3848 return true;
3851 static bool test_ResumePrinter(struct torture_context *tctx,
3852 struct dcerpc_binding_handle *b,
3853 struct policy_handle *handle)
3855 NTSTATUS status;
3856 struct spoolss_SetPrinter r;
3857 struct spoolss_SetPrinterInfoCtr info_ctr;
3858 struct spoolss_DevmodeContainer devmode_ctr;
3859 struct sec_desc_buf secdesc_ctr;
3861 info_ctr.level = 0;
3862 info_ctr.info.info0 = NULL;
3864 ZERO_STRUCT(devmode_ctr);
3865 ZERO_STRUCT(secdesc_ctr);
3867 r.in.handle = handle;
3868 r.in.info_ctr = &info_ctr;
3869 r.in.devmode_ctr = &devmode_ctr;
3870 r.in.secdesc_ctr = &secdesc_ctr;
3871 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3873 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3875 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3877 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3879 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3881 return true;
3884 static bool test_printer_purge(struct torture_context *tctx,
3885 struct dcerpc_binding_handle *b,
3886 struct policy_handle *handle)
3888 NTSTATUS status;
3889 struct spoolss_SetPrinter r;
3890 struct spoolss_SetPrinterInfoCtr info_ctr;
3891 struct spoolss_DevmodeContainer devmode_ctr;
3892 struct sec_desc_buf secdesc_ctr;
3894 info_ctr.level = 0;
3895 info_ctr.info.info0 = NULL;
3897 ZERO_STRUCT(devmode_ctr);
3898 ZERO_STRUCT(secdesc_ctr);
3900 r.in.handle = handle;
3901 r.in.info_ctr = &info_ctr;
3902 r.in.devmode_ctr = &devmode_ctr;
3903 r.in.secdesc_ctr = &secdesc_ctr;
3904 r.in.command = SPOOLSS_PRINTER_CONTROL_PURGE;
3906 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PURGE\n");
3908 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3909 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3910 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3912 return true;
3915 static bool test_GetPrinterData_checktype(struct torture_context *tctx,
3916 struct dcerpc_binding_handle *b,
3917 struct policy_handle *handle,
3918 const char *value_name,
3919 enum winreg_Type *expected_type,
3920 enum winreg_Type *type_p,
3921 uint8_t **data_p,
3922 uint32_t *needed_p)
3924 NTSTATUS status;
3925 struct spoolss_GetPrinterData r;
3926 uint32_t needed;
3927 enum winreg_Type type;
3928 union spoolss_PrinterData data;
3930 r.in.handle = handle;
3931 r.in.value_name = value_name;
3932 r.in.offered = 0;
3933 r.out.needed = &needed;
3934 r.out.type = &type;
3935 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3937 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3939 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3940 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3942 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3943 if (expected_type) {
3944 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3946 r.in.offered = needed;
3947 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3948 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3949 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3952 torture_assert_werr_ok(tctx, r.out.result,
3953 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3955 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3957 if (type_p) {
3958 *type_p = type;
3961 if (data_p) {
3962 *data_p = r.out.data;
3965 if (needed_p) {
3966 *needed_p = needed;
3969 return true;
3972 static bool test_GetPrinterData(struct torture_context *tctx,
3973 struct dcerpc_binding_handle *b,
3974 struct policy_handle *handle,
3975 const char *value_name,
3976 enum winreg_Type *type_p,
3977 uint8_t **data_p,
3978 uint32_t *needed_p)
3980 return test_GetPrinterData_checktype(tctx, b, handle, value_name,
3981 NULL, type_p, data_p, needed_p);
3984 static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
3985 struct dcerpc_pipe *p,
3986 struct policy_handle *handle,
3987 const char *key_name,
3988 const char *value_name,
3989 enum winreg_Type *expected_type,
3990 enum winreg_Type *type_p,
3991 uint8_t **data_p,
3992 uint32_t *needed_p)
3994 NTSTATUS status;
3995 struct spoolss_GetPrinterDataEx r;
3996 enum winreg_Type type;
3997 uint32_t needed;
3998 union spoolss_PrinterData data;
3999 struct dcerpc_binding_handle *b = p->binding_handle;
4001 r.in.handle = handle;
4002 r.in.key_name = key_name;
4003 r.in.value_name = value_name;
4004 r.in.offered = 0;
4005 r.out.type = &type;
4006 r.out.needed = &needed;
4007 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
4009 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
4010 r.in.key_name, r.in.value_name);
4012 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
4013 if (!NT_STATUS_IS_OK(status)) {
4014 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
4015 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
4017 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
4020 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4021 if (expected_type) {
4022 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
4024 r.in.offered = needed;
4025 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
4026 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
4027 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
4030 torture_assert_werr_ok(tctx, r.out.result,
4031 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
4033 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
4035 if (type_p) {
4036 *type_p = type;
4039 if (data_p) {
4040 *data_p = r.out.data;
4043 if (needed_p) {
4044 *needed_p = needed;
4047 return true;
4050 static bool test_GetPrinterDataEx(struct torture_context *tctx,
4051 struct dcerpc_pipe *p,
4052 struct policy_handle *handle,
4053 const char *key_name,
4054 const char *value_name,
4055 enum winreg_Type *type_p,
4056 uint8_t **data_p,
4057 uint32_t *needed_p)
4059 return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
4060 NULL, type_p, data_p, needed_p);
4063 static bool test_get_environment(struct torture_context *tctx,
4064 struct dcerpc_binding_handle *b,
4065 struct policy_handle *handle,
4066 const char **architecture)
4068 DATA_BLOB blob;
4069 enum winreg_Type type;
4070 uint8_t *data;
4071 uint32_t needed;
4073 torture_assert(tctx,
4074 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
4075 "failed to get Architecture");
4077 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
4079 blob = data_blob_const(data, needed);
4080 *architecture = reg_val_data_string(tctx, REG_SZ, blob);
4082 return true;
4085 static bool test_GetPrinterData_list(struct torture_context *tctx,
4086 void *private_data)
4088 struct test_spoolss_context *ctx =
4089 talloc_get_type_abort(private_data, struct test_spoolss_context);
4090 struct dcerpc_pipe *p = ctx->spoolss_pipe;
4091 struct dcerpc_binding_handle *b = p->binding_handle;
4092 const char *list[] = {
4093 "W3SvcInstalled",
4094 "BeepEnabled",
4095 "EventLog",
4096 /* "NetPopup", not on w2k8 */
4097 /* "NetPopupToComputer", not on w2k8 */
4098 "MajorVersion",
4099 "MinorVersion",
4100 "DefaultSpoolDirectory",
4101 "Architecture",
4102 "DsPresent",
4103 "OSVersion",
4104 /* "OSVersionEx", not on s3 */
4105 "DNSMachineName"
4107 int i;
4109 for (i=0; i < ARRAY_SIZE(list); i++) {
4110 enum winreg_Type type, type_ex;
4111 uint8_t *data, *data_ex;
4112 uint32_t needed, needed_ex;
4114 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
4115 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
4116 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
4117 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
4118 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
4119 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
4120 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
4123 return true;
4126 static bool test_EnumPrinterData(struct torture_context *tctx,
4127 struct dcerpc_pipe *p,
4128 struct policy_handle *handle,
4129 uint32_t enum_index,
4130 uint32_t value_offered,
4131 uint32_t data_offered,
4132 enum winreg_Type *type_p,
4133 uint32_t *value_needed_p,
4134 uint32_t *data_needed_p,
4135 const char **value_name_p,
4136 uint8_t **data_p,
4137 WERROR *result_p)
4139 struct spoolss_EnumPrinterData r;
4140 uint32_t data_needed;
4141 uint32_t value_needed;
4142 enum winreg_Type type;
4143 struct dcerpc_binding_handle *b = p->binding_handle;
4145 r.in.handle = handle;
4146 r.in.enum_index = enum_index;
4147 r.in.value_offered = value_offered;
4148 r.in.data_offered = data_offered;
4149 r.out.data_needed = &data_needed;
4150 r.out.value_needed = &value_needed;
4151 r.out.type = &type;
4152 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
4153 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
4155 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
4157 torture_assert_ntstatus_ok(tctx,
4158 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
4159 "EnumPrinterData failed");
4161 if (type_p) {
4162 *type_p = type;
4164 if (value_needed_p) {
4165 *value_needed_p = value_needed;
4167 if (data_needed_p) {
4168 *data_needed_p = data_needed;
4170 if (value_name_p) {
4171 *value_name_p = r.out.value_name;
4173 if (data_p) {
4174 *data_p = r.out.data;
4176 if (result_p) {
4177 *result_p = r.out.result;
4180 return true;
4184 static bool test_EnumPrinterData_all(struct torture_context *tctx,
4185 struct dcerpc_pipe *p,
4186 struct policy_handle *handle)
4188 uint32_t enum_index = 0;
4189 enum winreg_Type type;
4190 uint32_t value_needed;
4191 uint32_t data_needed;
4192 uint8_t *data;
4193 const char *value_name;
4194 WERROR result;
4196 torture_comment(tctx, "Testing EnumPrinterData\n");
4198 do {
4199 torture_assert(tctx,
4200 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
4201 &type, &value_needed, &data_needed,
4202 &value_name, &data, &result),
4203 "EnumPrinterData failed");
4205 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
4206 break;
4209 torture_assert(tctx,
4210 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
4211 &type, &value_needed, &data_needed,
4212 &value_name, &data, &result),
4213 "EnumPrinterData failed");
4215 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
4216 break;
4219 enum_index++;
4221 } while (W_ERROR_IS_OK(result));
4223 torture_comment(tctx, "EnumPrinterData test succeeded\n");
4225 return true;
4228 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
4229 struct dcerpc_binding_handle *b,
4230 struct policy_handle *handle,
4231 const char *key_name,
4232 uint32_t *count_p,
4233 struct spoolss_PrinterEnumValues **info_p)
4235 struct spoolss_EnumPrinterDataEx r;
4236 struct spoolss_PrinterEnumValues *info;
4237 uint32_t needed;
4238 uint32_t count;
4240 r.in.handle = handle;
4241 r.in.key_name = key_name;
4242 r.in.offered = 0;
4243 r.out.needed = &needed;
4244 r.out.count = &count;
4245 r.out.info = &info;
4247 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
4249 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
4250 "EnumPrinterDataEx failed");
4251 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4252 r.in.offered = needed;
4253 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
4254 "EnumPrinterDataEx failed");
4257 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
4259 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
4261 if (count_p) {
4262 *count_p = count;
4264 if (info_p) {
4265 *info_p = info;
4268 return true;
4271 static bool test_SetPrinterData(struct torture_context *tctx,
4272 struct dcerpc_binding_handle *b,
4273 struct policy_handle *handle,
4274 const char *value_name,
4275 enum winreg_Type type,
4276 uint8_t *data,
4277 uint32_t offered);
4278 static bool test_DeletePrinterData(struct torture_context *tctx,
4279 struct dcerpc_binding_handle *b,
4280 struct policy_handle *handle,
4281 const char *value_name);
4283 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
4284 struct dcerpc_pipe *p,
4285 struct policy_handle *handle)
4287 uint32_t count;
4288 struct spoolss_PrinterEnumValues *info;
4289 int i;
4290 uint32_t value_needed, data_needed;
4291 uint32_t value_offered, data_offered;
4292 WERROR result;
4293 struct dcerpc_binding_handle *b = p->binding_handle;
4295 enum winreg_Type type;
4296 DATA_BLOB blob;
4298 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
4300 torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
4301 type = REG_SZ;
4303 torture_assert(tctx,
4304 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
4305 "SetPrinterData failed");
4307 blob = data_blob_string_const("torture_data2");
4309 torture_assert(tctx,
4310 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
4311 "SetPrinterData failed");
4313 blob = data_blob_talloc(tctx, NULL, 4);
4314 SIVAL(blob.data, 0, 0x11223344);
4316 torture_assert(tctx,
4317 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
4318 "SetPrinterData failed");
4320 torture_assert(tctx,
4321 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
4322 "failed to call EnumPrinterDataEx");
4324 /* get the max sizes for value and data */
4326 torture_assert(tctx,
4327 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
4328 NULL, &value_needed, &data_needed,
4329 NULL, NULL, &result),
4330 "EnumPrinterData failed");
4331 torture_assert_werr_ok(tctx, result, "unexpected result");
4333 /* check if the reply from the EnumPrinterData really matches max values */
4335 for (i=0; i < count; i++) {
4336 if (info[i].value_name_len > value_needed) {
4337 torture_fail(tctx,
4338 talloc_asprintf(tctx,
4339 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
4340 info[i].value_name_len, value_needed));
4342 if (info[i].data_length > data_needed) {
4343 torture_fail(tctx,
4344 talloc_asprintf(tctx,
4345 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
4346 info[i].data_length, data_needed));
4350 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
4351 * sort or not sort the replies by value name, we should be able to do
4352 * the following entry comparison */
4354 data_offered = data_needed;
4355 value_offered = value_needed;
4357 for (i=0; i < count; i++) {
4359 const char *value_name;
4360 uint8_t *data;
4362 torture_assert(tctx,
4363 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
4364 &type, &value_needed, &data_needed,
4365 &value_name, &data, &result),
4366 "EnumPrinterData failed");
4368 if (i -1 == count) {
4369 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
4370 "unexpected result");
4371 break;
4372 } else {
4373 torture_assert_werr_ok(tctx, result, "unexpected result");
4376 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
4377 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
4378 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
4379 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
4380 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
4383 torture_assert(tctx,
4384 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
4385 "DeletePrinterData failed");
4386 torture_assert(tctx,
4387 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
4388 "DeletePrinterData failed");
4389 torture_assert(tctx,
4390 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
4391 "DeletePrinterData failed");
4393 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4395 return true;
4398 static bool test_DeletePrinterData(struct torture_context *tctx,
4399 struct dcerpc_binding_handle *b,
4400 struct policy_handle *handle,
4401 const char *value_name)
4403 NTSTATUS status;
4404 struct spoolss_DeletePrinterData r;
4406 r.in.handle = handle;
4407 r.in.value_name = value_name;
4409 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
4410 r.in.value_name);
4412 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
4414 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
4415 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
4417 return true;
4420 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
4421 struct dcerpc_binding_handle *b,
4422 struct policy_handle *handle,
4423 const char *key_name,
4424 const char *value_name)
4426 struct spoolss_DeletePrinterDataEx r;
4428 r.in.handle = handle;
4429 r.in.key_name = key_name;
4430 r.in.value_name = value_name;
4432 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
4433 r.in.key_name, r.in.value_name);
4435 torture_assert_ntstatus_ok(tctx,
4436 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
4437 "DeletePrinterDataEx failed");
4438 torture_assert_werr_ok(tctx, r.out.result,
4439 "DeletePrinterDataEx failed");
4441 return true;
4444 static bool test_DeletePrinterKey(struct torture_context *tctx,
4445 struct dcerpc_binding_handle *b,
4446 struct policy_handle *handle,
4447 const char *key_name)
4449 struct spoolss_DeletePrinterKey r;
4451 r.in.handle = handle;
4452 r.in.key_name = key_name;
4454 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
4456 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
4457 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
4458 return true;
4461 torture_assert_ntstatus_ok(tctx,
4462 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
4463 "DeletePrinterKey failed");
4464 torture_assert_werr_ok(tctx, r.out.result,
4465 "DeletePrinterKey failed");
4467 return true;
4470 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4471 struct dcerpc_binding_handle *b,
4472 struct policy_handle *handle)
4474 struct winreg_OpenHKLM r;
4476 r.in.system_name = NULL;
4477 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4478 r.out.handle = handle;
4480 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4482 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4483 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4485 return true;
4488 static void init_winreg_String(struct winreg_String *name, const char *s)
4490 name->name = s;
4491 if (s) {
4492 name->name_len = 2 * (strlen_m(s) + 1);
4493 name->name_size = name->name_len;
4494 } else {
4495 name->name_len = 0;
4496 name->name_size = 0;
4500 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4501 struct dcerpc_binding_handle *b,
4502 struct policy_handle *hive_handle,
4503 const char *keyname,
4504 uint32_t options,
4505 struct policy_handle *key_handle)
4507 struct winreg_OpenKey r;
4509 r.in.parent_handle = hive_handle;
4510 init_winreg_String(&r.in.keyname, keyname);
4511 r.in.options = options;
4512 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4513 r.out.handle = key_handle;
4515 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4517 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4518 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4520 return true;
4523 static bool test_winreg_OpenKey(struct torture_context *tctx,
4524 struct dcerpc_binding_handle *b,
4525 struct policy_handle *hive_handle,
4526 const char *keyname,
4527 struct policy_handle *key_handle)
4529 return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4530 REG_OPTION_NON_VOLATILE, key_handle);
4533 static bool test_winreg_CloseKey(struct torture_context *tctx,
4534 struct dcerpc_binding_handle *b,
4535 struct policy_handle *handle)
4537 struct winreg_CloseKey r;
4539 r.in.handle = handle;
4540 r.out.handle = handle;
4542 torture_comment(tctx, "Testing winreg_CloseKey\n");
4544 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4545 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4547 return true;
4550 bool test_winreg_QueryValue(struct torture_context *tctx,
4551 struct dcerpc_binding_handle *b,
4552 struct policy_handle *handle,
4553 const char *value_name,
4554 enum winreg_Type *type_p,
4555 uint32_t *data_size_p,
4556 uint32_t *data_length_p,
4557 uint8_t **data_p)
4559 struct winreg_QueryValue r;
4560 enum winreg_Type type = REG_NONE;
4561 uint32_t data_size = 0;
4562 uint32_t data_length = 0;
4563 struct winreg_String valuename;
4564 uint8_t *data = NULL;
4566 init_winreg_String(&valuename, value_name);
4568 data = talloc_zero_array(tctx, uint8_t, 0);
4570 r.in.handle = handle;
4571 r.in.value_name = &valuename;
4572 r.in.type = &type;
4573 r.in.data_size = &data_size;
4574 r.in.data_length = &data_length;
4575 r.in.data = data;
4576 r.out.type = &type;
4577 r.out.data = data;
4578 r.out.data_size = &data_size;
4579 r.out.data_length = &data_length;
4581 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4583 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4584 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4585 *r.in.data_size = *r.out.data_size;
4586 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4587 r.in.data = data;
4588 r.out.data = data;
4589 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4591 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4593 if (type_p) {
4594 *type_p = *r.out.type;
4596 if (data_size_p) {
4597 *data_size_p = *r.out.data_size;
4599 if (data_length_p) {
4600 *data_length_p = *r.out.data_length;
4602 if (data_p) {
4603 *data_p = r.out.data;
4606 return true;
4609 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4610 struct dcerpc_binding_handle *b,
4611 struct policy_handle *handle,
4612 const char *printer_name,
4613 const char *key_name,
4614 const char *value_name,
4615 enum winreg_Type *w_type,
4616 uint32_t *w_size,
4617 uint32_t *w_length,
4618 uint8_t **w_data)
4620 const char *printer_key;
4621 struct policy_handle key_handle;
4623 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4624 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4626 torture_assert(tctx,
4627 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4629 torture_assert(tctx,
4630 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4632 torture_assert(tctx,
4633 test_winreg_CloseKey(tctx, b, &key_handle), "");
4635 return true;
4638 static bool test_GetForm_winreg(struct torture_context *tctx,
4639 struct dcerpc_binding_handle *b,
4640 struct policy_handle *handle,
4641 const char *key_name,
4642 const char *form_name,
4643 enum winreg_Type *w_type,
4644 uint32_t *w_size,
4645 uint32_t *w_length,
4646 uint8_t **w_data)
4648 struct policy_handle key_handle;
4650 torture_assert(tctx,
4651 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4653 torture_assert(tctx,
4654 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4656 torture_assert(tctx,
4657 test_winreg_CloseKey(tctx, b, &key_handle), "");
4659 return true;
4662 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4663 struct dcerpc_binding_handle *b,
4664 struct policy_handle *handle,
4665 const char *symlink_keyname,
4666 const char *symlink_destination)
4668 /* check if the first key is a symlink to the second key */
4670 enum winreg_Type w_type;
4671 uint32_t w_size;
4672 uint32_t w_length;
4673 uint8_t *w_data;
4674 struct policy_handle key_handle;
4675 DATA_BLOB blob;
4676 const char *str;
4678 if (torture_setting_bool(tctx, "samba3", false)) {
4679 torture_skip(tctx, "skip winreg symlink test against samba");
4682 torture_assert(tctx,
4683 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4684 "failed to open key link");
4686 torture_assert(tctx,
4687 test_winreg_QueryValue(tctx, b, &key_handle,
4688 "SymbolicLinkValue",
4689 &w_type, &w_size, &w_length, &w_data),
4690 "failed to query for 'SymbolicLinkValue' attribute");
4692 torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4694 blob = data_blob(w_data, w_size);
4695 str = reg_val_data_string(tctx, REG_SZ, blob);
4697 torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4699 torture_assert(tctx,
4700 test_winreg_CloseKey(tctx, b, &key_handle),
4701 "failed to close key link");
4703 return true;
4706 static const char *strip_unc(const char *unc)
4708 char *name;
4710 if (!unc) {
4711 return NULL;
4714 if (unc[0] == '\\' && unc[1] == '\\') {
4715 unc +=2;
4718 name = strchr(unc, '\\');
4719 if (name) {
4720 return name+1;
4723 return unc;
4726 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4727 struct dcerpc_binding_handle *b,
4728 struct policy_handle *handle,
4729 const char *printer_name,
4730 struct dcerpc_binding_handle *winreg_handle,
4731 struct policy_handle *hive_handle)
4733 union spoolss_PrinterInfo info;
4734 const char *keys[] = {
4735 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4736 TOP_LEVEL_PRINT_PRINTERS_KEY
4738 int i;
4739 const char *printername, *sharename;
4741 torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4743 torture_assert(tctx,
4744 test_GetPrinter_level(tctx, b, handle, 2, &info),
4745 "failed to get printer info level 2");
4747 printername = strip_unc(info.info2.printername);
4748 sharename = strip_unc(info.info2.sharename);
4750 #define test_sz(wname, iname) \
4751 do {\
4752 DATA_BLOB blob;\
4753 const char *str;\
4754 enum winreg_Type w_type;\
4755 uint32_t w_size;\
4756 uint32_t w_length;\
4757 uint8_t *w_data;\
4758 torture_assert(tctx,\
4759 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4760 &w_type, &w_size, &w_length, &w_data),\
4761 "failed to query winreg");\
4762 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4763 blob = data_blob(w_data, w_size);\
4764 str = reg_val_data_string(tctx, REG_SZ, blob);\
4765 if (w_size == 2 && iname == NULL) {\
4766 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4767 } else {\
4768 torture_assert_str_equal(tctx, str, iname,\
4769 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4771 } while(0);
4773 #define test_dword(wname, iname) \
4774 do {\
4775 uint32_t value;\
4776 enum winreg_Type w_type;\
4777 uint32_t w_size;\
4778 uint32_t w_length;\
4779 uint8_t *w_data;\
4780 torture_assert(tctx,\
4781 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4782 &w_type, &w_size, &w_length, &w_data),\
4783 "failed to query winreg");\
4784 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4785 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4786 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4787 value = IVAL(w_data, 0);\
4788 torture_assert_int_equal(tctx, value, iname,\
4789 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4790 } while(0);
4792 #define test_binary(wname, iname) \
4793 do {\
4794 enum winreg_Type w_type;\
4795 uint32_t w_size;\
4796 uint32_t w_length;\
4797 uint8_t *w_data;\
4798 torture_assert(tctx,\
4799 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4800 &w_type, &w_size, &w_length, &w_data),\
4801 "failed to query winreg");\
4802 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4803 torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4804 torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4805 "binary unequal");\
4806 } while(0);
4809 #define test_dm(wname, iname) \
4810 do {\
4811 DATA_BLOB blob;\
4812 struct spoolss_DeviceMode dm;\
4813 enum ndr_err_code ndr_err;\
4814 enum winreg_Type w_type;\
4815 uint32_t w_size;\
4816 uint32_t w_length;\
4817 uint8_t *w_data;\
4818 torture_assert(tctx,\
4819 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4820 &w_type, &w_size, &w_length, &w_data),\
4821 "failed to query winreg");\
4822 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4823 blob = data_blob(w_data, w_size);\
4824 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4825 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4826 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4827 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4828 "dm unequal");\
4829 } while(0);
4831 #define test_sd(wname, iname) \
4832 do {\
4833 DATA_BLOB blob;\
4834 struct security_descriptor sd;\
4835 enum ndr_err_code ndr_err;\
4836 enum winreg_Type w_type;\
4837 uint32_t w_size;\
4838 uint32_t w_length;\
4839 uint8_t *w_data;\
4840 torture_assert(tctx,\
4841 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4842 &w_type, &w_size, &w_length, &w_data),\
4843 "failed to query winreg");\
4844 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4845 blob = data_blob(w_data, w_size);\
4846 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4847 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4848 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4849 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4850 "sd unequal");\
4851 } while(0);
4853 #define test_multi_sz(wname, iname) \
4854 do {\
4855 DATA_BLOB blob;\
4856 const char **array;\
4857 enum winreg_Type w_type;\
4858 uint32_t w_size;\
4859 uint32_t w_length;\
4860 uint8_t *w_data;\
4861 int i;\
4862 torture_assert(tctx,\
4863 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4864 &w_type, &w_size, &w_length, &w_data),\
4865 "failed to query winreg");\
4866 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4867 blob = data_blob(w_data, w_size);\
4868 torture_assert(tctx, \
4869 pull_reg_multi_sz(tctx, &blob, &array),\
4870 "failed to pull multi sz");\
4871 for (i=0; array[i] != NULL; i++) {\
4872 torture_assert_str_equal(tctx, array[i], iname[i],\
4873 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4875 } while(0);
4877 if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4878 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4879 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4881 torture_warning(tctx, "failed to check for winreg symlink");
4884 for (i=0; i < ARRAY_SIZE(keys); i++) {
4886 const char *printer_key;
4887 struct policy_handle key_handle;
4889 printer_key = talloc_asprintf(tctx, "%s\\%s",
4890 keys[i], printer_name);
4892 torture_assert(tctx,
4893 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4895 test_sz("Name", printername);
4896 test_sz("Share Name", sharename);
4897 test_sz("Port", info.info2.portname);
4898 test_sz("Printer Driver", info.info2.drivername);
4899 test_sz("Description", info.info2.comment);
4900 test_sz("Location", info.info2.location);
4901 test_sz("Separator File", info.info2.sepfile);
4902 test_sz("Print Processor", info.info2.printprocessor);
4903 test_sz("Datatype", info.info2.datatype);
4904 test_sz("Parameters", info.info2.parameters);
4905 /* winreg: 0, spoolss not */
4906 /* test_dword("Attributes", info.info2.attributes); */
4907 test_dword("Priority", info.info2.priority);
4908 test_dword("Default Priority", info.info2.defaultpriority);
4909 /* winreg: 60, spoolss: 0 */
4910 /* test_dword("StartTime", info.info2.starttime); */
4911 /* test_dword("UntilTime", info.info2.untiltime); */
4912 /* winreg != spoolss */
4913 /* test_dword("Status", info.info2.status); */
4914 test_dm("Default DevMode", info.info2.devmode);
4915 test_sd("Security", info.info2.secdesc);
4917 torture_assert(tctx,
4918 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4921 #undef test_dm
4922 #undef test_sd
4924 torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4926 return true;
4929 static bool test_PrintProcessors(struct torture_context *tctx,
4930 struct dcerpc_binding_handle *b,
4931 const char *environment,
4932 struct dcerpc_binding_handle *winreg_handle,
4933 struct policy_handle *hive_handle)
4935 union spoolss_PrintProcessorInfo *info;
4936 uint32_t count;
4937 int i;
4939 torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4941 torture_assert(tctx,
4942 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
4943 "failed to enum print processors level 1");
4945 for (i=0; i < count; i++) {
4947 const char *processor_key;
4948 struct policy_handle key_handle;
4950 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4951 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4952 environment,
4953 info[i].info1.print_processor_name);
4955 torture_assert(tctx,
4956 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4958 /* nothing to check in there so far */
4960 torture_assert(tctx,
4961 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4964 torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4966 return true;
4969 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4970 struct dcerpc_binding_handle *b,
4971 struct policy_handle *handle,
4972 const char *driver_name,
4973 const char *architecture,
4974 uint32_t level,
4975 uint32_t client_major_version,
4976 uint32_t client_minor_version,
4977 union spoolss_DriverInfo *info_p,
4978 WERROR *result);
4980 static const char *strip_path(const char *path)
4982 char *p;
4984 if (path == NULL) {
4985 return NULL;
4988 p = strrchr(path, '\\');
4989 if (p) {
4990 return p+1;
4993 return path;
4996 static const char **strip_paths(const char **path_array)
4998 int i;
5000 if (path_array == NULL) {
5001 return NULL;
5004 for (i=0; path_array[i] != NULL; i++) {
5005 path_array[i] = strip_path(path_array[i]);
5008 return path_array;
5011 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
5013 time_t t;
5014 struct tm *tm;
5016 if (nt == 0) {
5017 return talloc_strdup(mem_ctx, "01/01/1601");
5020 t = nt_time_to_unix(nt);
5021 tm = localtime(&t);
5023 return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
5024 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
5027 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
5029 return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
5030 (unsigned)((v >> 48) & 0xFFFF),
5031 (unsigned)((v >> 32) & 0xFFFF),
5032 (unsigned)((v >> 16) & 0xFFFF),
5033 (unsigned)(v & 0xFFFF));
5036 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
5037 struct dcerpc_binding_handle *b,
5038 struct policy_handle *handle,
5039 const char *printer_name,
5040 const char *driver_name,
5041 const char *environment,
5042 enum spoolss_DriverOSVersion version,
5043 struct dcerpc_binding_handle *winreg_handle,
5044 struct policy_handle *hive_handle,
5045 const char *server_name_slash)
5047 WERROR result = WERR_OK;
5048 union spoolss_DriverInfo info;
5049 const char *driver_key;
5050 struct policy_handle key_handle;
5052 const char *driver_path;
5053 const char *data_file;
5054 const char *config_file;
5055 const char *help_file;
5056 const char **dependent_files;
5058 const char *driver_date;
5059 const char *inbox_driver_date;
5061 const char *driver_version;
5062 const char *inbox_driver_version;
5064 ZERO_STRUCT(key_handle);
5066 torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
5068 driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
5069 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
5070 environment,
5071 version,
5072 driver_name);
5074 torture_assert(tctx,
5075 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
5076 "failed to open driver key");
5078 if (torture_setting_bool(tctx, "samba3", false) ||
5079 torture_setting_bool(tctx, "w2k3", false)) {
5080 goto try_level6;
5083 if (handle) {
5084 torture_assert(tctx,
5085 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
5086 "failed to get driver info level 8");
5087 } else {
5088 torture_assert(tctx,
5089 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
5090 "failed to get driver info level 8");
5093 if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
5094 goto try_level6;
5097 driver_path = strip_path(info.info8.driver_path);
5098 data_file = strip_path(info.info8.data_file);
5099 config_file = strip_path(info.info8.config_file);
5100 help_file = strip_path(info.info8.help_file);
5101 dependent_files = strip_paths(info.info8.dependent_files);
5103 driver_date = driver_winreg_date(tctx, info.info8.driver_date);
5104 inbox_driver_date = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
5106 driver_version = driver_winreg_version(tctx, info.info8.driver_version);
5107 inbox_driver_version = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
5109 test_sz("Configuration File", config_file);
5110 test_sz("Data File", data_file);
5111 test_sz("Datatype", info.info8.default_datatype);
5112 test_sz("Driver", driver_path);
5113 test_sz("DriverDate", driver_date);
5114 test_sz("DriverVersion", driver_version);
5115 test_sz("HardwareID", info.info8.hardware_id);
5116 test_sz("Help File", help_file);
5117 test_sz("InfPath", info.info8.inf_path);
5118 test_sz("Manufacturer", info.info8.manufacturer_name);
5119 test_sz("MinInboxDriverVerDate", inbox_driver_date);
5120 test_sz("MinInboxDriverVerVersion", inbox_driver_version);
5121 test_sz("Monitor", info.info8.monitor_name);
5122 test_sz("OEM URL", info.info8.manufacturer_url);
5123 test_sz("Print Processor", info.info8.print_processor);
5124 test_sz("Provider", info.info8.provider);
5125 test_sz("VendorSetup", info.info8.vendor_setup);
5126 test_multi_sz("ColorProfiles", info.info8.color_profiles);
5127 test_multi_sz("Dependent Files", dependent_files);
5128 test_multi_sz("CoreDependencies", info.info8.core_driver_dependencies);
5129 test_multi_sz("Previous Names", info.info8.previous_names);
5130 /* test_dword("Attributes", ?); */
5131 test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
5132 test_dword("Version", info.info8.version);
5133 /* test_dword("TempDir", ?); */
5135 try_level6:
5137 if (handle) {
5138 torture_assert(tctx,
5139 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
5140 "failed to get driver info level 6");
5141 } else {
5142 torture_assert(tctx,
5143 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
5144 "failed to get driver info level 6");
5147 driver_path = strip_path(info.info6.driver_path);
5148 data_file = strip_path(info.info6.data_file);
5149 config_file = strip_path(info.info6.config_file);
5150 help_file = strip_path(info.info6.help_file);
5151 dependent_files = strip_paths(info.info6.dependent_files);
5153 driver_date = driver_winreg_date(tctx, info.info6.driver_date);
5155 driver_version = driver_winreg_version(tctx, info.info6.driver_version);
5157 test_sz("Configuration File", config_file);
5158 test_sz("Data File", data_file);
5159 test_sz("Datatype", info.info6.default_datatype);
5160 test_sz("Driver", driver_path);
5161 if (torture_setting_bool(tctx, "w2k3", false)) {
5162 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
5163 push_nttime(blob.data, 0, info.info6.driver_date);
5164 test_binary("DriverDate", blob);
5165 SBVAL(blob.data, 0, info.info6.driver_version);
5166 test_binary("DriverVersion", blob);
5167 } else {
5168 test_sz("DriverDate", driver_date);
5169 test_sz("DriverVersion", driver_version);
5171 test_sz("HardwareID", info.info6.hardware_id);
5172 test_sz("Help File", help_file);
5173 test_sz("Manufacturer", info.info6.manufacturer_name);
5174 test_sz("Monitor", info.info6.monitor_name);
5175 test_sz("OEM URL", info.info6.manufacturer_url);
5176 test_sz("Provider", info.info6.provider);
5177 test_multi_sz("Dependent Files", dependent_files);
5178 test_multi_sz("Previous Names", info.info6.previous_names);
5179 /* test_dword("Attributes", ?); */
5180 test_dword("Version", info.info6.version);
5181 /* test_dword("TempDir", ?); */
5183 if (handle) {
5184 torture_assert(tctx,
5185 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
5186 "failed to get driver info level 3");
5187 } else {
5188 torture_assert(tctx,
5189 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
5190 "failed to get driver info level 3");
5193 driver_path = strip_path(info.info3.driver_path);
5194 data_file = strip_path(info.info3.data_file);
5195 config_file = strip_path(info.info3.config_file);
5196 help_file = strip_path(info.info3.help_file);
5197 dependent_files = strip_paths(info.info3.dependent_files);
5199 test_sz("Configuration File", config_file);
5200 test_sz("Data File", data_file);
5201 test_sz("Datatype", info.info3.default_datatype);
5202 test_sz("Driver", driver_path);
5203 test_sz("Help File", help_file);
5204 test_sz("Monitor", info.info3.monitor_name);
5205 test_multi_sz("Dependent Files", dependent_files);
5206 /* test_dword("Attributes", ?); */
5207 test_dword("Version", info.info3.version);
5208 /* test_dword("TempDir", ?); */
5211 torture_assert(tctx,
5212 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
5214 torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
5216 return true;
5219 #undef test_sz
5220 #undef test_dword
5222 static bool test_SetPrinterData(struct torture_context *tctx,
5223 struct dcerpc_binding_handle *b,
5224 struct policy_handle *handle,
5225 const char *value_name,
5226 enum winreg_Type type,
5227 uint8_t *data,
5228 uint32_t offered)
5230 struct spoolss_SetPrinterData r;
5232 r.in.handle = handle;
5233 r.in.value_name = value_name;
5234 r.in.type = type;
5235 r.in.data = data;
5236 r.in.offered = offered;
5238 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
5239 r.in.value_name);
5241 torture_assert_ntstatus_ok(tctx,
5242 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
5243 "SetPrinterData failed");
5244 torture_assert_werr_ok(tctx, r.out.result,
5245 "SetPrinterData failed");
5247 return true;
5250 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
5251 struct dcerpc_binding_handle *b,
5252 struct policy_handle *handle,
5253 const char *printer_name,
5254 struct dcerpc_binding_handle *winreg_handle,
5255 struct policy_handle *hive_handle)
5257 const char *values[] = {
5258 "spootyfoot",
5259 "spooty\\foot",
5260 #if 0
5261 /* FIXME: not working with s3 atm. */
5262 "spooty,foot",
5263 "spooty,fo,ot",
5264 #endif
5265 "spooty foot",
5266 #if 0
5267 /* FIXME: not working with s3 atm. */
5268 "spooty\\fo,ot",
5269 "spooty,fo\\ot"
5270 #endif
5272 int i;
5274 for (i=0; i < ARRAY_SIZE(values); i++) {
5276 enum winreg_Type type, expected_type = REG_SZ;
5277 DATA_BLOB blob;
5278 uint8_t *data;
5279 uint32_t needed;
5281 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
5282 type = REG_SZ;
5284 torture_assert(tctx,
5285 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
5286 "SetPrinterData failed");
5288 torture_assert(tctx,
5289 test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
5290 "GetPrinterData failed");
5292 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
5293 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
5294 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
5296 if (winreg_handle && hive_handle) {
5298 enum winreg_Type w_type;
5299 uint32_t w_size;
5300 uint32_t w_length;
5301 uint8_t *w_data;
5303 torture_assert(tctx,
5304 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5305 printer_name, "PrinterDriverData", values[i],
5306 &w_type, &w_size, &w_length, &w_data), "");
5308 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
5309 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
5310 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
5311 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
5314 torture_assert(tctx,
5315 test_DeletePrinterData(tctx, b, handle, values[i]),
5316 "DeletePrinterData failed");
5319 return true;
5323 static bool test_EnumPrinterKey(struct torture_context *tctx,
5324 struct dcerpc_binding_handle *b,
5325 struct policy_handle *handle,
5326 const char *key_name,
5327 const char ***array);
5329 static bool test_SetPrinterDataEx(struct torture_context *tctx,
5330 struct dcerpc_binding_handle *b,
5331 struct policy_handle *handle,
5332 const char *key_name,
5333 const char *value_name,
5334 enum winreg_Type type,
5335 uint8_t *data,
5336 uint32_t offered)
5338 NTSTATUS status;
5339 struct spoolss_SetPrinterDataEx r;
5341 r.in.handle = handle;
5342 r.in.key_name = key_name;
5343 r.in.value_name = value_name;
5344 r.in.type = type;
5345 r.in.data = data;
5346 r.in.offered = offered;
5348 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
5349 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
5351 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
5353 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
5354 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
5356 return true;
5359 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
5360 struct dcerpc_pipe *p,
5361 struct policy_handle *handle)
5363 struct dcerpc_binding_handle *b = p->binding_handle;
5364 const char *value_name = "dog";
5365 const char *keys[] = {
5366 "torturedataex",
5367 "torture data ex",
5368 "torturedataex_with_subkey\\subkey",
5369 "torturedataex_with_subkey\\subkey:0",
5370 "torturedataex_with_subkey\\subkey:1",
5371 "torturedataex_with_subkey\\subkey\\subsubkey",
5372 "torturedataex_with_subkey\\subkey\\subsubkey:0",
5373 "torturedataex_with_subkey\\subkey\\subsubkey:1",
5374 "torture,data",
5375 "torture,data,ex",
5376 "torture,data\\ex",
5377 "torture\\data,ex",
5378 "torture/data",
5379 "torture/data ex",
5380 "torture/data ex/sub",
5381 "torture//data",
5382 "torture//data ex",
5383 "torture//data ex/sub",
5384 "torture//data ex//sub",
5386 int i;
5388 for (i=0; i < ARRAY_SIZE(keys); i++) {
5390 char *c;
5391 const char *key;
5392 enum winreg_Type type;
5393 DATA_BLOB blob_in, blob_out;
5394 const char **subkeys;
5395 uint32_t ecount;
5396 struct spoolss_PrinterEnumValues *einfo;
5397 uint32_t needed;
5399 blob_in = data_blob_talloc(tctx, NULL, 42);
5401 generate_random_buffer(blob_in.data, blob_in.length);
5403 torture_assert(tctx,
5404 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
5405 "failed to call SetPrinterDataEx");
5407 torture_assert(tctx,
5408 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
5409 "failed to call GetPrinterDataEx");
5411 blob_out.length = needed;
5412 torture_assert(tctx,
5413 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
5414 "failed to call EnumPrinterDataEx");
5416 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5417 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5418 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5420 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5421 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5422 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5423 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5424 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5425 if (einfo[0].data_length > 0) {
5426 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5429 key = talloc_strdup(tctx, keys[i]);
5431 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
5432 return false;
5435 c = strchr(key, '\\');
5436 if (c) {
5437 int k;
5439 /* we have subkeys */
5441 *c = 0;
5443 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
5444 return false;
5447 for (k=0; subkeys && subkeys[k]; k++) {
5449 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
5451 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
5452 return false;
5456 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5457 return false;
5460 } else {
5461 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5462 return false;
5467 return true;
5470 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
5471 struct dcerpc_pipe *p,
5472 struct policy_handle *handle)
5474 struct dcerpc_binding_handle *b = p->binding_handle;
5475 const char *key = "torturedataex";
5476 const char *values[] = {
5477 "torture_value",
5478 "torture value",
5479 "torture,value",
5480 "torture/value",
5481 "torture\\value",
5482 "torture\\\\value"
5484 int i;
5486 for (i=0; i < ARRAY_SIZE(values); i++) {
5488 enum winreg_Type type;
5489 DATA_BLOB blob_in, blob_out;
5490 uint32_t ecount;
5491 struct spoolss_PrinterEnumValues *einfo;
5492 uint32_t needed;
5494 if (torture_setting_bool(tctx, "samba3", false)) {
5495 char *q;
5496 q = strrchr(values[i], ',');
5497 if (q) {
5498 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
5499 values[i]);
5500 continue;
5504 blob_in = data_blob_talloc(tctx, NULL, 42);
5506 generate_random_buffer(blob_in.data, blob_in.length);
5508 torture_assert(tctx,
5509 test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
5510 "failed to call SetPrinterDataEx");
5512 torture_assert(tctx,
5513 test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
5514 "failed to call GetPrinterDataEx");
5516 blob_out.length = needed;
5517 torture_assert(tctx,
5518 test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
5519 "failed to call EnumPrinterDataEx");
5521 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5522 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5523 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5525 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5526 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5527 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5528 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5529 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5530 if (einfo[0].data_length > 0) {
5531 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5534 torture_assert(tctx,
5535 test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5536 "failed to call DeletePrinterDataEx");
5539 return true;
5543 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5544 struct dcerpc_pipe *p,
5545 struct policy_handle *handle,
5546 const char *printername,
5547 struct dcerpc_binding_handle *winreg_handle,
5548 struct policy_handle *hive_handle)
5550 struct dcerpc_binding_handle *b = p->binding_handle;
5551 const char *value_name = "dog";
5552 const char *key_name = "torturedataex";
5553 enum winreg_Type types[] = {
5554 REG_SZ,
5555 REG_MULTI_SZ,
5556 REG_DWORD,
5557 REG_BINARY
5559 const char *str = "abcdefghi";
5560 int t, s;
5562 for (t=0; t < ARRAY_SIZE(types); t++) {
5563 for (s=0; s < strlen(str); s++) {
5565 enum winreg_Type type;
5566 const char *string = talloc_strndup(tctx, str, s);
5567 const char *array[2];
5568 DATA_BLOB blob = data_blob_string_const(string);
5569 DATA_BLOB data;
5570 uint8_t *data_out;
5571 uint32_t needed, offered = 0;
5572 uint32_t ecount;
5573 struct spoolss_PrinterEnumValues *einfo;
5575 array[0] = talloc_strdup(tctx, string);
5576 array[1] = NULL;
5578 if (types[t] == REG_DWORD) {
5579 s = 0xffff;
5582 switch (types[t]) {
5583 case REG_BINARY:
5584 data = blob;
5585 offered = blob.length;
5586 break;
5587 case REG_DWORD:
5588 data = data_blob_talloc(tctx, NULL, 4);
5589 SIVAL(data.data, 0, 0x12345678);
5590 offered = 4;
5591 break;
5592 case REG_SZ:
5593 torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5594 type = REG_SZ;
5595 offered = data.length;
5596 /*strlen_m_term(data.string)*2;*/
5597 break;
5598 case REG_MULTI_SZ:
5599 torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5600 type = REG_MULTI_SZ;
5601 offered = data.length;
5602 break;
5603 default:
5604 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5607 torture_assert(tctx,
5608 test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5609 "failed to call SetPrinterDataEx");
5611 torture_assert(tctx,
5612 test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
5613 "failed to call GetPrinterDataEx");
5615 torture_assert(tctx,
5616 test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5617 "failed to call EnumPrinterDataEx");
5619 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5620 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5621 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5623 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5624 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5625 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5626 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5627 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5628 if (einfo[0].data_length > 0) {
5629 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5632 if (winreg_handle && hive_handle) {
5633 enum winreg_Type w_type;
5634 uint32_t w_size;
5635 uint32_t w_length;
5636 uint8_t *w_data;
5638 torture_assert(tctx,
5639 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5640 printername, key_name, value_name,
5641 &w_type, &w_size, &w_length, &w_data), "");
5643 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5644 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5645 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5646 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5649 torture_assert(tctx,
5650 test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5651 "failed to call DeletePrinterDataEx");
5655 return true;
5658 static bool test_PrinterData_winreg(struct torture_context *tctx,
5659 struct dcerpc_pipe *p,
5660 struct policy_handle *handle,
5661 const char *printer_name)
5663 struct dcerpc_binding_handle *b = p->binding_handle;
5664 struct dcerpc_pipe *p2;
5665 bool ret = true;
5666 struct policy_handle hive_handle;
5667 struct dcerpc_binding_handle *b2;
5669 torture_assert_ntstatus_ok(tctx,
5670 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5671 "could not open winreg pipe");
5672 b2 = p2->binding_handle;
5674 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5676 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5677 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5679 test_winreg_CloseKey(tctx, b2, &hive_handle);
5681 talloc_free(p2);
5683 return ret;
5686 static bool test_Forms_winreg(struct torture_context *tctx,
5687 struct dcerpc_binding_handle *b,
5688 struct policy_handle *handle,
5689 bool print_server,
5690 const char *printer_name)
5692 struct dcerpc_pipe *p2;
5693 bool ret = true;
5694 struct policy_handle hive_handle;
5695 struct dcerpc_binding_handle *b2;
5697 torture_assert_ntstatus_ok(tctx,
5698 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5699 "could not open winreg pipe");
5700 b2 = p2->binding_handle;
5702 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5704 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5706 test_winreg_CloseKey(tctx, b2, &hive_handle);
5708 talloc_free(p2);
5710 return ret;
5713 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5714 struct dcerpc_pipe *p,
5715 struct policy_handle *handle,
5716 const char *printer_name)
5718 struct dcerpc_binding_handle *b = p->binding_handle;
5719 struct dcerpc_pipe *p2;
5720 bool ret = true;
5721 struct policy_handle hive_handle;
5722 struct dcerpc_binding_handle *b2;
5724 torture_assert_ntstatus_ok(tctx,
5725 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5726 "could not open winreg pipe");
5727 b2 = p2->binding_handle;
5729 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5731 ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5733 test_winreg_CloseKey(tctx, b2, &hive_handle);
5735 talloc_free(p2);
5737 return ret;
5740 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5741 struct dcerpc_pipe *p,
5742 struct policy_handle *handle,
5743 const char *printer_name,
5744 const char *driver_name,
5745 const char *environment,
5746 enum spoolss_DriverOSVersion version)
5748 struct dcerpc_binding_handle *b = p->binding_handle;
5749 struct dcerpc_pipe *p2;
5750 bool ret = true;
5751 struct policy_handle hive_handle;
5752 struct dcerpc_binding_handle *b2;
5754 torture_assert_ntstatus_ok(tctx,
5755 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5756 "could not open winreg pipe");
5757 b2 = p2->binding_handle;
5759 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5761 ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
5763 test_winreg_CloseKey(tctx, b2, &hive_handle);
5765 talloc_free(p2);
5767 return ret;
5770 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5771 struct dcerpc_binding_handle *b,
5772 const char *environment)
5774 struct dcerpc_pipe *p2;
5775 bool ret = true;
5776 struct policy_handle hive_handle;
5777 struct dcerpc_binding_handle *b2;
5779 torture_assert_ntstatus_ok(tctx,
5780 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5781 "could not open winreg pipe");
5782 b2 = p2->binding_handle;
5784 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5786 ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5788 test_winreg_CloseKey(tctx, b2, &hive_handle);
5790 talloc_free(p2);
5792 return ret;
5795 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5796 struct dcerpc_pipe *p,
5797 struct policy_handle *handle,
5798 const char *printer_name)
5800 struct spoolss_SetPrinterInfoCtr info_ctr;
5801 struct spoolss_DevmodeContainer devmode_ctr;
5802 struct sec_desc_buf secdesc_ctr;
5803 union spoolss_SetPrinterInfo sinfo;
5804 union spoolss_PrinterInfo info;
5805 struct dcerpc_binding_handle *b = p->binding_handle;
5806 const char *pname;
5808 ZERO_STRUCT(info_ctr);
5809 ZERO_STRUCT(devmode_ctr);
5810 ZERO_STRUCT(secdesc_ctr);
5812 torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5814 torture_assert(tctx,
5815 test_GetPrinter_level(tctx, b, handle, 2, &info),
5816 "failed to query Printer level 2");
5818 torture_assert(tctx,
5819 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5820 "failed to convert");
5822 info_ctr.level = 2;
5823 info_ctr.info = sinfo;
5825 #define TEST_SZ(wname, iname) \
5826 do {\
5827 enum winreg_Type type;\
5828 uint8_t *data;\
5829 uint32_t needed;\
5830 DATA_BLOB blob;\
5831 const char *str;\
5832 torture_assert(tctx,\
5833 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5834 "failed to query");\
5835 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5836 blob = data_blob_const(data, needed);\
5837 torture_assert(tctx,\
5838 pull_reg_sz(tctx, &blob, &str),\
5839 "failed to pull REG_SZ");\
5840 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5841 } while(0);
5844 #define TEST_SET_SZ(wname, iname, val) \
5845 do {\
5846 enum winreg_Type type;\
5847 uint8_t *data;\
5848 uint32_t needed;\
5849 DATA_BLOB blob;\
5850 const char *str;\
5851 sinfo.info2->iname = val;\
5852 torture_assert(tctx,\
5853 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5854 "failed to call SetPrinter");\
5855 torture_assert(tctx,\
5856 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5857 "failed to query");\
5858 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5859 blob = data_blob_const(data, needed);\
5860 torture_assert(tctx,\
5861 pull_reg_sz(tctx, &blob, &str),\
5862 "failed to pull REG_SZ");\
5863 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5864 } while(0);
5866 #define TEST_SET_DWORD(wname, iname, val) \
5867 do {\
5868 enum winreg_Type type;\
5869 uint8_t *data;\
5870 uint32_t needed;\
5871 uint32_t value;\
5872 sinfo.info2->iname = val;\
5873 torture_assert(tctx,\
5874 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5875 "failed to call SetPrinter");\
5876 torture_assert(tctx,\
5877 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5878 "failed to query");\
5879 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5880 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5881 value = IVAL(data, 0); \
5882 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5883 } while(0);
5885 TEST_SET_SZ("description", comment, "newval");
5886 TEST_SET_SZ("location", location, "newval");
5887 TEST_SET_SZ("driverName", drivername, "newval");
5888 /* TEST_SET_DWORD("priority", priority, 25); */
5890 torture_assert(tctx,
5891 test_GetPrinter_level(tctx, b, handle, 2, &info),
5892 "failed to query Printer level 2");
5894 TEST_SZ("description", info.info2.comment);
5895 TEST_SZ("driverName", info.info2.drivername);
5896 TEST_SZ("location", info.info2.location);
5898 pname = strrchr(info.info2.printername, '\\');
5899 if (pname == NULL) {
5900 pname = info.info2.printername;
5901 } else {
5902 pname++;
5904 TEST_SZ("printerName", pname);
5905 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5906 /* TEST_SZ("printShareName", info.info2.sharename); */
5908 /* FIXME gd: complete the list */
5910 #undef TEST_SZ
5911 #undef TEST_SET_SZ
5912 #undef TEST_DWORD
5914 torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5916 return true;
5919 static bool test_print_processors_winreg(struct torture_context *tctx,
5920 void *private_data)
5922 struct test_spoolss_context *ctx =
5923 talloc_get_type_abort(private_data, struct test_spoolss_context);
5924 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5925 struct dcerpc_binding_handle *b = p->binding_handle;
5927 return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5930 static bool test_AddPrintProcessor(struct torture_context *tctx,
5931 struct dcerpc_binding_handle *b,
5932 const char *environment,
5933 const char *path_name,
5934 const char *print_processor_name,
5935 WERROR expected_error)
5937 struct spoolss_AddPrintProcessor r;
5939 r.in.server = NULL;
5940 r.in.architecture = environment;
5941 r.in.path_name = path_name;
5942 r.in.print_processor_name = print_processor_name;
5944 torture_comment(tctx, "Testing AddPrintProcessor(%s)\n",
5945 print_processor_name);
5947 torture_assert_ntstatus_ok(tctx,
5948 dcerpc_spoolss_AddPrintProcessor_r(b, tctx, &r),
5949 "spoolss_AddPrintProcessor failed");
5950 torture_assert_werr_equal(tctx, r.out.result, expected_error,
5951 "spoolss_AddPrintProcessor failed");
5953 return true;
5956 static bool test_DeletePrintProcessor(struct torture_context *tctx,
5957 struct dcerpc_binding_handle *b,
5958 const char *environment,
5959 const char *print_processor_name,
5960 WERROR expected_error)
5962 struct spoolss_DeletePrintProcessor r;
5964 r.in.server = NULL;
5965 r.in.architecture = environment;
5966 r.in.print_processor_name = print_processor_name;
5968 torture_comment(tctx, "Testing DeletePrintProcessor(%s)\n",
5969 print_processor_name);
5971 torture_assert_ntstatus_ok(tctx,
5972 dcerpc_spoolss_DeletePrintProcessor_r(b, tctx, &r),
5973 "spoolss_DeletePrintProcessor failed");
5974 torture_assert_werr_equal(tctx, r.out.result, expected_error,
5975 "spoolss_DeletePrintProcessor failed");
5977 return true;
5980 static bool test_add_print_processor(struct torture_context *tctx,
5981 void *private_data)
5983 struct test_spoolss_context *ctx =
5984 talloc_get_type_abort(private_data, struct test_spoolss_context);
5985 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5986 struct dcerpc_binding_handle *b = p->binding_handle;
5987 int i;
5989 struct {
5990 const char *environment;
5991 const char *path_name;
5992 const char *print_processor_name;
5993 WERROR expected_add_result;
5994 WERROR expected_del_result;
5995 } tests[] = {
5997 .environment = ctx->environment,
5998 .path_name = "",
5999 .print_processor_name = "winprint",
6000 .expected_add_result = WERR_PRINT_PROCESSOR_ALREADY_INSTALLED,
6001 .expected_del_result = WERR_CAN_NOT_COMPLETE
6003 .environment = ctx->environment,
6004 .path_name = "",
6005 .print_processor_name = "unknown",
6006 .expected_add_result = WERR_MOD_NOT_FOUND,
6007 .expected_del_result = WERR_UNKNOWN_PRINTPROCESSOR
6011 for (i=0; i < ARRAY_SIZE(tests); i++) {
6012 torture_assert(tctx,
6013 test_AddPrintProcessor(tctx, b,
6014 tests[i].environment,
6015 tests[i].path_name,
6016 tests[i].print_processor_name,
6017 tests[i].expected_add_result),
6018 "add print processor failed");
6019 torture_assert(tctx,
6020 test_DeletePrintProcessor(tctx, b,
6021 tests[i].environment,
6022 tests[i].print_processor_name,
6023 tests[i].expected_del_result),
6024 "delete print processor failed");
6027 return true;
6030 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
6031 struct dcerpc_binding_handle *b,
6032 struct policy_handle *handle,
6033 uint32_t *change_id)
6035 enum winreg_Type type;
6036 uint8_t *data;
6037 uint32_t needed;
6039 torture_assert(tctx,
6040 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
6041 "failed to call GetPrinterData");
6043 torture_assert(tctx, type == REG_DWORD, "unexpected type");
6044 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
6046 *change_id = IVAL(data, 0);
6048 return true;
6051 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
6052 struct dcerpc_pipe *p,
6053 struct policy_handle *handle,
6054 uint32_t *change_id)
6056 enum winreg_Type type;
6057 uint8_t *data;
6058 uint32_t needed;
6060 torture_assert(tctx,
6061 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
6062 "failed to call GetPrinterData");
6064 torture_assert(tctx, type == REG_DWORD, "unexpected type");
6065 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
6067 *change_id = IVAL(data, 0);
6069 return true;
6072 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
6073 struct dcerpc_binding_handle *b,
6074 struct policy_handle *handle,
6075 uint32_t *change_id)
6077 union spoolss_PrinterInfo info;
6079 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
6080 "failed to query Printer level 0");
6082 *change_id = info.info0.change_id;
6084 return true;
6087 static bool test_ChangeID(struct torture_context *tctx,
6088 struct dcerpc_pipe *p,
6089 struct policy_handle *handle)
6091 uint32_t change_id, change_id_ex, change_id_info;
6092 uint32_t change_id2, change_id_ex2, change_id_info2;
6093 union spoolss_PrinterInfo info;
6094 const char *comment;
6095 struct dcerpc_binding_handle *b = p->binding_handle;
6097 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
6099 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6100 "failed to query for ChangeID");
6101 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6102 "failed to query for ChangeID");
6103 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6104 "failed to query for ChangeID");
6106 torture_assert_int_equal(tctx, change_id, change_id_ex,
6107 "change_ids should all be equal");
6108 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
6109 "change_ids should all be equal");
6112 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
6114 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6115 "failed to query for ChangeID");
6116 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
6117 "failed to query Printer level 2");
6118 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6119 "failed to query for ChangeID");
6120 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6121 "failed to query for ChangeID");
6122 torture_assert_int_equal(tctx, change_id, change_id_ex,
6123 "change_id should not have changed");
6124 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
6125 "change_id should not have changed");
6128 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
6130 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6131 "failed to query for ChangeID");
6132 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6133 "failed to query for ChangeID");
6134 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6135 "failed to query for ChangeID");
6136 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
6137 "failed to query Printer level 2");
6138 comment = talloc_strdup(tctx, info.info2.comment);
6141 struct spoolss_SetPrinterInfoCtr info_ctr;
6142 struct spoolss_DevmodeContainer devmode_ctr;
6143 struct sec_desc_buf secdesc_ctr;
6144 union spoolss_SetPrinterInfo sinfo;
6146 ZERO_STRUCT(info_ctr);
6147 ZERO_STRUCT(devmode_ctr);
6148 ZERO_STRUCT(secdesc_ctr);
6151 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
6152 sinfo.info2->comment = "torture_comment";
6154 info_ctr.level = 2;
6155 info_ctr.info = sinfo;
6157 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6158 "failed to call SetPrinter");
6160 sinfo.info2->comment = comment;
6162 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6163 "failed to call SetPrinter");
6167 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
6168 "failed to query for ChangeID");
6169 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
6170 "failed to query for ChangeID");
6171 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
6172 "failed to query for ChangeID");
6174 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
6175 "change_ids should all be equal");
6176 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
6177 "change_ids should all be equal");
6179 torture_assert(tctx, (change_id < change_id2),
6180 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6181 change_id2, change_id));
6182 torture_assert(tctx, (change_id_ex < change_id_ex2),
6183 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6184 change_id_ex2, change_id_ex));
6185 torture_assert(tctx, (change_id_info < change_id_info2),
6186 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6187 change_id_info2, change_id_info));
6189 torture_comment(tctx, "ChangeID tests succeeded\n\n");
6191 return true;
6194 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
6195 struct dcerpc_pipe *p,
6196 struct policy_handle *handle)
6198 NTSTATUS status;
6199 const struct dcerpc_binding *binding2;
6200 struct dcerpc_pipe *p2;
6201 struct spoolss_ClosePrinter cp;
6203 /* only makes sense on SMB */
6204 if (p->conn->transport.transport != NCACN_NP) {
6205 return true;
6208 torture_comment(tctx, "Testing close on secondary pipe\n");
6210 binding2 = p->binding;
6211 status = dcerpc_secondary_connection(p, &p2, binding2);
6212 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
6214 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
6215 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
6217 cp.in.handle = handle;
6218 cp.out.handle = handle;
6220 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
6221 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
6222 "ERROR: Allowed close on secondary connection");
6224 talloc_free(p2);
6226 return true;
6229 static bool test_OpenPrinter_badname(struct torture_context *tctx,
6230 struct dcerpc_binding_handle *b, const char *name)
6232 NTSTATUS status;
6233 struct spoolss_OpenPrinter op;
6234 struct spoolss_OpenPrinterEx opEx;
6235 struct policy_handle handle;
6236 bool ret = true;
6238 op.in.printername = name;
6239 op.in.datatype = NULL;
6240 op.in.devmode_ctr.devmode= NULL;
6241 op.in.access_mask = 0;
6242 op.out.handle = &handle;
6244 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
6246 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
6247 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
6248 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
6249 "unexpected result");
6251 if (W_ERROR_IS_OK(op.out.result)) {
6252 ret &=test_ClosePrinter(tctx, b, &handle);
6255 opEx.in.printername = name;
6256 opEx.in.datatype = NULL;
6257 opEx.in.devmode_ctr.devmode = NULL;
6258 opEx.in.access_mask = 0;
6259 opEx.in.userlevel_ctr.level = 1;
6260 opEx.in.userlevel_ctr.user_info.level1 = NULL;
6261 opEx.out.handle = &handle;
6263 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
6265 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
6266 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
6267 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
6268 "unexpected result");
6270 if (W_ERROR_IS_OK(opEx.out.result)) {
6271 ret &=test_ClosePrinter(tctx, b, &handle);
6274 return ret;
6277 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
6278 void *private_data)
6280 struct test_spoolss_context *ctx =
6281 talloc_get_type_abort(private_data, struct test_spoolss_context);
6283 const char *badnames[] = {
6284 "__INVALID_PRINTER__",
6285 "\\\\__INVALID_HOST__",
6287 "\\\\\\",
6288 "\\\\\\__INVALID_PRINTER__"
6290 const char *badname;
6291 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6292 const char *server_name = dcerpc_server_name(p);
6293 struct dcerpc_binding_handle *b = p->binding_handle;
6294 int i;
6296 for (i=0; i < ARRAY_SIZE(badnames); i++) {
6297 torture_assert(tctx,
6298 test_OpenPrinter_badname(tctx, b, badnames[i]),
6299 "");
6302 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
6303 torture_assert(tctx,
6304 test_OpenPrinter_badname(tctx, b, badname),
6305 "");
6307 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
6308 torture_assert(tctx,
6309 test_OpenPrinter_badname(tctx, b, badname),
6310 "");
6312 return true;
6315 static bool test_OpenPrinter(struct torture_context *tctx,
6316 struct dcerpc_pipe *p,
6317 const char *name,
6318 const char *environment,
6319 bool open_only)
6321 NTSTATUS status;
6322 struct spoolss_OpenPrinter r;
6323 struct policy_handle handle;
6324 bool ret = true;
6325 struct dcerpc_binding_handle *b = p->binding_handle;
6327 r.in.printername = name;
6328 r.in.datatype = NULL;
6329 r.in.devmode_ctr.devmode= NULL;
6330 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6331 r.out.handle = &handle;
6333 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
6335 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
6337 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
6339 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
6341 if (open_only) {
6342 goto close_printer;
6345 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6346 ret = false;
6349 if (!torture_setting_bool(tctx, "samba3", false)) {
6350 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6351 ret = false;
6355 close_printer:
6356 if (!test_ClosePrinter(tctx, b, &handle)) {
6357 ret = false;
6360 return ret;
6363 static bool test_OpenPrinterEx(struct torture_context *tctx,
6364 struct dcerpc_binding_handle *b,
6365 const char *printername,
6366 const char *datatype,
6367 struct spoolss_DeviceMode *devmode,
6368 uint32_t access_mask,
6369 struct spoolss_UserLevelCtr *userlevel_ctr,
6370 struct policy_handle *handle,
6371 WERROR expected_result)
6373 struct spoolss_OpenPrinterEx r;
6375 r.in.printername = printername;
6376 r.in.datatype = datatype;
6377 r.in.devmode_ctr.devmode= devmode;
6378 r.in.access_mask = access_mask;
6379 r.in.userlevel_ctr = *userlevel_ctr;
6380 r.out.handle = handle;
6382 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
6384 torture_assert_ntstatus_ok(tctx,
6385 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
6386 "OpenPrinterEx failed");
6388 torture_assert_werr_equal(tctx, r.out.result, expected_result,
6389 "OpenPrinterEx failed");
6391 return true;
6394 static bool call_OpenPrinterEx(struct torture_context *tctx,
6395 struct dcerpc_pipe *p,
6396 const char *name,
6397 struct spoolss_DeviceMode *devmode,
6398 struct policy_handle *handle)
6400 struct spoolss_UserLevelCtr userlevel_ctr;
6401 struct spoolss_UserLevel1 userlevel1;
6402 struct dcerpc_binding_handle *b = p->binding_handle;
6404 userlevel1.size = 1234;
6405 userlevel1.client = "hello";
6406 userlevel1.user = "spottyfoot!";
6407 userlevel1.build = 1;
6408 userlevel1.major = 2;
6409 userlevel1.minor = 3;
6410 userlevel1.processor = 4;
6412 userlevel_ctr.level = 1;
6413 userlevel_ctr.user_info.level1 = &userlevel1;
6415 return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
6416 SEC_FLAG_MAXIMUM_ALLOWED,
6417 &userlevel_ctr,
6418 handle,
6419 WERR_OK);
6422 static bool test_printer_rename(struct torture_context *tctx,
6423 void *private_data)
6425 struct torture_printer_context *t =
6426 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6427 struct dcerpc_pipe *p = t->spoolss_pipe;
6429 bool ret = true;
6430 union spoolss_PrinterInfo info;
6431 union spoolss_SetPrinterInfo sinfo;
6432 struct spoolss_SetPrinterInfoCtr info_ctr;
6433 struct spoolss_DevmodeContainer devmode_ctr;
6434 struct sec_desc_buf secdesc_ctr;
6435 const char *printer_name;
6436 const char *printer_name_orig;
6437 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
6438 struct policy_handle new_handle;
6439 const char *q;
6440 struct dcerpc_binding_handle *b = p->binding_handle;
6442 ZERO_STRUCT(devmode_ctr);
6443 ZERO_STRUCT(secdesc_ctr);
6445 torture_comment(tctx, "Testing Printer rename operations\n");
6447 torture_assert(tctx,
6448 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
6449 "failed to call GetPrinter level 2");
6451 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
6453 q = strrchr(info.info2.printername, '\\');
6454 if (q) {
6455 torture_warning(tctx,
6456 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6459 torture_assert(tctx,
6460 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
6462 sinfo.info2->printername = printer_name_new;
6464 info_ctr.level = 2;
6465 info_ctr.info = sinfo;
6467 torture_assert(tctx,
6468 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6469 "failed to call SetPrinter level 2");
6471 torture_assert(tctx,
6472 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
6473 "failed to call GetPrinter level 2");
6475 printer_name = talloc_strdup(tctx, info.info2.printername);
6477 q = strrchr(info.info2.printername, '\\');
6478 if (q) {
6479 torture_warning(tctx,
6480 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6481 q++;
6482 printer_name = q;
6485 torture_assert_str_equal(tctx, printer_name, printer_name_new,
6486 "new printer name was not set");
6488 /* samba currently cannot fully rename printers */
6489 if (!torture_setting_bool(tctx, "samba3", false)) {
6490 torture_assert(tctx,
6491 test_OpenPrinter_badname(tctx, b, printer_name_orig),
6492 "still can open printer with oldname after rename");
6493 } else {
6494 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
6497 torture_assert(tctx,
6498 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
6499 "failed to open printer with new name");
6501 torture_assert(tctx,
6502 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
6503 "failed to call GetPrinter level 2");
6505 torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
6506 "new printer name was not set");
6508 torture_assert(tctx,
6509 test_ClosePrinter(tctx, b, &new_handle),
6510 "failed to close printer");
6512 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
6514 return ret;
6517 static bool test_openprinter(struct torture_context *tctx,
6518 struct dcerpc_binding_handle *b,
6519 const char *real_printername)
6521 struct spoolss_UserLevelCtr userlevel_ctr;
6522 struct policy_handle handle;
6523 struct spoolss_UserLevel1 userlevel1;
6524 const char *printername = NULL;
6525 int i;
6527 struct {
6528 const char *suffix;
6529 WERROR expected_result;
6530 } tests[] = {
6532 .suffix = "rubbish",
6533 .expected_result = WERR_INVALID_PRINTER_NAME
6535 .suffix = ", LocalOnl",
6536 .expected_result = WERR_INVALID_PRINTER_NAME
6538 .suffix = ", localOnly",
6539 .expected_result = WERR_INVALID_PRINTER_NAME
6541 .suffix = ", localonl",
6542 .expected_result = WERR_INVALID_PRINTER_NAME
6544 .suffix = ",LocalOnl",
6545 .expected_result = WERR_INVALID_PRINTER_NAME
6547 .suffix = ",localOnl2",
6548 .expected_result = WERR_INVALID_PRINTER_NAME
6550 .suffix = ", DrvConver2t",
6551 .expected_result = WERR_INVALID_PRINTER_NAME
6553 .suffix = ", drvconvert",
6554 .expected_result = WERR_INVALID_PRINTER_NAME
6556 .suffix = ",drvconvert",
6557 .expected_result = WERR_INVALID_PRINTER_NAME
6559 .suffix = ", DrvConvert",
6560 .expected_result = WERR_OK
6562 .suffix = " , DrvConvert",
6563 .expected_result = WERR_INVALID_PRINTER_NAME
6565 .suffix = ",DrvConvert",
6566 .expected_result = WERR_OK
6568 .suffix = ", DrvConvertsadfasdf",
6569 .expected_result = WERR_OK
6571 .suffix = ",DrvConvertasdfasd",
6572 .expected_result = WERR_OK
6574 .suffix = ", LocalOnly",
6575 .expected_result = WERR_OK
6577 .suffix = " , LocalOnly",
6578 .expected_result = WERR_INVALID_PRINTER_NAME
6580 .suffix = ",LocalOnly",
6581 .expected_result = WERR_OK
6583 .suffix = ", LocalOnlysagi4gjfkd",
6584 .expected_result = WERR_OK
6586 .suffix = ",LocalOnlysagi4gjfkd",
6587 .expected_result = WERR_OK
6591 userlevel1.size = 1234;
6592 userlevel1.client = "hello";
6593 userlevel1.user = "spottyfoot!";
6594 userlevel1.build = 1;
6595 userlevel1.major = 2;
6596 userlevel1.minor = 3;
6597 userlevel1.processor = 4;
6599 userlevel_ctr.level = 1;
6600 userlevel_ctr.user_info.level1 = &userlevel1;
6602 torture_comment(tctx, "Testing openprinterex printername pattern\n");
6604 torture_assert(tctx,
6605 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0,
6606 &userlevel_ctr, &handle,
6607 WERR_OK),
6608 "OpenPrinterEx failed");
6609 test_ClosePrinter(tctx, b, &handle);
6611 for (i=0; i < ARRAY_SIZE(tests); i++) {
6613 printername = talloc_asprintf(tctx, "%s%s",
6614 real_printername,
6615 tests[i].suffix);
6617 torture_assert(tctx,
6618 test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0,
6619 &userlevel_ctr, &handle,
6620 tests[i].expected_result),
6621 "OpenPrinterEx failed");
6622 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6623 test_ClosePrinter(tctx, b, &handle);
6627 return true;
6631 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6632 struct dcerpc_pipe *p,
6633 const char *name,
6634 const char *environment)
6636 struct policy_handle handle;
6637 bool ret = true;
6638 struct dcerpc_binding_handle *b = p->binding_handle;
6640 if (!test_openprinter(tctx, b, name)) {
6641 return false;
6644 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6645 return false;
6648 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6649 ret = false;
6652 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6653 ret = false;
6656 if (!test_EnumForms_all(tctx, b, &handle, false)) {
6657 ret = false;
6660 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6661 ret = false;
6664 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6665 ret = false;
6668 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6669 ret = false;
6672 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6673 ret = false;
6676 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6677 ret = false;
6680 if (!test_printer_all_keys(tctx, b, &handle)) {
6681 ret = false;
6684 if (!test_PausePrinter(tctx, b, &handle)) {
6685 ret = false;
6688 if (!test_DoPrintTest(tctx, b, &handle)) {
6689 ret = false;
6692 if (!test_ResumePrinter(tctx, b, &handle)) {
6693 ret = false;
6696 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
6697 ret = false;
6700 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
6701 ret = false;
6704 if (!torture_setting_bool(tctx, "samba3", false)) {
6705 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6706 ret = false;
6710 if (!test_ClosePrinter(tctx, b, &handle)) {
6711 ret = false;
6714 return ret;
6717 static bool test_EnumPrinters_old(struct torture_context *tctx,
6718 void *private_data)
6720 struct test_spoolss_context *ctx =
6721 talloc_get_type_abort(private_data, struct test_spoolss_context);
6722 struct spoolss_EnumPrinters r;
6723 NTSTATUS status;
6724 uint16_t levels[] = {1, 2, 4, 5};
6725 int i;
6726 bool ret = true;
6727 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6728 struct dcerpc_binding_handle *b = p->binding_handle;
6730 for (i=0;i<ARRAY_SIZE(levels);i++) {
6731 union spoolss_PrinterInfo *info;
6732 int j;
6733 uint32_t needed;
6734 uint32_t count;
6736 r.in.flags = PRINTER_ENUM_LOCAL;
6737 r.in.server = "";
6738 r.in.level = levels[i];
6739 r.in.buffer = NULL;
6740 r.in.offered = 0;
6741 r.out.needed = &needed;
6742 r.out.count = &count;
6743 r.out.info = &info;
6745 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6747 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6748 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6750 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6751 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6752 r.in.buffer = &blob;
6753 r.in.offered = needed;
6754 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6757 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6759 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6761 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6763 if (!info) {
6764 torture_comment(tctx, "No printers returned\n");
6765 return true;
6768 for (j=0;j<count;j++) {
6769 if (r.in.level == 1) {
6770 char *unc = talloc_strdup(tctx, info[j].info1.name);
6771 char *slash, *name, *full_name;
6772 name = unc;
6773 if (unc[0] == '\\' && unc[1] == '\\') {
6774 unc +=2;
6776 slash = strchr(unc, '\\');
6777 if (slash) {
6778 slash++;
6779 name = slash;
6781 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6782 dcerpc_server_name(p), name);
6783 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6784 ret = false;
6786 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6787 ret = false;
6789 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6790 ret = false;
6792 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6793 ret = false;
6799 return ret;
6802 static bool test_EnumPrinters_level(struct torture_context *tctx,
6803 struct dcerpc_binding_handle *b,
6804 uint32_t flags,
6805 const char *servername,
6806 uint32_t level,
6807 uint32_t *count_p,
6808 union spoolss_PrinterInfo **info_p)
6810 struct spoolss_EnumPrinters r;
6811 union spoolss_PrinterInfo *info;
6812 uint32_t needed;
6813 uint32_t count;
6815 r.in.flags = flags;
6816 r.in.server = servername;
6817 r.in.level = level;
6818 r.in.buffer = NULL;
6819 r.in.offered = 0;
6820 r.out.needed = &needed;
6821 r.out.count = &count;
6822 r.out.info = &info;
6824 torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6825 r.in.server, r.in.level);
6827 torture_assert_ntstatus_ok(tctx,
6828 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6829 "EnumPrinters failed");
6830 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6831 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6832 r.in.buffer = &blob;
6833 r.in.offered = needed;
6834 torture_assert_ntstatus_ok(tctx,
6835 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6836 "EnumPrinters failed");
6839 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6841 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6843 if (count_p) {
6844 *count_p = count;
6846 if (info_p) {
6847 *info_p = info;
6850 return true;
6853 static const char *get_short_printername(struct torture_context *tctx,
6854 const char *name)
6856 const char *short_name;
6858 if (name[0] == '\\' && name[1] == '\\') {
6859 name += 2;
6860 short_name = strchr(name, '\\');
6861 if (short_name) {
6862 return talloc_strdup(tctx, short_name+1);
6866 return name;
6869 static const char *get_full_printername(struct torture_context *tctx,
6870 const char *name)
6872 const char *full_name = talloc_strdup(tctx, name);
6873 char *p;
6875 if (name && name[0] == '\\' && name[1] == '\\') {
6876 name += 2;
6877 p = strchr(name, '\\');
6878 if (p) {
6879 return full_name;
6883 return NULL;
6886 static bool test_OnePrinter_servername(struct torture_context *tctx,
6887 struct dcerpc_pipe *p,
6888 struct dcerpc_binding_handle *b,
6889 const char *servername,
6890 const char *printername)
6892 union spoolss_PrinterInfo info;
6893 const char *short_name = get_short_printername(tctx, printername);
6894 const char *full_name = get_full_printername(tctx, printername);
6896 if (short_name) {
6897 struct policy_handle handle;
6898 torture_assert(tctx,
6899 call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
6900 "failed to open printer");
6902 torture_assert(tctx,
6903 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6904 "failed to get printer info");
6906 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
6907 "unexpected servername");
6908 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
6909 "unexpected printername");
6911 if (info.info2.devmode) {
6912 const char *expected_devicename;
6913 expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
6914 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6915 "unexpected devicemode devicename");
6918 torture_assert(tctx,
6919 test_ClosePrinter(tctx, b, &handle),
6920 "failed to close printer");
6923 if (full_name) {
6924 struct policy_handle handle;
6926 torture_assert(tctx,
6927 call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
6928 "failed to open printer");
6930 torture_assert(tctx,
6931 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6932 "failed to get printer info");
6934 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
6935 "unexpected servername");
6936 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
6937 "unexpected printername");
6939 if (info.info2.devmode) {
6940 const char *expected_devicename;
6941 expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
6942 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6943 "unexpected devicemode devicename");
6946 torture_assert(tctx,
6947 test_ClosePrinter(tctx, b, &handle),
6948 "failed to close printer");
6951 return true;
6954 static bool test_EnumPrinters_servername(struct torture_context *tctx,
6955 void *private_data)
6957 struct test_spoolss_context *ctx =
6958 talloc_get_type_abort(private_data, struct test_spoolss_context);
6959 int i;
6960 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6961 struct dcerpc_binding_handle *b = p->binding_handle;
6962 uint32_t count;
6963 union spoolss_PrinterInfo *info;
6964 const char *servername;
6965 uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
6967 torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6969 servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6971 torture_assert(tctx,
6972 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6973 "failed to enumerate printers");
6975 for (i=0; i < count; i++) {
6977 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
6978 "unexpected servername");
6980 torture_assert(tctx,
6981 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6982 "failed to check printer");
6985 servername = "";
6987 torture_assert(tctx,
6988 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6989 "failed to enumerate printers");
6991 for (i=0; i < count; i++) {
6993 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
6994 "unexpected servername");
6996 torture_assert(tctx,
6997 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6998 "failed to check printer");
7002 return true;
7005 #if 0
7006 static bool test_GetPrinterDriver(struct torture_context *tctx,
7007 struct dcerpc_binding_handle *b,
7008 struct policy_handle *handle,
7009 const char *driver_name)
7011 struct spoolss_GetPrinterDriver r;
7012 uint32_t needed;
7014 r.in.handle = handle;
7015 r.in.architecture = "W32X86";
7016 r.in.level = 1;
7017 r.in.buffer = NULL;
7018 r.in.offered = 0;
7019 r.out.needed = &needed;
7021 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
7023 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
7024 "failed to call GetPrinterDriver");
7025 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
7026 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7027 r.in.buffer = &blob;
7028 r.in.offered = needed;
7029 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
7030 "failed to call GetPrinterDriver");
7033 torture_assert_werr_ok(tctx, r.out.result,
7034 "failed to call GetPrinterDriver");
7036 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
7038 return true;
7040 #endif
7042 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
7043 struct dcerpc_binding_handle *b,
7044 struct policy_handle *handle,
7045 const char *driver_name,
7046 const char *architecture,
7047 uint32_t level,
7048 uint32_t client_major_version,
7049 uint32_t client_minor_version,
7050 union spoolss_DriverInfo *info_p,
7051 WERROR *result_p)
7054 struct spoolss_GetPrinterDriver2 r;
7055 uint32_t needed;
7056 uint32_t server_major_version;
7057 uint32_t server_minor_version;
7059 r.in.handle = handle;
7060 r.in.architecture = architecture;
7061 r.in.client_major_version = client_major_version;
7062 r.in.client_minor_version = client_minor_version;
7063 r.in.buffer = NULL;
7064 r.in.offered = 0;
7065 r.in.level = level;
7066 r.out.needed = &needed;
7067 r.out.server_major_version = &server_major_version;
7068 r.out.server_minor_version = &server_minor_version;
7070 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
7071 driver_name, r.in.level);
7073 torture_assert_ntstatus_ok(tctx,
7074 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
7075 "failed to call GetPrinterDriver2");
7076 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
7077 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7078 r.in.buffer = &blob;
7079 r.in.offered = needed;
7080 torture_assert_ntstatus_ok(tctx,
7081 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
7082 "failed to call GetPrinterDriver2");
7085 if (result_p) {
7086 *result_p = r.out.result;
7089 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
7090 switch (r.in.level) {
7091 case 101:
7092 case 8:
7093 torture_comment(tctx,
7094 "level %d not implemented, not considering as an error\n",
7095 r.in.level);
7096 return true;
7097 default:
7098 break;
7102 torture_assert_werr_ok(tctx, r.out.result,
7103 "failed to call GetPrinterDriver2");
7105 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
7107 if (info_p) {
7108 *info_p = *r.out.info;
7111 return true;
7114 static bool test_GetPrinterDriver2(struct torture_context *tctx,
7115 struct dcerpc_binding_handle *b,
7116 struct policy_handle *handle,
7117 const char *driver_name,
7118 const char *architecture)
7120 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
7121 int i;
7124 for (i=0;i<ARRAY_SIZE(levels);i++) {
7126 torture_assert(tctx,
7127 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
7128 "");
7131 return true;
7134 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
7135 void *private_data)
7137 struct test_spoolss_context *ctx =
7138 talloc_get_type_abort(private_data, struct test_spoolss_context);
7139 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
7140 int i;
7141 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7142 struct dcerpc_binding_handle *b = p->binding_handle;
7143 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7145 for (i=0;i<ARRAY_SIZE(levels);i++) {
7147 uint32_t count;
7148 union spoolss_DriverInfo *info;
7150 torture_assert(tctx,
7151 test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
7152 "failed to enumerate drivers");
7154 if (!info) {
7155 torture_comment(tctx, "No printer drivers returned\n");
7156 break;
7160 return true;
7163 static bool test_DeletePrinter(struct torture_context *tctx,
7164 struct dcerpc_binding_handle *b,
7165 struct policy_handle *handle)
7167 struct spoolss_DeletePrinter r;
7169 torture_comment(tctx, "Testing DeletePrinter\n");
7171 r.in.handle = handle;
7173 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
7174 "failed to delete printer");
7175 torture_assert_werr_ok(tctx, r.out.result,
7176 "failed to delete printer");
7178 return true;
7181 static bool test_EnumPrinters_findname(struct torture_context *tctx,
7182 struct dcerpc_binding_handle *b,
7183 uint32_t flags,
7184 uint32_t level,
7185 const char *name,
7186 bool *found)
7188 struct spoolss_EnumPrinters e;
7189 uint32_t count;
7190 union spoolss_PrinterInfo *info;
7191 uint32_t needed;
7192 int i;
7194 *found = false;
7196 e.in.flags = flags;
7197 e.in.server = NULL;
7198 e.in.level = level;
7199 e.in.buffer = NULL;
7200 e.in.offered = 0;
7201 e.out.count = &count;
7202 e.out.info = &info;
7203 e.out.needed = &needed;
7205 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
7206 "failed to enum printers");
7208 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
7209 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7210 e.in.buffer = &blob;
7211 e.in.offered = needed;
7213 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
7214 "failed to enum printers");
7217 torture_assert_werr_ok(tctx, e.out.result,
7218 "failed to enum printers");
7220 for (i=0; i < count; i++) {
7222 const char *current = NULL;
7223 const char *q;
7225 switch (level) {
7226 case 1:
7227 current = info[i].info1.name;
7228 break;
7231 if (strequal(current, name)) {
7232 *found = true;
7233 break;
7236 q = strrchr(current, '\\');
7237 if (q) {
7238 if (!e.in.server) {
7239 torture_warning(tctx,
7240 "server returns printername %s incl. servername although we did not set servername", current);
7242 q++;
7243 if (strequal(q, name)) {
7244 *found = true;
7245 break;
7250 return true;
7253 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
7254 struct dcerpc_pipe *p,
7255 const char *printername,
7256 bool ex)
7258 WERROR result;
7259 struct spoolss_AddPrinter r;
7260 struct spoolss_AddPrinterEx rex;
7261 struct spoolss_SetPrinterInfoCtr info_ctr;
7262 struct spoolss_SetPrinterInfo1 info1;
7263 struct spoolss_DevmodeContainer devmode_ctr;
7264 struct sec_desc_buf secdesc_ctr;
7265 struct spoolss_UserLevelCtr userlevel_ctr;
7266 struct policy_handle handle;
7267 bool found = false;
7268 struct dcerpc_binding_handle *b = p->binding_handle;
7270 ZERO_STRUCT(devmode_ctr);
7271 ZERO_STRUCT(secdesc_ctr);
7272 ZERO_STRUCT(userlevel_ctr);
7273 ZERO_STRUCT(info1);
7275 torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
7276 ex ? "Ex":"", printername);
7278 /* try to add printer to wellknown printer list (level 1) */
7280 userlevel_ctr.level = 1;
7282 info_ctr.info.info1 = &info1;
7283 info_ctr.level = 1;
7285 rex.in.server = NULL;
7286 rex.in.info_ctr = &info_ctr;
7287 rex.in.devmode_ctr = &devmode_ctr;
7288 rex.in.secdesc_ctr = &secdesc_ctr;
7289 rex.in.userlevel_ctr = &userlevel_ctr;
7290 rex.out.handle = &handle;
7292 r.in.server = NULL;
7293 r.in.info_ctr = &info_ctr;
7294 r.in.devmode_ctr = &devmode_ctr;
7295 r.in.secdesc_ctr = &secdesc_ctr;
7296 r.out.handle = &handle;
7298 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7299 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7300 "failed to add printer");
7301 result = ex ? rex.out.result : r.out.result;
7302 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
7303 "unexpected result code");
7305 info1.name = printername;
7306 info1.flags = PRINTER_ATTRIBUTE_SHARED;
7308 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7309 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7310 "failed to add printer");
7311 result = ex ? rex.out.result : r.out.result;
7312 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7313 "unexpected result code");
7315 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7316 better do a real check to see the printer is really there */
7318 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7319 PRINTER_ENUM_NETWORK, 1,
7320 printername,
7321 &found),
7322 "failed to enum printers");
7324 torture_assert(tctx, found, "failed to find newly added printer");
7326 info1.flags = 0;
7328 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7329 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7330 "failed to add printer");
7331 result = ex ? rex.out.result : r.out.result;
7332 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7333 "unexpected result code");
7335 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7336 better do a real check to see the printer has really been removed
7337 from the well known printer list */
7339 found = false;
7341 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7342 PRINTER_ENUM_NETWORK, 1,
7343 printername,
7344 &found),
7345 "failed to enum printers");
7346 #if 0
7347 torture_assert(tctx, !found, "printer still in well known printer list");
7348 #endif
7349 return true;
7352 static bool test_AddPrinter_normal(struct torture_context *tctx,
7353 struct dcerpc_pipe *p,
7354 struct policy_handle *handle_p,
7355 const char *printername,
7356 const char *drivername,
7357 const char *portname,
7358 struct spoolss_DeviceMode *devmode,
7359 bool ex)
7361 WERROR result;
7362 struct spoolss_AddPrinter r;
7363 struct spoolss_AddPrinterEx rex;
7364 struct spoolss_SetPrinterInfoCtr info_ctr;
7365 struct spoolss_SetPrinterInfo2 info2;
7366 struct spoolss_DevmodeContainer devmode_ctr;
7367 struct sec_desc_buf secdesc_ctr;
7368 struct spoolss_UserLevelCtr userlevel_ctr;
7369 struct policy_handle handle;
7370 bool found = false;
7371 bool existing_printer_deleted = false;
7372 struct dcerpc_binding_handle *b = p->binding_handle;
7374 ZERO_STRUCT(devmode_ctr);
7375 ZERO_STRUCT(secdesc_ctr);
7376 ZERO_STRUCT(userlevel_ctr);
7378 torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
7379 ex ? "Ex":"", printername);
7381 devmode_ctr.devmode = devmode;
7383 userlevel_ctr.level = 1;
7385 rex.in.server = NULL;
7386 rex.in.info_ctr = &info_ctr;
7387 rex.in.devmode_ctr = &devmode_ctr;
7388 rex.in.secdesc_ctr = &secdesc_ctr;
7389 rex.in.userlevel_ctr = &userlevel_ctr;
7390 rex.out.handle = &handle;
7392 r.in.server = NULL;
7393 r.in.info_ctr = &info_ctr;
7394 r.in.devmode_ctr = &devmode_ctr;
7395 r.in.secdesc_ctr = &secdesc_ctr;
7396 r.out.handle = &handle;
7398 again:
7400 /* try to add printer to printer list (level 2) */
7402 ZERO_STRUCT(info2);
7404 info_ctr.info.info2 = &info2;
7405 info_ctr.level = 2;
7407 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7408 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7409 "failed to add printer");
7410 result = ex ? rex.out.result : r.out.result;
7411 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
7412 "unexpected result code");
7414 info2.printername = printername;
7416 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7417 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7418 "failed to add printer");
7419 result = ex ? rex.out.result : r.out.result;
7421 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
7422 struct policy_handle printer_handle;
7424 if (existing_printer_deleted) {
7425 torture_fail(tctx, "already deleted printer still existing?");
7428 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
7429 "failed to open printer handle");
7431 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
7432 "failed to delete printer");
7434 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
7435 "failed to close server handle");
7437 existing_printer_deleted = true;
7439 goto again;
7442 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
7443 "unexpected result code");
7445 info2.portname = portname;
7447 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7448 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7449 "failed to add printer");
7450 result = ex ? rex.out.result : r.out.result;
7451 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
7452 "unexpected result code");
7454 info2.drivername = drivername;
7456 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7457 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7458 "failed to add printer");
7459 result = ex ? rex.out.result : r.out.result;
7461 /* w2k8r2 allows to add printer w/o defining printprocessor */
7463 if (!W_ERROR_IS_OK(result)) {
7464 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
7465 "unexpected result code");
7467 info2.printprocessor = "winprint";
7469 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7470 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7471 "failed to add printer");
7472 result = ex ? rex.out.result : r.out.result;
7473 torture_assert_werr_ok(tctx, result,
7474 "failed to add printer");
7477 *handle_p = handle;
7479 /* we are paranoid, really check if the printer is there now */
7481 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7482 PRINTER_ENUM_LOCAL, 1,
7483 printername,
7484 &found),
7485 "failed to enum printers");
7486 torture_assert(tctx, found, "failed to find newly added printer");
7488 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7489 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7490 "failed to add printer");
7491 result = ex ? rex.out.result : r.out.result;
7492 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7493 "unexpected result code");
7495 return true;
7498 static bool test_printer_info(struct torture_context *tctx,
7499 void *private_data)
7501 struct torture_printer_context *t =
7502 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7503 struct dcerpc_pipe *p = t->spoolss_pipe;
7504 struct dcerpc_binding_handle *b = p->binding_handle;
7506 bool ret = true;
7508 if (torture_setting_bool(tctx, "samba3", false)) {
7509 torture_skip(tctx, "skipping printer info cross tests against samba 3");
7512 if (!test_PrinterInfo(tctx, b, &t->handle)) {
7513 ret = false;
7516 if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
7517 ret = false;
7520 return ret;
7523 static bool test_EnumPrinterKey(struct torture_context *tctx,
7524 struct dcerpc_binding_handle *b,
7525 struct policy_handle *handle,
7526 const char *key_name,
7527 const char ***array)
7529 struct spoolss_EnumPrinterKey r;
7530 uint32_t needed = 0;
7531 union spoolss_KeyNames key_buffer;
7532 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7533 uint32_t _ndr_size;
7534 int i;
7536 r.in.handle = handle;
7537 r.in.key_name = key_name;
7538 r.out.key_buffer = &key_buffer;
7539 r.out.needed = &needed;
7540 r.out._ndr_size = &_ndr_size;
7542 for (i=0; i < ARRAY_SIZE(offered); i++) {
7544 if (offered[i] < 0 && needed) {
7545 if (needed <= 4) {
7546 continue;
7548 r.in.offered = needed + offered[i];
7549 } else {
7550 r.in.offered = offered[i];
7553 ZERO_STRUCT(key_buffer);
7555 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
7557 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7558 "failed to call EnumPrinterKey");
7559 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
7561 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7562 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7563 _ndr_size, r.in.offered/2));
7565 r.in.offered = needed;
7566 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7567 "failed to call EnumPrinterKey");
7570 if (offered[i] > 0) {
7571 torture_assert_werr_ok(tctx, r.out.result,
7572 "failed to call EnumPrinterKey");
7575 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7576 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7577 _ndr_size, r.in.offered/2));
7579 torture_assert(tctx, (*r.out.needed <= r.in.offered),
7580 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
7582 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
7583 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
7585 if (key_buffer.string_array) {
7586 uint32_t calc_needed = 0;
7587 int s;
7588 for (s=0; key_buffer.string_array[s]; s++) {
7589 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7591 if (!key_buffer.string_array[0]) {
7592 calc_needed += 2;
7594 calc_needed += 2;
7596 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7597 "EnumPrinterKey unexpected size");
7601 if (array) {
7602 *array = key_buffer.string_array;
7605 return true;
7608 bool test_printer_all_keys(struct torture_context *tctx,
7609 struct dcerpc_binding_handle *b,
7610 struct policy_handle *handle)
7612 const char **key_array = NULL;
7613 int i;
7615 torture_comment(tctx, "Testing Printer Keys\n");
7617 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7618 "failed to call test_EnumPrinterKey");
7620 for (i=0; key_array && key_array[i]; i++) {
7621 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7622 "failed to call test_EnumPrinterKey");
7624 for (i=0; key_array && key_array[i]; i++) {
7625 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7626 "failed to call test_EnumPrinterDataEx");
7629 torture_comment(tctx, "Printer Keys test succeeded\n\n");
7631 return true;
7634 static bool test_openprinter_wrap(struct torture_context *tctx,
7635 void *private_data)
7637 struct torture_printer_context *t =
7638 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7639 struct dcerpc_pipe *p = t->spoolss_pipe;
7640 struct dcerpc_binding_handle *b = p->binding_handle;
7641 const char *printername = t->info2.printername;
7643 return test_openprinter(tctx, b, printername);
7646 static bool test_csetprinter(struct torture_context *tctx,
7647 void *private_data)
7649 struct torture_printer_context *t =
7650 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7651 struct dcerpc_pipe *p = t->spoolss_pipe;
7653 const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7654 const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7655 const char *portname = t->info2.portname;
7657 union spoolss_PrinterInfo info;
7658 struct policy_handle new_handle, new_handle2;
7659 struct dcerpc_binding_handle *b = p->binding_handle;
7661 torture_comment(tctx, "Testing c_setprinter\n");
7663 torture_assert(tctx,
7664 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7665 "failed to get level 0 printer info");
7666 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7667 info.info0.c_setprinter);
7669 /* check if c_setprinter on 1st handle increases after a printer has
7670 * been added */
7672 torture_assert(tctx,
7673 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7674 "failed to add new printer");
7675 torture_assert(tctx,
7676 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7677 "failed to get level 0 printer info");
7678 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7679 info.info0.c_setprinter);
7681 /* check if c_setprinter on new handle increases after a printer has
7682 * been added */
7684 torture_assert(tctx,
7685 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7686 "failed to get level 0 printer info");
7687 torture_comment(tctx, "csetprinter on created handle: %d\n",
7688 info.info0.c_setprinter);
7690 /* open the new printer and check if c_setprinter increases */
7692 torture_assert(tctx,
7693 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7694 "failed to open created printer");
7695 torture_assert(tctx,
7696 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
7697 "failed to get level 0 printer info");
7698 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
7699 info.info0.c_setprinter);
7701 /* cleanup */
7703 torture_assert(tctx,
7704 test_ClosePrinter(tctx, b, &new_handle2),
7705 "failed to close printer");
7706 torture_assert(tctx,
7707 test_DeletePrinter(tctx, b, &new_handle),
7708 "failed to delete new printer");
7710 return true;
7713 static bool compose_local_driver_directory(struct torture_context *tctx,
7714 const char *environment,
7715 const char *local_dir,
7716 const char **path)
7718 char *p;
7720 p = strrchr(local_dir, '/');
7721 if (!p) {
7722 return NULL;
7724 p++;
7726 if (strequal(environment, "Windows x64")) {
7727 if (!strequal(p, "x64")) {
7728 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
7730 } else if (strequal(environment, "Windows NT x86")) {
7731 if (!strequal(p, "i386")) {
7732 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
7734 } else {
7735 torture_assert(tctx, "unknown environment: '%s'\n", environment);
7738 return true;
7741 #if 0
7742 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
7743 const char *devicename)
7745 struct spoolss_DeviceMode *r;
7747 r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
7748 if (r == NULL) {
7749 return NULL;
7752 r->devicename = talloc_strdup(r, devicename);
7753 r->specversion = DMSPEC_NT4_AND_ABOVE;
7754 r->driverversion = 0x0600;
7755 r->size = 0x00dc;
7756 r->__driverextra_length = 0;
7757 r->fields = DEVMODE_FORMNAME |
7758 DEVMODE_TTOPTION |
7759 DEVMODE_PRINTQUALITY |
7760 DEVMODE_DEFAULTSOURCE |
7761 DEVMODE_COPIES |
7762 DEVMODE_SCALE |
7763 DEVMODE_PAPERSIZE |
7764 DEVMODE_ORIENTATION;
7765 r->orientation = DMORIENT_PORTRAIT;
7766 r->papersize = DMPAPER_LETTER;
7767 r->paperlength = 0;
7768 r->paperwidth = 0;
7769 r->scale = 100;
7770 r->copies = 55;
7771 r->defaultsource = DMBIN_FORMSOURCE;
7772 r->printquality = DMRES_HIGH;
7773 r->color = DMRES_MONOCHROME;
7774 r->duplex = DMDUP_SIMPLEX;
7775 r->yresolution = 0;
7776 r->ttoption = DMTT_SUBDEV;
7777 r->collate = DMCOLLATE_FALSE;
7778 r->formname = talloc_strdup(r, "Letter");
7780 return r;
7782 #endif
7784 static bool test_architecture_buffer(struct torture_context *tctx,
7785 void *private_data)
7787 struct test_spoolss_context *ctx =
7788 talloc_get_type_abort(private_data, struct test_spoolss_context);
7790 struct spoolss_OpenPrinterEx r;
7791 struct spoolss_UserLevel1 u1;
7792 struct policy_handle handle;
7793 uint32_t architectures[] = {
7794 PROCESSOR_ARCHITECTURE_INTEL,
7795 PROCESSOR_ARCHITECTURE_IA64,
7796 PROCESSOR_ARCHITECTURE_AMD64
7798 uint32_t needed[3];
7799 int i;
7800 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7801 struct dcerpc_binding_handle *b = p->binding_handle;
7803 for (i=0; i < ARRAY_SIZE(architectures); i++) {
7805 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7807 u1.size = 0;
7808 u1.client = NULL;
7809 u1.user = NULL;
7810 u1.build = 0;
7811 u1.major = 3;
7812 u1.minor = 0;
7813 u1.processor = architectures[i];
7815 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7816 r.in.datatype = NULL;
7817 r.in.devmode_ctr.devmode= NULL;
7818 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7819 r.in.userlevel_ctr.level = 1;
7820 r.in.userlevel_ctr.user_info.level1 = &u1;
7821 r.out.handle = &handle;
7823 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7824 torture_assert_werr_ok(tctx, r.out.result, "");
7827 struct spoolss_EnumPrinters e;
7828 uint32_t count;
7829 union spoolss_PrinterInfo *info;
7831 e.in.flags = PRINTER_ENUM_LOCAL;
7832 e.in.server = NULL;
7833 e.in.level = 2;
7834 e.in.buffer = NULL;
7835 e.in.offered = 0;
7836 e.out.count = &count;
7837 e.out.info = &info;
7838 e.out.needed = &needed[i];
7840 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7841 #if 0
7842 torture_comment(tctx, "needed was %d\n", needed[i]);
7843 #endif
7846 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7849 for (i=1; i < ARRAY_SIZE(architectures); i++) {
7850 if (needed[i-1] != needed[i]) {
7851 torture_fail(tctx,
7852 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7853 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7857 return true;
7860 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
7861 void *private_data)
7863 struct test_spoolss_context *ctx =
7864 talloc_get_type_abort(private_data, struct test_spoolss_context);
7865 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7866 struct dcerpc_binding_handle *b = p->binding_handle;
7868 return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
7871 static bool test_PrintServer_Forms(struct torture_context *tctx,
7872 void *private_data)
7874 struct test_spoolss_context *ctx =
7875 talloc_get_type_abort(private_data, struct test_spoolss_context);
7876 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7877 struct dcerpc_binding_handle *b = p->binding_handle;
7879 return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
7882 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
7883 void *private_data)
7885 struct test_spoolss_context *ctx =
7886 talloc_get_type_abort(private_data, struct test_spoolss_context);
7887 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7888 struct dcerpc_binding_handle *b = p->binding_handle;
7890 return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
7893 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
7895 NTSTATUS status;
7897 status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
7899 torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
7901 torture_assert(tctx,
7902 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
7903 "failed to open printserver");
7904 torture_assert(tctx,
7905 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
7906 "failed to get environment");
7908 return true;
7911 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
7913 struct test_spoolss_context *t;
7915 *data = t = talloc_zero(tctx, struct test_spoolss_context);
7917 return torture_rpc_spoolss_setup_common(tctx, t);
7920 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
7922 test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
7924 return true;
7927 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
7929 struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
7930 bool ret;
7932 ret = torture_rpc_spoolss_teardown_common(tctx, t);
7933 talloc_free(t);
7935 return ret;
7938 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
7940 struct dcerpc_pipe *p;
7941 struct dcerpc_binding_handle *b;
7942 const char *server_name_slash;
7943 const char *driver_name;
7944 const char *printer_name;
7945 const char *port_name;
7947 torture_assert_ntstatus_ok(tctx,
7948 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
7949 "Error connecting to server");
7951 p = t->spoolss_pipe;
7952 b = p->binding_handle;
7953 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7955 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
7956 t->driver.info8.driver_name = TORTURE_DRIVER;
7957 t->driver.info8.driver_path = "pscript5.dll";
7958 t->driver.info8.data_file = "cups6.ppd";
7959 t->driver.info8.config_file = "ps5ui.dll";
7960 t->driver.info8.help_file = "pscript.hlp";
7961 t->driver.info8.default_datatype = "RAW";
7962 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
7963 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
7964 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
7965 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
7966 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
7967 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
7968 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
7969 t->driver.info8.dependent_files->string[5] = "cups6.ini";
7970 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
7971 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
7973 t->driver.local.driver_directory= "/usr/share/cups/drivers";
7975 t->info2.portname = "LPT1:";
7977 printer_name = t->info2.printername;
7978 port_name = t->info2.portname;
7980 torture_assert(tctx,
7981 fillup_printserver_info(tctx, p, &t->driver),
7982 "failed to fillup printserver info");
7984 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
7986 torture_assert(tctx,
7987 compose_local_driver_directory(tctx, t->driver.remote.environment,
7988 t->driver.local.driver_directory,
7989 &t->driver.local.driver_directory),
7990 "failed to compose local driver directory");
7992 t->info2.drivername = "Microsoft XPS Document Writer";
7994 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7995 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7996 t->info2.drivername, t->driver.remote.environment);
7997 t->have_driver = true;
7998 goto try_add;
8001 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
8002 t->info2.drivername, t->driver.remote.environment);
8004 t->info2.drivername = "Microsoft XPS Document Writer v4";
8006 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
8007 torture_comment(tctx, "driver '%s' (architecture: %s, version: 4) is present on server\n",
8008 t->info2.drivername, t->driver.remote.environment);
8009 t->have_driver = true;
8010 goto try_add;
8013 torture_comment(tctx, "trying to upload own driver\n");
8015 if (!directory_exist(t->driver.local.driver_directory)) {
8016 torture_warning(tctx, "no local driver is available!");
8017 t->have_driver = false;
8018 goto try_add;
8021 torture_assert(tctx,
8022 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
8023 "failed to upload printer driver");
8025 torture_assert(tctx,
8026 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
8027 "failed to add driver");
8029 t->added_driver = true;
8030 t->have_driver = true;
8032 try_add:
8033 driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
8035 if (t->wellknown) {
8036 torture_assert(tctx,
8037 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
8038 "failed to add wellknown printer");
8039 } else {
8040 torture_assert(tctx,
8041 test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
8042 "failed to add printer");
8045 return true;
8048 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
8050 struct torture_printer_context *t;
8052 *data = t = talloc_zero(tctx, struct torture_printer_context);
8054 t->ex = false;
8055 t->wellknown = false;
8056 t->info2.printername = TORTURE_PRINTER;
8057 t->devmode = NULL;
8059 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8062 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
8064 struct torture_printer_context *t;
8066 *data = t = talloc_zero(tctx, struct torture_printer_context);
8068 t->ex = true;
8069 t->wellknown = false;
8070 t->info2.printername = TORTURE_PRINTER_EX;
8071 t->devmode = NULL;
8073 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8076 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
8078 struct torture_printer_context *t;
8080 *data = t = talloc_zero(tctx, struct torture_printer_context);
8082 t->ex = false;
8083 t->wellknown = true;
8084 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
8085 t->devmode = NULL;
8087 /* FIXME */
8088 if (t->wellknown) {
8089 torture_skip(tctx, "skipping AddPrinter level 1");
8092 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8095 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
8097 struct torture_printer_context *t;
8099 *data = t = talloc_zero(tctx, struct torture_printer_context);
8101 t->ex = true;
8102 t->wellknown = true;
8103 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
8104 t->devmode = NULL;
8106 /* FIXME */
8107 if (t->wellknown) {
8108 torture_skip(tctx, "skipping AddPrinterEx level 1");
8111 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8114 #if 0
8115 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
8117 struct torture_printer_context *t;
8119 *data = t = talloc_zero(tctx, struct torture_printer_context);
8121 t->ex = true;
8122 t->wellknown = false;
8123 t->info2.printername = TORTURE_PRINTER_EX;
8124 t->devmode = torture_devicemode(t, TORTURE_PRINTER_EX);
8126 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8128 #endif
8130 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
8132 bool found = false;
8133 struct dcerpc_pipe *p = t->spoolss_pipe;
8134 struct dcerpc_binding_handle *b;
8135 const char *printer_name = t->info2.printername;
8137 if (t->added_driver) {
8138 torture_assert(tctx,
8139 remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
8140 "failed to remove printer driver");
8143 if (p && !t->wellknown) {
8144 b = p->binding_handle;
8146 torture_assert(tctx,
8147 test_DeletePrinter(tctx, b, &t->handle),
8148 "failed to delete printer");
8150 torture_assert(tctx,
8151 test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
8152 printer_name, &found),
8153 "failed to enumerate printers");
8155 torture_assert(tctx, !found, "deleted printer still there");
8158 return true;
8161 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
8163 struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
8164 bool ret;
8166 ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
8167 talloc_free(t);
8169 return ret;
8172 static bool test_print_test(struct torture_context *tctx,
8173 void *private_data)
8175 struct torture_printer_context *t =
8176 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8177 struct dcerpc_pipe *p = t->spoolss_pipe;
8178 struct dcerpc_binding_handle *b = p->binding_handle;
8180 torture_assert(tctx,
8181 test_PausePrinter(tctx, b, &t->handle),
8182 "failed to pause printer");
8184 torture_assert(tctx,
8185 test_DoPrintTest(tctx, b, &t->handle),
8186 "failed to do print test");
8188 torture_assert(tctx,
8189 test_ResumePrinter(tctx, b, &t->handle),
8190 "failed to resume printer");
8192 return true;
8195 static bool test_print_test_extended(struct torture_context *tctx,
8196 void *private_data)
8198 struct torture_printer_context *t =
8199 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8200 struct dcerpc_pipe *p = t->spoolss_pipe;
8201 struct dcerpc_binding_handle *b = p->binding_handle;
8202 bool ret = true;
8204 torture_assert(tctx,
8205 test_PausePrinter(tctx, b, &t->handle),
8206 "failed to pause printer");
8208 ret = test_DoPrintTest_extended(tctx, b, &t->handle);
8209 if (ret == false) {
8210 torture_comment(tctx, "WARNING! failed to do extended print test\n");
8211 if (torture_setting_bool(tctx, "samba3", false)) {
8212 torture_comment(tctx, "non-critical for samba3\n");
8213 ret = true;
8214 tctx->last_result = TORTURE_SKIP;
8218 torture_assert(tctx,
8219 test_ResumePrinter(tctx, b, &t->handle),
8220 "failed to resume printer");
8222 return ret;
8225 static bool test_print_test_properties(struct torture_context *tctx,
8226 void *private_data)
8228 struct torture_printer_context *t =
8229 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8230 struct dcerpc_pipe *p = t->spoolss_pipe;
8231 struct dcerpc_binding_handle *b = p->binding_handle;
8233 if (torture_setting_bool(tctx, "samba3", false)) {
8234 torture_skip(tctx, "skip printer job property tests against samba");
8237 torture_assert(tctx,
8238 test_PausePrinter(tctx, b, &t->handle),
8239 "failed to pause printer");
8241 torture_assert(tctx,
8242 test_DoPrintTest_properties(tctx, b, &t->handle),
8243 "failed to test print job properties");
8245 torture_assert(tctx,
8246 test_ResumePrinter(tctx, b, &t->handle),
8247 "failed to resume printer");
8249 return true;
8252 /* use smbd file IO to spool a print job */
8253 static bool test_print_test_smbd(struct torture_context *tctx,
8254 void *private_data)
8256 struct torture_printer_context *t =
8257 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8258 struct dcerpc_pipe *p = t->spoolss_pipe;
8259 struct dcerpc_binding_handle *b = p->binding_handle;
8260 NTSTATUS status;
8261 uint32_t count;
8262 union spoolss_JobInfo *info = NULL;
8263 int i;
8265 struct smb2_tree *tree;
8266 struct smb2_handle job_h;
8267 struct cli_credentials *credentials = cmdline_credentials;
8268 struct smbcli_options options;
8269 TALLOC_CTX *mem_ctx = talloc_new(tctx);
8271 * Do not test against the dynamically added printers, printing via
8272 * smbd means that a different spoolss process may handle the
8273 * OpenPrinter request to the one that handled the AddPrinter request.
8274 * This currently leads to an ugly race condition where one process
8275 * sees the new printer and one doesn't.
8277 const char *share = TORTURE_PRINTER_STATIC1;
8279 torture_comment(tctx, "Testing smbd job spooling\n");
8280 lpcfg_smbcli_options(tctx->lp_ctx, &options);
8282 status = smb2_connect(mem_ctx,
8283 torture_setting_string(tctx, "host", NULL),
8284 lpcfg_smb_ports(tctx->lp_ctx),
8285 share,
8286 lpcfg_resolve_context(tctx->lp_ctx),
8287 credentials,
8288 &tree,
8289 tctx->ev,
8290 &options,
8291 lpcfg_socket_options(tctx->lp_ctx),
8292 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
8293 if (!NT_STATUS_IS_OK(status)) {
8294 printf("Failed to connect to SMB2 printer %s - %s\n",
8295 share, nt_errstr(status));
8296 return false;
8299 status = torture_smb2_testfile(tree, "smbd_spooler_job", &job_h);
8300 torture_assert_ntstatus_ok(tctx, status, "smbd spool job create");
8302 status = smb2_util_write(tree, job_h, "exciting print job data", 0,
8303 sizeof("exciting print job data"));
8304 torture_assert_ntstatus_ok(tctx, status, "smbd spool job write");
8306 /* check back end spoolss job was created */
8307 torture_assert(tctx,
8308 test_EnumJobs_args(tctx, b, &t->handle, 1, &count, &info),
8309 "EnumJobs level 1 failed");
8311 for (i = 0; i < count; i++) {
8312 if (!strcmp(info[i].info1.document_name, "smbd_spooler_job")) {
8313 break;
8316 torture_assert(tctx, (i != count), "smbd_spooler_job not found");
8318 status = smb2_util_close(tree, job_h);
8319 torture_assert_ntstatus_ok(tctx, status, "smbd spool job close");
8321 /* disconnect from printer share */
8322 talloc_free(mem_ctx);
8324 return true;
8327 static bool test_print_test_purge(struct torture_context *tctx,
8328 void *private_data)
8330 struct torture_printer_context *t =
8331 (struct torture_printer_context *)talloc_get_type_abort(private_data,
8332 struct torture_printer_context);
8333 struct dcerpc_pipe *p = t->spoolss_pipe;
8334 struct dcerpc_binding_handle *b = p->binding_handle;
8335 uint32_t num_jobs = 8;
8336 uint32_t *job_ids;
8337 int i;
8338 bool ret = true;
8339 uint32_t count;
8340 union spoolss_JobInfo *info;
8342 torture_assert(tctx,
8343 test_PausePrinter(tctx, b, &t->handle),
8344 "failed to pause printer");
8346 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
8347 for (i=0; i < num_jobs; i++) {
8348 ret = test_DoPrintTest_add_one_job(tctx, b, &t->handle,
8349 "TorturePrintJob",
8350 &job_ids[i]);
8351 torture_assert(tctx, ret, "failed to add print job");
8354 torture_assert(tctx,
8355 test_EnumJobs_args(tctx, b, &t->handle, 1, &count, &info),
8356 "EnumJobs level 1 failed");
8358 torture_assert_int_equal(tctx, count, num_jobs,
8359 "unexpected number of jobs in queue");
8361 torture_assert(tctx,
8362 test_printer_purge(tctx, b, &t->handle),
8363 "failed to purge printer");
8365 torture_assert(tctx,
8366 test_EnumJobs_args(tctx, b, &t->handle, 1, &count, &info),
8367 "EnumJobs level 1 failed");
8369 torture_assert_int_equal(tctx, count, 0,
8370 "unexpected number of jobs in queue");
8372 torture_assert(tctx,
8373 test_ResumePrinter(tctx, b, &t->handle),
8374 "failed to resume printer");
8376 return true;
8379 static bool test_printer_sd(struct torture_context *tctx,
8380 void *private_data)
8382 struct torture_printer_context *t =
8383 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8384 struct dcerpc_pipe *p = t->spoolss_pipe;
8385 struct dcerpc_binding_handle *b = p->binding_handle;
8387 torture_assert(tctx,
8388 test_PrinterInfo_SD(tctx, b, &t->handle),
8389 "failed to test security descriptors");
8391 return true;
8394 static bool test_printer_dm(struct torture_context *tctx,
8395 void *private_data)
8397 struct torture_printer_context *t =
8398 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8399 struct dcerpc_pipe *p = t->spoolss_pipe;
8401 torture_assert(tctx,
8402 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
8403 "failed to test devicemodes");
8405 return true;
8408 static bool test_printer_info_winreg(struct torture_context *tctx,
8409 void *private_data)
8411 struct torture_printer_context *t =
8412 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8413 struct dcerpc_pipe *p = t->spoolss_pipe;
8415 torture_assert(tctx,
8416 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
8417 "failed to test printer info winreg");
8419 return true;
8422 static bool test_printer_change_id(struct torture_context *tctx,
8423 void *private_data)
8425 struct torture_printer_context *t =
8426 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8427 struct dcerpc_pipe *p = t->spoolss_pipe;
8429 torture_assert(tctx,
8430 test_ChangeID(tctx, p, &t->handle),
8431 "failed to test change id");
8433 return true;
8436 static bool test_printer_keys(struct torture_context *tctx,
8437 void *private_data)
8439 struct torture_printer_context *t =
8440 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8441 struct dcerpc_pipe *p = t->spoolss_pipe;
8442 struct dcerpc_binding_handle *b = p->binding_handle;
8444 torture_assert(tctx,
8445 test_printer_all_keys(tctx, b, &t->handle),
8446 "failed to test printer keys");
8448 return true;
8451 static bool test_printer_data_consistency(struct torture_context *tctx,
8452 void *private_data)
8454 struct torture_printer_context *t =
8455 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8456 struct dcerpc_pipe *p = t->spoolss_pipe;
8458 torture_assert(tctx,
8459 test_EnumPrinterData_consistency(tctx, p, &t->handle),
8460 "failed to test printer data consistency");
8462 return true;
8465 static bool test_printer_data_keys(struct torture_context *tctx,
8466 void *private_data)
8468 struct torture_printer_context *t =
8469 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8470 struct dcerpc_pipe *p = t->spoolss_pipe;
8472 torture_assert(tctx,
8473 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
8474 "failed to test printer data keys");
8476 return true;
8479 static bool test_printer_data_values(struct torture_context *tctx,
8480 void *private_data)
8482 struct torture_printer_context *t =
8483 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8484 struct dcerpc_pipe *p = t->spoolss_pipe;
8486 torture_assert(tctx,
8487 test_SetPrinterDataEx_values(tctx, p, &t->handle),
8488 "failed to test printer data values");
8490 return true;
8493 static bool test_printer_data_set(struct torture_context *tctx,
8494 void *private_data)
8496 struct torture_printer_context *t =
8497 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8498 struct dcerpc_pipe *p = t->spoolss_pipe;
8500 torture_assert(tctx,
8501 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
8502 "failed to test printer data set");
8504 return true;
8507 static bool test_printer_data_winreg(struct torture_context *tctx,
8508 void *private_data)
8510 struct torture_printer_context *t =
8511 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8512 struct dcerpc_pipe *p = t->spoolss_pipe;
8514 torture_assert(tctx,
8515 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
8516 "failed to test printer data winreg");
8518 return true;
8521 static bool test_printer_data_dsspooler(struct torture_context *tctx,
8522 void *private_data)
8524 struct torture_printer_context *t =
8525 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8526 struct dcerpc_pipe *p = t->spoolss_pipe;
8528 torture_assert(tctx,
8529 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
8530 "failed to test printer data winreg dsspooler");
8532 return true;
8535 static bool test_printer_ic(struct torture_context *tctx,
8536 void *private_data)
8538 struct torture_printer_context *t =
8539 talloc_get_type_abort(private_data,
8540 struct torture_printer_context);
8541 struct dcerpc_pipe *p = t->spoolss_pipe;
8542 struct dcerpc_binding_handle *b = p->binding_handle;
8543 struct policy_handle gdi_handle;
8545 if (torture_setting_bool(tctx, "samba3", false)) {
8546 torture_skip(tctx, "skip printer information context tests against samba");
8550 struct spoolss_CreatePrinterIC r;
8551 struct spoolss_DevmodeContainer devmode_ctr;
8553 ZERO_STRUCT(devmode_ctr);
8555 r.in.handle = &t->handle;
8556 r.in.devmode_ctr = &devmode_ctr;
8557 r.out.gdi_handle = &gdi_handle;
8559 torture_assert_ntstatus_ok(tctx,
8560 dcerpc_spoolss_CreatePrinterIC_r(b, tctx, &r),
8561 "CreatePrinterIC failed");
8562 torture_assert_werr_ok(tctx, r.out.result,
8563 "CreatePrinterIC failed");
8567 struct spoolss_PlayGDIScriptOnPrinterIC r;
8568 DATA_BLOB in,out;
8569 int i;
8570 uint32_t num_fonts = 0;
8572 in = data_blob_string_const("");
8574 r.in.gdi_handle = &gdi_handle;
8575 r.in.pIn = in.data;
8576 r.in.cIn = in.length;
8577 r.in.ul = 0;
8579 for (i = 0; i < 4; i++) {
8581 out = data_blob_talloc_zero(tctx, i);
8583 r.in.cOut = out.length;
8584 r.out.pOut = out.data;
8586 torture_assert_ntstatus_ok(tctx,
8587 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8588 "PlayGDIScriptOnPrinterIC failed");
8589 torture_assert_werr_equal(tctx, r.out.result, WERR_NOMEM,
8590 "PlayGDIScriptOnPrinterIC failed");
8593 out = data_blob_talloc_zero(tctx, 4);
8595 r.in.cOut = out.length;
8596 r.out.pOut = out.data;
8598 torture_assert_ntstatus_ok(tctx,
8599 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8600 "PlayGDIScriptOnPrinterIC failed");
8601 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
8602 "PlayGDIScriptOnPrinterIC failed");
8604 /* now we should have the required length, so retry with a
8605 * buffer which is large enough to carry all font ids */
8607 num_fonts = IVAL(r.out.pOut, 0);
8609 torture_comment(tctx, "PlayGDIScriptOnPrinterIC gave font count of %d\n", num_fonts);
8611 out = data_blob_talloc_zero(tctx,
8612 num_fonts * sizeof(struct UNIVERSAL_FONT_ID) + 4);
8614 r.in.cOut = out.length;
8615 r.out.pOut = out.data;
8617 torture_assert_ntstatus_ok(tctx,
8618 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8619 "PlayGDIScriptOnPrinterIC failed");
8620 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
8621 "PlayGDIScriptOnPrinterIC failed");
8626 struct spoolss_DeletePrinterIC r;
8628 r.in.gdi_handle = &gdi_handle;
8629 r.out.gdi_handle = &gdi_handle;
8631 torture_assert_ntstatus_ok(tctx,
8632 dcerpc_spoolss_DeletePrinterIC_r(b, tctx, &r),
8633 "DeletePrinterIC failed");
8634 torture_assert_werr_ok(tctx, r.out.result,
8635 "DeletePrinterIC failed");
8639 return true;
8642 static bool test_printer_bidi(struct torture_context *tctx,
8643 void *private_data)
8645 struct torture_printer_context *t =
8646 talloc_get_type_abort(private_data,
8647 struct torture_printer_context);
8648 struct dcerpc_pipe *p = t->spoolss_pipe;
8649 struct dcerpc_binding_handle *b = p->binding_handle;
8650 struct spoolss_RpcSendRecvBidiData r;
8651 struct RPC_BIDI_REQUEST_CONTAINER bidi_req;
8652 struct RPC_BIDI_RESPONSE_CONTAINER *bidi_rep = NULL;
8654 if (torture_setting_bool(tctx, "samba3", false)) {
8655 torture_skip(tctx, "skip printer bidirectional tests against samba");
8658 ZERO_STRUCT(bidi_req);
8660 r.in.hPrinter = t->handle;
8661 r.in.pAction = "foobar";
8662 r.in.pReqData = &bidi_req;
8663 r.out.ppRespData = &bidi_rep;
8665 torture_assert_ntstatus_ok(tctx,
8666 dcerpc_spoolss_RpcSendRecvBidiData_r(b, tctx, &r),
8667 "RpcSendRecvBidiData failed");
8668 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
8669 "RpcSendRecvBidiData failed");
8671 if (!(t->info2.attributes & PRINTER_ATTRIBUTE_ENABLE_BIDI)) {
8672 torture_skip(tctx, "skipping further tests as printer is not BIDI enabled");
8675 r.in.pAction = BIDI_ACTION_ENUM_SCHEMA;
8677 torture_assert_ntstatus_ok(tctx,
8678 dcerpc_spoolss_RpcSendRecvBidiData_r(b, tctx, &r),
8679 "RpcSendRecvBidiData failed");
8680 torture_assert_werr_ok(tctx, r.out.result,
8681 "RpcSendRecvBidiData failed");
8683 return true;
8686 static bool test_printer_set_publish(struct torture_context *tctx,
8687 struct dcerpc_binding_handle *b,
8688 struct policy_handle *handle)
8690 union spoolss_PrinterInfo info;
8691 struct spoolss_SetPrinterInfo7 info7;
8692 struct spoolss_SetPrinterInfoCtr info_ctr;
8693 struct spoolss_DevmodeContainer devmode_ctr;
8694 struct sec_desc_buf secdesc_ctr;
8696 info7.guid = "";
8697 info7.action = DSPRINT_PUBLISH;
8699 ZERO_STRUCT(info_ctr);
8700 ZERO_STRUCT(devmode_ctr);
8701 ZERO_STRUCT(secdesc_ctr);
8702 info_ctr.level = 7;
8703 info_ctr.info.info7 = &info7;
8705 torture_assert(tctx,
8706 test_SetPrinter(tctx, b, handle, &info_ctr,
8707 &devmode_ctr, &secdesc_ctr, 0), "");
8709 torture_assert(tctx,
8710 test_GetPrinter_level(tctx, b, handle, 2, &info),
8711 "");
8712 torture_assert(tctx,
8713 (info.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED),
8714 "info2 publish flag not set");
8715 torture_assert(tctx,
8716 test_GetPrinter_level(tctx, b, handle, 7, &info),
8717 "");
8718 if (info.info7.action & DSPRINT_PENDING) {
8719 torture_comment(tctx, "publish is pending\n");
8720 torture_assert_int_equal(tctx,
8721 info.info7.action,
8722 (DSPRINT_PENDING | DSPRINT_PUBLISH),
8723 "info7 publish flag not set");
8724 } else {
8725 struct GUID guid;
8726 torture_assert_int_equal(tctx,
8727 info.info7.action,
8728 DSPRINT_PUBLISH,
8729 "info7 publish flag not set");
8730 torture_assert_ntstatus_ok(tctx,
8731 GUID_from_string(info.info7.guid,
8732 &guid),
8733 "invalid published printer GUID");
8736 return true;
8739 static bool test_printer_set_unpublish(struct torture_context *tctx,
8740 struct dcerpc_binding_handle *b,
8741 struct policy_handle *handle)
8743 union spoolss_PrinterInfo info;
8744 struct spoolss_SetPrinterInfo7 info7;
8745 struct spoolss_SetPrinterInfoCtr info_ctr;
8746 struct spoolss_DevmodeContainer devmode_ctr;
8747 struct sec_desc_buf secdesc_ctr;
8749 info7.action = DSPRINT_UNPUBLISH;
8750 info7.guid = "";
8752 ZERO_STRUCT(info_ctr);
8753 ZERO_STRUCT(devmode_ctr);
8754 ZERO_STRUCT(secdesc_ctr);
8755 info_ctr.level = 7;
8756 info_ctr.info.info7 = &info7;
8758 torture_assert(tctx,
8759 test_SetPrinter(tctx, b, handle, &info_ctr,
8760 &devmode_ctr, &secdesc_ctr, 0), "");
8762 torture_assert(tctx,
8763 test_GetPrinter_level(tctx, b, handle, 2, &info),
8764 "");
8765 torture_assert(tctx,
8766 !(info.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED),
8767 "info2 publish flag still set");
8768 torture_assert(tctx,
8769 test_GetPrinter_level(tctx, b, handle, 7, &info),
8770 "");
8772 if (info.info7.action & DSPRINT_PENDING) {
8773 struct GUID guid;
8774 torture_comment(tctx, "unpublish is pending\n");
8775 torture_assert_int_equal(tctx,
8776 info.info7.action,
8777 (DSPRINT_PENDING | DSPRINT_UNPUBLISH),
8778 "info7 unpublish flag not set");
8779 torture_assert_ntstatus_ok(tctx,
8780 GUID_from_string(info.info7.guid,
8781 &guid),
8782 "invalid printer GUID");
8783 } else {
8784 torture_assert_int_equal(tctx,
8785 info.info7.action, DSPRINT_UNPUBLISH,
8786 "info7 unpublish flag not set");
8789 return true;
8792 static bool test_printer_publish_toggle(struct torture_context *tctx,
8793 void *private_data)
8795 struct torture_printer_context *t =
8796 talloc_get_type_abort(private_data,
8797 struct torture_printer_context);
8798 struct dcerpc_pipe *p = t->spoolss_pipe;
8799 struct dcerpc_binding_handle *b = p->binding_handle;
8800 struct policy_handle *handle = &t->handle;
8801 union spoolss_PrinterInfo info7;
8802 union spoolss_PrinterInfo info2;
8804 /* check publish status via level 7 and level 2 */
8805 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 7, &info7),
8806 "");
8807 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info2),
8808 "");
8810 if (info2.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
8811 torture_assert_int_equal(tctx,
8812 info7.info7.action, DSPRINT_PUBLISH,
8813 "info7 publish flag not set");
8814 torture_assert(tctx, test_printer_set_unpublish(tctx, b, handle), "");
8815 torture_assert(tctx, test_printer_set_publish(tctx, b, handle), "");
8816 } else {
8817 torture_assert_int_equal(tctx,
8818 info7.info7.action, DSPRINT_UNPUBLISH,
8819 "info7 unpublish flag not set");
8820 torture_assert(tctx, test_printer_set_publish(tctx, b, handle), "");
8821 torture_assert(tctx, test_printer_set_unpublish(tctx, b, handle), "");
8824 return true;
8827 static bool test_driver_info_winreg(struct torture_context *tctx,
8828 void *private_data)
8830 struct torture_printer_context *t =
8831 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8832 struct dcerpc_pipe *p = t->spoolss_pipe;
8833 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
8835 if (!t->have_driver) {
8836 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
8839 torture_assert(tctx,
8840 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
8841 "failed to test driver info winreg");
8843 return true;
8846 void torture_tcase_printer(struct torture_tcase *tcase)
8848 torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
8849 torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
8850 torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
8851 torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
8852 torture_tcase_add_simple_test(tcase, "print_test_smbd", test_print_test_smbd);
8853 torture_tcase_add_simple_test(tcase, "print_test_properties", test_print_test_properties);
8854 torture_tcase_add_simple_test(tcase, "print_test_purge", test_print_test_purge);
8855 torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
8856 torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
8857 torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
8858 torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
8859 torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
8860 torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
8861 torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
8862 torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
8863 torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
8864 torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
8865 torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
8866 torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
8867 torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
8868 torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
8869 torture_tcase_add_simple_test(tcase, "printer_ic", test_printer_ic);
8870 torture_tcase_add_simple_test(tcase, "bidi", test_printer_bidi);
8871 torture_tcase_add_simple_test(tcase, "publish_toggle",
8872 test_printer_publish_toggle);
8875 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
8877 struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
8878 struct torture_tcase *tcase;
8880 tcase = torture_suite_add_tcase(suite, "addprinter");
8882 torture_tcase_set_fixture(tcase,
8883 torture_rpc_spoolss_printer_setup,
8884 torture_rpc_spoolss_printer_teardown);
8886 torture_tcase_printer(tcase);
8888 tcase = torture_suite_add_tcase(suite, "addprinterex");
8890 torture_tcase_set_fixture(tcase,
8891 torture_rpc_spoolss_printerex_setup,
8892 torture_rpc_spoolss_printer_teardown);
8894 torture_tcase_printer(tcase);
8896 tcase = torture_suite_add_tcase(suite, "addprinterwkn");
8898 torture_tcase_set_fixture(tcase,
8899 torture_rpc_spoolss_printerwkn_setup,
8900 torture_rpc_spoolss_printer_teardown);
8902 tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
8904 torture_tcase_set_fixture(tcase,
8905 torture_rpc_spoolss_printerexwkn_setup,
8906 torture_rpc_spoolss_printer_teardown);
8908 #if 0
8909 /* test is not correct */
8910 tcase = torture_suite_add_tcase(suite, "addprinterdm");
8912 torture_tcase_set_fixture(tcase,
8913 torture_rpc_spoolss_printerdm_setup,
8914 torture_rpc_spoolss_printer_teardown);
8916 torture_tcase_printer(tcase);
8917 #endif
8918 return suite;
8921 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
8923 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
8924 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
8926 torture_tcase_set_fixture(tcase,
8927 torture_rpc_spoolss_setup,
8928 torture_rpc_spoolss_teardown);
8930 torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
8931 torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
8932 torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
8933 torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
8934 torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
8935 torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
8936 torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
8937 torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
8938 torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
8939 torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
8940 torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
8941 torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
8942 torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
8943 torture_tcase_add_simple_test(tcase, "add_processor", test_add_print_processor);
8944 torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
8945 torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
8946 torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
8947 torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
8948 torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
8949 torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
8950 torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
8952 torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
8954 return suite;
8957 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
8958 struct dcerpc_binding_handle *b,
8959 const char *server,
8960 const char *environment,
8961 const char **dir_p)
8963 struct spoolss_GetPrinterDriverDirectory r;
8964 uint32_t needed;
8966 r.in.server = server;
8967 r.in.environment = environment;
8968 r.in.level = 1;
8969 r.in.buffer = NULL;
8970 r.in.offered = 0;
8971 r.out.needed = &needed;
8973 torture_assert_ntstatus_ok(tctx,
8974 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8975 "failed to query driver directory");
8977 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
8978 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
8979 r.in.buffer = &blob;
8980 r.in.offered = needed;
8982 torture_assert_ntstatus_ok(tctx,
8983 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8984 "failed to query driver directory");
8987 torture_assert_werr_ok(tctx, r.out.result,
8988 "failed to query driver directory");
8990 if (dir_p) {
8991 *dir_p = r.out.info->info1.directory_name;
8994 return true;
8997 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8999 if (info_ctr == NULL) {
9000 return NULL;
9003 switch (info_ctr->level) {
9004 case 1:
9005 return info_ctr->info.info1->driver_name;
9006 case 2:
9007 return info_ctr->info.info2->driver_name;
9008 case 3:
9009 return info_ctr->info.info3->driver_name;
9010 case 4:
9011 return info_ctr->info.info4->driver_name;
9012 case 6:
9013 return info_ctr->info.info6->driver_name;
9014 case 8:
9015 return info_ctr->info.info8->driver_name;
9016 default:
9017 return NULL;
9021 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
9023 if (info_ctr == NULL) {
9024 return NULL;
9027 switch (info_ctr->level) {
9028 case 2:
9029 return info_ctr->info.info2->architecture;
9030 case 3:
9031 return info_ctr->info.info3->architecture;
9032 case 4:
9033 return info_ctr->info.info4->architecture;
9034 case 6:
9035 return info_ctr->info.info6->architecture;
9036 case 8:
9037 return info_ctr->info.info8->architecture;
9038 default:
9039 return NULL;
9044 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
9045 struct dcerpc_binding_handle *b,
9046 const char *servername,
9047 struct spoolss_AddDriverInfoCtr *info_ctr,
9048 WERROR expected_result)
9050 struct spoolss_AddPrinterDriver r;
9051 const char *drivername = get_driver_from_info(info_ctr);
9052 const char *environment = get_environment_from_info(info_ctr);
9054 r.in.servername = servername;
9055 r.in.info_ctr = info_ctr;
9057 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
9058 drivername, info_ctr->level, environment);
9060 torture_assert_ntstatus_ok(tctx,
9061 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
9062 "spoolss_AddPrinterDriver failed");
9063 torture_assert_werr_equal(tctx, r.out.result, expected_result,
9064 "spoolss_AddPrinterDriver failed with unexpected result");
9066 return true;
9070 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
9071 struct dcerpc_binding_handle *b,
9072 const char *servername,
9073 struct spoolss_AddDriverInfoCtr *info_ctr,
9074 uint32_t flags,
9075 WERROR expected_result)
9077 struct spoolss_AddPrinterDriverEx r;
9078 const char *drivername = get_driver_from_info(info_ctr);
9079 const char *environment = get_environment_from_info(info_ctr);
9081 r.in.servername = servername;
9082 r.in.info_ctr = info_ctr;
9083 r.in.flags = flags;
9085 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
9086 drivername, info_ctr->level, environment);
9088 torture_assert_ntstatus_ok(tctx,
9089 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
9090 "AddPrinterDriverEx failed");
9091 torture_assert_werr_equal(tctx, r.out.result, expected_result,
9092 "AddPrinterDriverEx failed with unexpected result");
9094 return true;
9097 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
9098 if (path && strlen(path)) {\
9099 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
9102 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
9103 struct dcerpc_binding_handle *b,
9104 const char *server_name,
9105 struct spoolss_AddDriverInfo8 *r,
9106 uint32_t flags,
9107 bool ex,
9108 const char *remote_driver_dir)
9110 struct spoolss_AddDriverInfoCtr info_ctr;
9111 struct spoolss_AddDriverInfo1 info1;
9113 ZERO_STRUCT(info1);
9115 info_ctr.level = 1;
9116 info_ctr.info.info1 = &info1;
9118 if (ex) {
9119 torture_assert(tctx,
9120 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
9121 "failed to test AddPrinterDriverEx level 1");
9122 } else {
9123 torture_assert(tctx,
9124 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9125 "failed to test AddPrinterDriver level 1");
9128 info1.driver_name = r->driver_name;
9130 if (ex) {
9131 torture_assert(tctx,
9132 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
9133 "failed to test AddPrinterDriverEx level 1");
9134 } else {
9135 torture_assert(tctx,
9136 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9137 "failed to test AddPrinterDriver level 1");
9140 return true;
9143 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
9144 struct dcerpc_binding_handle *b,
9145 const char *server_name,
9146 struct spoolss_AddDriverInfo8 *r,
9147 uint32_t flags,
9148 bool ex,
9149 const char *remote_driver_dir)
9151 struct spoolss_AddDriverInfoCtr info_ctr;
9152 struct spoolss_AddDriverInfo2 info2;
9153 union spoolss_DriverInfo info;
9155 ZERO_STRUCT(info2);
9157 info_ctr.level = 2;
9158 info_ctr.info.info2 = &info2;
9160 if (ex) {
9161 torture_assert(tctx,
9162 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9163 "failed to test AddPrinterDriverEx level 2");
9164 } else {
9165 torture_assert(tctx,
9166 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9167 "failed to test AddPrinterDriver level 2");
9170 info2.driver_name = r->driver_name;
9172 if (ex) {
9173 torture_assert(tctx,
9174 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9175 "failed to test AddPrinterDriverEx level 2");
9176 } else {
9177 torture_assert(tctx,
9178 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9179 "failed to test AddPrinterDriver level 2");
9182 info2.version = r->version;
9184 if (ex) {
9185 torture_assert(tctx,
9186 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9187 "failed to test AddPrinterDriverEx level 2");
9188 } else {
9189 torture_assert(tctx,
9190 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9191 "failed to test AddPrinterDriver level 2");
9194 info2.architecture = r->architecture;
9196 if (ex) {
9197 torture_assert(tctx,
9198 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9199 "failed to test AddPrinterDriverEx level 2");
9200 } else {
9201 torture_assert(tctx,
9202 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9203 "failed to test AddPrinterDriver level 2");
9206 info2.driver_path = r->driver_path;
9208 if (ex) {
9209 torture_assert(tctx,
9210 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9211 "failed to test AddPrinterDriverEx level 2");
9212 } else {
9213 torture_assert(tctx,
9214 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9215 "failed to test AddPrinterDriver level 2");
9218 info2.data_file = r->data_file;
9220 if (ex) {
9221 torture_assert(tctx,
9222 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9223 "failed to test AddPrinterDriverEx level 2");
9224 } else {
9225 torture_assert(tctx,
9226 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9227 "failed to test AddPrinterDriver level 2");
9230 info2.config_file = r->config_file;
9232 if (ex) {
9233 torture_assert(tctx,
9234 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
9235 "failed to test AddPrinterDriverEx");
9238 if (ex) {
9239 torture_assert(tctx,
9240 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9241 "failed to test AddPrinterDriverEx level 2");
9242 } else {
9243 torture_assert(tctx,
9244 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
9245 "failed to test AddPrinterDriver level 2");
9248 torture_assert(tctx,
9249 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
9250 "failed to find added printer driver");
9252 if (remote_driver_dir) {
9253 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
9254 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
9255 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
9258 return true;
9261 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
9262 struct dcerpc_binding_handle *b,
9263 const char *server_name,
9264 struct spoolss_AddDriverInfo8 *r,
9265 uint32_t flags,
9266 bool ex,
9267 const char *remote_driver_dir)
9269 struct spoolss_AddDriverInfoCtr info_ctr;
9270 struct spoolss_AddDriverInfo3 info3;
9271 union spoolss_DriverInfo info;
9273 info3.driver_name = r->driver_name;
9274 info3.version = r->version;
9275 info3.architecture = r->architecture;
9276 info3.driver_path = r->driver_path;
9277 info3.data_file = r->data_file;
9278 info3.config_file = r->config_file;
9279 info3.help_file = r->help_file;
9280 info3.monitor_name = r->monitor_name;
9281 info3.default_datatype = r->default_datatype;
9282 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
9283 info3.dependent_files = r->dependent_files;
9285 info_ctr.level = 3;
9286 info_ctr.info.info3 = &info3;
9288 if (ex) {
9289 torture_assert(tctx,
9290 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9291 "failed to test AddPrinterDriverEx level 3");
9292 } else {
9293 torture_assert(tctx,
9294 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
9295 "failed to test AddPrinterDriver level 3");
9298 torture_assert(tctx,
9299 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
9300 "failed to find added printer driver");
9302 if (remote_driver_dir) {
9303 int i;
9304 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
9305 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
9306 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
9307 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
9308 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
9309 ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
9313 return true;
9316 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
9317 struct dcerpc_binding_handle *b,
9318 const char *server_name,
9319 struct spoolss_AddDriverInfo8 *r,
9320 uint32_t flags,
9321 bool ex,
9322 const char *remote_driver_dir)
9324 struct spoolss_AddDriverInfoCtr info_ctr;
9325 struct spoolss_AddDriverInfo4 info4;
9326 union spoolss_DriverInfo info;
9328 info4.version = r->version;
9329 info4.driver_name = r->driver_name;
9330 info4.architecture = r->architecture;
9331 info4.driver_path = r->driver_path;
9332 info4.data_file = r->data_file;
9333 info4.config_file = r->config_file;
9334 info4.help_file = r->help_file;
9335 info4.monitor_name = r->monitor_name;
9336 info4.default_datatype = r->default_datatype;
9337 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
9338 info4.dependent_files = r->dependent_files;
9339 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
9340 info4.previous_names = r->previous_names;
9342 info_ctr.level = 4;
9343 info_ctr.info.info4 = &info4;
9345 if (ex) {
9346 torture_assert(tctx,
9347 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9348 "failed to test AddPrinterDriverEx level 4");
9349 } else {
9350 torture_assert(tctx,
9351 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
9352 "failed to test AddPrinterDriver level 4");
9355 torture_assert(tctx,
9356 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
9357 "failed to find added printer driver");
9359 if (remote_driver_dir) {
9360 int i;
9361 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
9362 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
9363 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
9364 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
9365 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
9366 ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
9370 return true;
9373 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
9374 struct dcerpc_binding_handle *b,
9375 const char *server_name,
9376 struct spoolss_AddDriverInfo8 *r,
9377 uint32_t flags,
9378 bool ex,
9379 const char *remote_driver_dir)
9381 struct spoolss_AddDriverInfoCtr info_ctr;
9382 struct spoolss_AddDriverInfo6 info6;
9383 union spoolss_DriverInfo info;
9385 info6.version = r->version;
9386 info6.driver_name = r->driver_name;
9387 info6.architecture = r->architecture;
9388 info6.driver_path = r->driver_path;
9389 info6.data_file = r->data_file;
9390 info6.config_file = r->config_file;
9391 info6.help_file = r->help_file;
9392 info6.monitor_name = r->monitor_name;
9393 info6.default_datatype = r->default_datatype;
9394 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
9395 info6.dependent_files = r->dependent_files;
9396 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
9397 info6.previous_names = r->previous_names;
9398 info6.driver_date = r->driver_date;
9399 info6.driver_version = r->driver_version;
9400 info6.manufacturer_name = r->manufacturer_name;
9401 info6.manufacturer_url = r->manufacturer_url;
9402 info6.hardware_id = r->hardware_id;
9403 info6.provider = r->provider;
9405 info_ctr.level = 6;
9406 info_ctr.info.info6 = &info6;
9408 if (ex) {
9409 torture_assert(tctx,
9410 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9411 "failed to test AddPrinterDriverEx level 6");
9412 } else {
9413 torture_assert(tctx,
9414 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9415 "failed to test AddPrinterDriver level 6");
9418 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9420 if (!ex) {
9421 return true;
9424 torture_assert(tctx,
9425 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
9426 "failed to find added printer driver");
9428 if (remote_driver_dir) {
9429 int i;
9430 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
9431 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
9432 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
9433 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
9434 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
9435 ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
9439 torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
9440 torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
9442 return true;
9445 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
9446 struct dcerpc_binding_handle *b,
9447 const char *server_name,
9448 struct spoolss_AddDriverInfo8 *r,
9449 uint32_t flags,
9450 bool ex,
9451 const char *remote_driver_dir)
9453 struct spoolss_AddDriverInfoCtr info_ctr;
9454 union spoolss_DriverInfo info;
9456 info_ctr.level = 8;
9457 info_ctr.info.info8 = r;
9459 if (ex) {
9460 torture_assert(tctx,
9461 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9462 "failed to test AddPrinterDriverEx level 8");
9463 } else {
9464 torture_assert(tctx,
9465 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9466 "failed to test AddPrinterDriver level 8");
9469 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9471 if (!ex) {
9472 return true;
9475 torture_assert(tctx,
9476 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
9477 "failed to find added printer driver");
9479 if (remote_driver_dir) {
9480 int i;
9481 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
9482 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
9483 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
9484 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
9485 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
9486 ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
9490 torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
9491 torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
9493 return true;
9496 #undef ASSERT_DRIVER_PATH
9498 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
9499 struct dcerpc_binding_handle *b,
9500 const char *server,
9501 const char *driver,
9502 const char *environment,
9503 WERROR expected_result)
9505 struct spoolss_DeletePrinterDriver r;
9507 r.in.server = server;
9508 r.in.architecture = environment;
9509 r.in.driver = driver;
9511 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
9513 torture_assert_ntstatus_ok(tctx,
9514 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
9515 "DeletePrinterDriver failed");
9516 torture_assert_werr_equal(tctx, r.out.result, expected_result,
9517 "DeletePrinterDriver failed with unexpected result");
9519 return true;
9522 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
9523 struct dcerpc_binding_handle *b,
9524 const char *server,
9525 const char *driver,
9526 const char *environment,
9527 uint32_t delete_flags,
9528 uint32_t version,
9529 WERROR expected_result)
9531 struct spoolss_DeletePrinterDriverEx r;
9533 r.in.server = server;
9534 r.in.architecture = environment;
9535 r.in.driver = driver;
9536 r.in.delete_flags = delete_flags;
9537 r.in.version = version;
9539 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
9541 torture_assert_ntstatus_ok(tctx,
9542 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
9543 "DeletePrinterDriverEx failed");
9544 torture_assert_werr_equal(tctx, r.out.result, expected_result,
9545 "DeletePrinterDriverEx failed with unexpected result");
9547 return true;
9550 static bool test_DeletePrinterDriver(struct torture_context *tctx,
9551 struct dcerpc_binding_handle *b,
9552 const char *server_name,
9553 const char *driver,
9554 const char *environment)
9556 torture_assert(tctx,
9557 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
9558 "failed to delete driver");
9560 torture_assert(tctx,
9561 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
9562 "failed to delete driver");
9564 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
9565 torture_fail(tctx, "deleted driver still enumerated");
9568 torture_assert(tctx,
9569 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
9570 "2nd delete failed");
9572 return true;
9575 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
9576 struct dcerpc_binding_handle *b,
9577 const char *server_name,
9578 const char *driver,
9579 const char *environment,
9580 uint32_t delete_flags,
9581 uint32_t version)
9583 torture_assert(tctx,
9584 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
9585 "failed to delete driver");
9587 torture_assert(tctx,
9588 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
9589 "failed to delete driver");
9591 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
9592 torture_fail(tctx, "deleted driver still enumerated");
9595 torture_assert(tctx,
9596 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
9597 "2nd delete failed");
9599 return true;
9602 static bool test_PrinterDriver_args(struct torture_context *tctx,
9603 struct dcerpc_binding_handle *b,
9604 const char *server_name,
9605 uint32_t level,
9606 struct spoolss_AddDriverInfo8 *r,
9607 uint32_t add_flags,
9608 uint32_t delete_flags,
9609 uint32_t delete_version,
9610 bool ex,
9611 const char *remote_driver_dir)
9613 bool ret = true;
9615 switch (level) {
9616 case 1:
9617 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9618 break;
9619 case 2:
9620 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9621 break;
9622 case 3:
9623 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9624 break;
9625 case 4:
9626 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9627 break;
9628 case 6:
9629 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9630 break;
9631 case 8:
9632 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9633 break;
9634 default:
9635 return false;
9638 if (ret == false) {
9639 return ret;
9642 if (level == 1) {
9643 return ret;
9646 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9648 if (!ex && (level == 6 || level == 8)) {
9649 return ret;
9653 struct dcerpc_pipe *p2;
9654 struct policy_handle hive_handle;
9655 struct dcerpc_binding_handle *b2;
9657 torture_assert_ntstatus_ok(tctx,
9658 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
9659 "could not open winreg pipe");
9660 b2 = p2->binding_handle;
9662 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
9664 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
9666 test_winreg_CloseKey(tctx, b2, &hive_handle);
9668 talloc_free(p2);
9671 if (ex) {
9672 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
9673 } else {
9674 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
9678 static bool fillup_printserver_info(struct torture_context *tctx,
9679 struct dcerpc_pipe *p,
9680 struct torture_driver_context *d)
9682 struct policy_handle server_handle;
9683 struct dcerpc_binding_handle *b = p->binding_handle;
9684 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9686 torture_assert(tctx,
9687 test_OpenPrinter_server(tctx, p, &server_handle),
9688 "failed to open printserver");
9689 torture_assert(tctx,
9690 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
9691 "failed to get environment");
9692 torture_assert(tctx,
9693 test_ClosePrinter(tctx, b, &server_handle),
9694 "failed to close printserver");
9696 torture_assert(tctx,
9697 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
9698 d->local.environment ? d->local.environment : d->remote.environment,
9699 &d->remote.driver_directory),
9700 "failed to get driver directory");
9702 return true;
9705 static const char *driver_directory_dir(const char *driver_directory)
9707 char *p;
9709 p = strrchr(driver_directory, '\\');
9710 if (p) {
9711 return p+1;
9714 return NULL;
9717 static const char *driver_directory_share(struct torture_context *tctx,
9718 const char *driver_directory)
9720 const char *p;
9721 char *tok;
9723 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
9724 driver_directory += 2;
9727 p = talloc_strdup(tctx, driver_directory);
9729 torture_assert(tctx,
9730 next_token_talloc(tctx, &p, &tok, "\\"),
9731 "cannot explode uri");
9732 torture_assert(tctx,
9733 next_token_talloc(tctx, &p, &tok, "\\"),
9734 "cannot explode uri");
9736 return tok;
9739 static bool upload_printer_driver_file(struct torture_context *tctx,
9740 struct smbcli_state *cli,
9741 struct torture_driver_context *d,
9742 const char *file_name)
9744 XFILE *f;
9745 int fnum;
9746 uint8_t *buf;
9747 int maxwrite = 64512;
9748 off_t nread = 0;
9749 size_t start = 0;
9750 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
9751 const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
9752 const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
9754 if (!file_name || strlen(file_name) == 0) {
9755 return true;
9758 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
9760 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
9761 if (fnum == -1) {
9762 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
9765 f = x_fopen(local_name, O_RDONLY, 0);
9766 if (f == NULL) {
9767 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
9770 buf = talloc_array(tctx, uint8_t, maxwrite);
9771 if (!buf) {
9772 x_fclose(f);
9773 return false;
9776 while (!x_feof(f)) {
9777 int n = maxwrite;
9778 int ret;
9780 if ((n = x_fread(buf, 1, n, f)) < 1) {
9781 if((n == 0) && x_feof(f))
9782 break; /* Empty local file. */
9784 torture_warning(tctx,
9785 "failed to read file: %s\n", strerror(errno));
9786 break;
9789 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
9791 if (n != ret) {
9792 torture_warning(tctx,
9793 "failed to write file: %s\n", smbcli_errstr(cli->tree));
9794 break;
9797 nread += n;
9800 x_fclose(f);
9802 torture_assert_ntstatus_ok(tctx,
9803 smbcli_close(cli->tree, fnum),
9804 "failed to close file");
9806 return true;
9809 static bool connect_printer_driver_share(struct torture_context *tctx,
9810 const char *server_name,
9811 const char *share_name,
9812 struct smbcli_state **cli)
9814 struct smbcli_options smb_options;
9815 struct smbcli_session_options smb_session_options;
9817 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
9818 share_name, server_name);
9820 lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
9821 lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
9823 torture_assert_ntstatus_ok(tctx,
9824 smbcli_full_connection(tctx, cli, server_name,
9825 lpcfg_smb_ports(tctx->lp_ctx),
9826 share_name, NULL,
9827 lpcfg_socket_options(tctx->lp_ctx),
9828 cmdline_credentials,
9829 lpcfg_resolve_context(tctx->lp_ctx),
9830 tctx->ev,
9831 &smb_options,
9832 &smb_session_options,
9833 lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
9834 "failed to open driver share");
9836 return true;
9839 static bool upload_printer_driver(struct torture_context *tctx,
9840 const char *server_name,
9841 struct torture_driver_context *d)
9843 struct smbcli_state *cli;
9844 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9845 int i;
9847 torture_assert(tctx,
9848 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9849 "failed to connect to driver share");
9851 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
9852 server_name, share_name);
9854 torture_assert(tctx,
9855 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
9856 "failed to upload driver_path");
9857 torture_assert(tctx,
9858 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
9859 "failed to upload data_file");
9860 torture_assert(tctx,
9861 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
9862 "failed to upload config_file");
9863 torture_assert(tctx,
9864 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
9865 "failed to upload help_file");
9866 if (d->info8.dependent_files) {
9867 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9868 torture_assert(tctx,
9869 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9870 "failed to upload dependent_files");
9874 talloc_free(cli);
9876 return true;
9879 static bool check_printer_driver_file(struct torture_context *tctx,
9880 struct smbcli_state *cli,
9881 struct torture_driver_context *d,
9882 const char *file_name)
9884 const char *remote_arch_dir = driver_directory_dir(d->remote.driver_directory);
9885 const char *remote_name = talloc_asprintf(tctx, "%s\\%d\\%s",
9886 remote_arch_dir,
9887 d->info8.version,
9888 file_name);
9889 int fnum;
9891 torture_assert(tctx, (file_name && strlen(file_name) != 0), "invalid filename");
9893 torture_comment(tctx, "checking for driver file at %s\n", remote_name);
9895 fnum = smbcli_open(cli->tree, remote_name, O_RDONLY, DENY_NONE);
9896 if (fnum == -1) {
9897 return false;
9900 torture_assert_ntstatus_ok(tctx,
9901 smbcli_close(cli->tree, fnum),
9902 "failed to close driver file");
9904 return true;
9907 static bool check_printer_driver_files(struct torture_context *tctx,
9908 const char *server_name,
9909 struct torture_driver_context *d,
9910 bool expect_exist)
9912 struct smbcli_state *cli;
9913 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9914 int i;
9916 torture_assert(tctx,
9917 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9918 "failed to connect to driver share");
9920 torture_comment(tctx, "checking %sexistent driver files at \\\\%s\\%s\n",
9921 (expect_exist ? "": "non-"),
9922 server_name, share_name);
9924 if (d->info8.driver_path && d->info8.driver_path[0]) {
9925 torture_assert(tctx,
9926 check_printer_driver_file(tctx, cli, d, d->info8.driver_path) == expect_exist,
9927 "failed driver_path check");
9929 if (d->info8.data_file && d->info8.data_file[0]) {
9930 torture_assert(tctx,
9931 check_printer_driver_file(tctx, cli, d, d->info8.data_file) == expect_exist,
9932 "failed data_file check");
9934 if (d->info8.config_file && d->info8.config_file[0]) {
9935 torture_assert(tctx,
9936 check_printer_driver_file(tctx, cli, d, d->info8.config_file) == expect_exist,
9937 "failed config_file check");
9939 if (d->info8.help_file && d->info8.help_file[0]) {
9940 torture_assert(tctx,
9941 check_printer_driver_file(tctx, cli, d, d->info8.help_file) == expect_exist,
9942 "failed help_file check");
9944 if (d->info8.dependent_files) {
9945 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9946 torture_assert(tctx,
9947 check_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]) == expect_exist,
9948 "failed dependent_files check");
9952 talloc_free(cli);
9954 return true;
9957 static bool remove_printer_driver_file(struct torture_context *tctx,
9958 struct smbcli_state *cli,
9959 struct torture_driver_context *d,
9960 const char *file_name)
9962 const char *remote_name;
9963 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
9965 if (!file_name || strlen(file_name) == 0) {
9966 return true;
9969 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
9971 torture_comment(tctx, "Removing %s\n", remote_name);
9973 torture_assert_ntstatus_ok(tctx,
9974 smbcli_unlink(cli->tree, remote_name),
9975 "failed to unlink");
9977 return true;
9980 static bool remove_printer_driver(struct torture_context *tctx,
9981 const char *server_name,
9982 struct torture_driver_context *d)
9984 struct smbcli_state *cli;
9985 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9986 int i;
9988 torture_assert(tctx,
9989 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9990 "failed to connect to driver share");
9992 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
9993 server_name, share_name);
9995 torture_assert(tctx,
9996 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
9997 "failed to remove driver_path");
9998 torture_assert(tctx,
9999 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
10000 "failed to remove data_file");
10001 if (!strequal(d->info8.config_file, d->info8.driver_path)) {
10002 torture_assert(tctx,
10003 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
10004 "failed to remove config_file");
10006 torture_assert(tctx,
10007 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
10008 "failed to remove help_file");
10009 if (d->info8.dependent_files) {
10010 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
10011 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
10012 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
10013 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
10014 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
10015 continue;
10017 torture_assert(tctx,
10018 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
10019 "failed to remove dependent_files");
10023 talloc_free(cli);
10025 return true;
10029 static bool test_add_driver_arg(struct torture_context *tctx,
10030 struct dcerpc_pipe *p,
10031 struct torture_driver_context *d)
10033 bool ret = true;
10034 struct dcerpc_binding_handle *b = p->binding_handle;
10035 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10036 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
10037 int i;
10038 struct spoolss_AddDriverInfo8 info8;
10039 uint32_t add_flags = APD_COPY_NEW_FILES;
10040 uint32_t delete_flags = 0;
10042 ZERO_STRUCT(info8);
10044 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
10045 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
10047 torture_assert(tctx,
10048 fillup_printserver_info(tctx, p, d),
10049 "failed to fillup printserver info");
10051 if (!directory_exist(d->local.driver_directory)) {
10052 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10055 torture_assert(tctx,
10056 upload_printer_driver(tctx, dcerpc_server_name(p), d),
10057 "failed to upload printer driver");
10059 info8 = d->info8;
10060 if (d->info8.dependent_files) {
10061 info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
10062 if (d->info8.dependent_files->string) {
10063 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
10065 info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
10066 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
10067 info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
10071 info8.architecture = d->local.environment;
10073 for (i=0; i < ARRAY_SIZE(levels); i++) {
10075 if (torture_setting_bool(tctx, "samba3", false)) {
10076 switch (levels[i]) {
10077 case 2:
10078 case 4:
10079 case 8:
10080 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
10081 continue;
10082 default:
10083 break;
10086 if (torture_setting_bool(tctx, "w2k3", false)) {
10087 switch (levels[i]) {
10088 case 8:
10089 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
10090 continue;
10091 default:
10092 break;
10096 torture_comment(tctx,
10097 "Testing PrinterDriver%s '%s' add & delete level %d\n",
10098 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
10100 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex, d->remote.driver_directory);
10103 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
10104 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
10105 if (d->info8.config_file) {
10106 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
10108 if (d->info8.help_file) {
10109 info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
10111 if (d->info8.dependent_files && d->info8.dependent_files->string) {
10112 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
10113 info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
10117 for (i=0; i < ARRAY_SIZE(levels); i++) {
10119 if (torture_setting_bool(tctx, "samba3", false)) {
10120 switch (levels[i]) {
10121 case 2:
10122 case 4:
10123 case 8:
10124 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
10125 continue;
10126 default:
10127 break;
10130 if (torture_setting_bool(tctx, "w2k3", false)) {
10131 switch (levels[i]) {
10132 case 8:
10133 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
10134 continue;
10135 default:
10136 break;
10140 torture_comment(tctx,
10141 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
10142 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
10144 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex, d->remote.driver_directory);
10147 torture_assert(tctx,
10148 remove_printer_driver(tctx, dcerpc_server_name(p), d),
10149 "failed to remove printer driver");
10151 torture_comment(tctx, "\n");
10153 return ret;
10156 static bool test_add_driver_ex_64(struct torture_context *tctx,
10157 struct dcerpc_pipe *p)
10159 struct torture_driver_context *d;
10161 d = talloc_zero(tctx, struct torture_driver_context);
10163 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10164 d->info8.driver_name = TORTURE_DRIVER_EX;
10165 d->info8.architecture = NULL;
10166 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10167 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10168 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10169 d->local.environment = talloc_strdup(d, "Windows x64");
10170 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
10171 d->ex = true;
10173 return test_add_driver_arg(tctx, p, d);
10176 static bool test_add_driver_ex_32(struct torture_context *tctx,
10177 struct dcerpc_pipe *p)
10179 struct torture_driver_context *d;
10181 d = talloc_zero(tctx, struct torture_driver_context);
10183 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10184 d->info8.driver_name = TORTURE_DRIVER_EX;
10185 d->info8.architecture = NULL;
10186 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10187 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10188 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10189 d->local.environment = talloc_strdup(d, "Windows NT x86");
10190 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10191 d->ex = true;
10193 return test_add_driver_arg(tctx, p, d);
10196 static bool test_add_driver_64(struct torture_context *tctx,
10197 struct dcerpc_pipe *p)
10199 struct torture_driver_context *d;
10201 d = talloc_zero(tctx, struct torture_driver_context);
10203 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10204 d->info8.driver_name = TORTURE_DRIVER;
10205 d->info8.architecture = NULL;
10206 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10207 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10208 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10209 d->local.environment = talloc_strdup(d, "Windows x64");
10210 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
10211 d->ex = false;
10213 return test_add_driver_arg(tctx, p, d);
10216 static bool test_add_driver_32(struct torture_context *tctx,
10217 struct dcerpc_pipe *p)
10219 struct torture_driver_context *d;
10221 d = talloc_zero(tctx, struct torture_driver_context);
10223 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10224 d->info8.driver_name = TORTURE_DRIVER;
10225 d->info8.architecture = NULL;
10226 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10227 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10228 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10229 d->local.environment = talloc_strdup(d, "Windows NT x86");
10230 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10231 d->ex = false;
10233 return test_add_driver_arg(tctx, p, d);
10236 static bool test_add_driver_adobe(struct torture_context *tctx,
10237 struct dcerpc_pipe *p)
10239 struct torture_driver_context *d;
10241 if (!torture_setting_bool(tctx, "samba3", false)) {
10242 torture_skip(tctx, "skipping adobe test which only works against samba3");
10245 d = talloc_zero(tctx, struct torture_driver_context);
10247 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
10248 d->info8.driver_name = TORTURE_DRIVER_ADOBE;
10249 d->info8.architecture = NULL;
10250 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
10251 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
10252 d->info8.config_file = talloc_strdup(d, "ADOBEPS4.DRV");
10253 #if 0
10254 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
10255 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
10256 #endif
10257 d->local.environment = talloc_strdup(d, "Windows 4.0");
10258 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
10259 d->ex = false;
10261 return test_add_driver_arg(tctx, p, d);
10264 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
10265 struct dcerpc_pipe *p)
10267 struct torture_driver_context *d;
10268 struct spoolss_StringArray *a;
10270 if (!torture_setting_bool(tctx, "samba3", false)) {
10271 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
10274 d = talloc_zero(tctx, struct torture_driver_context);
10276 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
10277 d->info8.driver_name = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
10278 d->info8.architecture = NULL;
10279 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
10280 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
10281 d->info8.config_file = NULL;
10282 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
10283 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
10284 d->info8.default_datatype = talloc_strdup(d, "RAW");
10286 a = talloc_zero(d, struct spoolss_StringArray);
10287 a->string = talloc_zero_array(a, const char *, 7);
10288 a->string[0] = talloc_strdup(a->string, "ADOBEPS4.DRV");
10289 a->string[1] = talloc_strdup(a->string, "DEFPRTR2.PPD");
10290 a->string[2] = talloc_strdup(a->string, "ADOBEPS4.HLP");
10291 a->string[3] = talloc_strdup(a->string, "PSMON.DLL");
10292 a->string[4] = talloc_strdup(a->string, "ADFONTS.MFM");
10293 a->string[5] = talloc_strdup(a->string, "ICONLIB.DLL");
10295 d->info8.dependent_files = a;
10296 d->local.environment = talloc_strdup(d, "Windows 4.0");
10297 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
10298 d->ex = false;
10300 return test_add_driver_arg(tctx, p, d);
10303 static bool test_add_driver_timestamps(struct torture_context *tctx,
10304 struct dcerpc_pipe *p)
10306 struct torture_driver_context *d;
10307 struct timeval t = timeval_current();
10309 d = talloc_zero(tctx, struct torture_driver_context);
10311 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10312 d->info8.driver_name = TORTURE_DRIVER_TIMESTAMPS;
10313 d->info8.architecture = NULL;
10314 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10315 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10316 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10317 d->info8.driver_date = timeval_to_nttime(&t);
10318 d->local.environment = talloc_strdup(d, "Windows NT x86");
10319 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10320 d->ex = true;
10322 torture_assert(tctx,
10323 test_add_driver_arg(tctx, p, d),
10324 "");
10326 unix_to_nt_time(&d->info8.driver_date, 1);
10328 torture_assert(tctx,
10329 test_add_driver_arg(tctx, p, d),
10330 "");
10332 return true;
10335 static bool test_multiple_drivers(struct torture_context *tctx,
10336 struct dcerpc_pipe *p)
10338 struct torture_driver_context *d;
10339 struct dcerpc_binding_handle *b = p->binding_handle;
10340 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10341 int i;
10342 struct spoolss_AddDriverInfo8 info8;
10343 uint32_t add_flags = APD_COPY_NEW_FILES;
10344 uint32_t delete_flags = 0;
10346 d = talloc_zero(tctx, struct torture_driver_context);
10348 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10349 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10350 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10351 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10352 d->local.environment = talloc_strdup(d, "Windows NT x86");
10353 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10354 d->ex = true;
10356 torture_assert(tctx,
10357 fillup_printserver_info(tctx, p, d),
10358 "failed to fillup printserver info");
10360 if (!directory_exist(d->local.driver_directory)) {
10361 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10364 torture_assert(tctx,
10365 upload_printer_driver(tctx, dcerpc_server_name(p), d),
10366 "failed to upload printer driver");
10368 info8 = d->info8;
10369 info8.architecture = d->local.environment;
10371 for (i=0; i < 3; i++) {
10372 info8.driver_name = talloc_asprintf(d, "torture_test_driver_%d", i);
10374 torture_assert(tctx,
10375 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &info8, add_flags, true, NULL),
10376 "failed to add driver");
10379 torture_assert(tctx,
10380 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_0", info8.architecture, delete_flags, info8.version),
10381 "failed to delete driver");
10383 torture_assert(tctx,
10384 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_1", NULL),
10385 "torture_test_driver_1 no longer on the server");
10387 torture_assert(tctx,
10388 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
10389 "torture_test_driver_2 no longer on the server");
10391 torture_assert(tctx,
10392 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_1", info8.architecture, delete_flags, info8.version),
10393 "failed to delete driver");
10395 torture_assert(tctx,
10396 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
10397 "torture_test_driver_2 no longer on the server");
10399 torture_assert(tctx,
10400 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_2", info8.architecture, delete_flags, info8.version),
10401 "failed to delete driver");
10403 torture_assert(tctx,
10404 remove_printer_driver(tctx, dcerpc_server_name(p), d),
10405 "failed to remove printer driver");
10407 return true;
10410 static bool test_del_driver_all_files(struct torture_context *tctx,
10411 struct dcerpc_pipe *p)
10413 struct torture_driver_context *d;
10414 struct spoolss_StringArray *a;
10415 uint32_t add_flags = APD_COPY_NEW_FILES;
10416 uint32_t delete_flags = DPD_DELETE_ALL_FILES;
10417 struct dcerpc_binding_handle *b = p->binding_handle;
10418 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10420 d = talloc_zero(tctx, struct torture_driver_context);
10422 d->ex = true;
10423 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10424 d->info8.driver_name = TORTURE_DRIVER_DELETER;
10425 d->info8.architecture = NULL;
10426 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10427 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10428 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10429 d->info8.help_file = talloc_strdup(d, "pscript.hlp");
10430 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
10431 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
10433 a = talloc_zero(d, struct spoolss_StringArray);
10434 a->string = talloc_zero_array(a, const char *, 3);
10435 a->string[0] = talloc_strdup(a->string, "cups6.inf");
10436 a->string[1] = talloc_strdup(a->string, "cups6.ini");
10438 d->info8.dependent_files = a;
10439 d->info8.architecture = d->local.environment;
10441 torture_assert(tctx,
10442 fillup_printserver_info(tctx, p, d),
10443 "failed to fillup printserver info");
10445 if (!directory_exist(d->local.driver_directory)) {
10446 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10449 torture_assert(tctx,
10450 upload_printer_driver(tctx, dcerpc_server_name(p), d),
10451 "failed to upload printer driver");
10453 torture_assert(tctx,
10454 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d->info8, add_flags, true, NULL),
10455 "failed to add driver");
10457 torture_assert(tctx,
10458 test_DeletePrinterDriverEx(tctx, b, server_name_slash,
10459 d->info8.driver_name,
10460 d->local.environment,
10461 delete_flags,
10462 d->info8.version),
10463 "failed to delete driver");
10465 torture_assert(tctx,
10466 check_printer_driver_files(tctx, dcerpc_server_name(p), d, false),
10467 "printer driver file check failed");
10469 talloc_free(d);
10470 return true;
10473 static bool test_del_driver_unused_files(struct torture_context *tctx,
10474 struct dcerpc_pipe *p)
10476 struct torture_driver_context *d1;
10477 struct torture_driver_context *d2;
10478 uint32_t add_flags = APD_COPY_NEW_FILES;
10479 struct dcerpc_binding_handle *b = p->binding_handle;
10480 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10482 d1 = talloc_zero(tctx, struct torture_driver_context);
10483 d1->ex = true;
10484 d1->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10485 d1->info8.driver_name = TORTURE_DRIVER_DELETER;
10486 d1->info8.architecture = NULL;
10487 d1->info8.driver_path = talloc_strdup(d1, "pscript5.dll");
10488 d1->info8.data_file = talloc_strdup(d1, "cups6.ppd");
10489 d1->info8.config_file = talloc_strdup(d1, "cupsui6.dll");
10490 d1->info8.help_file = talloc_strdup(d1, "pscript.hlp");
10491 d1->local.environment = talloc_strdup(d1, SPOOLSS_ARCHITECTURE_x64);
10492 d1->local.driver_directory = talloc_strdup(d1, "/usr/share/cups/drivers/x64");
10493 d1->info8.architecture = d1->local.environment;
10495 d2 = talloc_zero(tctx, struct torture_driver_context);
10496 d2->ex = true;
10497 d2->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10498 d2->info8.driver_name = TORTURE_DRIVER_DELETERIN;
10499 d2->info8.architecture = NULL;
10500 d2->info8.driver_path = talloc_strdup(d2, "pscript5.dll"); /* overlapping */
10501 d2->info8.data_file = talloc_strdup(d2, "cupsps6.dll");
10502 d2->info8.config_file = talloc_strdup(d2, "cups6.ini");
10503 d2->info8.help_file = talloc_strdup(d2, "pscript.hlp"); /* overlapping */
10504 d2->local.environment = talloc_strdup(d2, SPOOLSS_ARCHITECTURE_x64);
10505 d2->local.driver_directory = talloc_strdup(d2, "/usr/share/cups/drivers/x64");
10506 d2->info8.architecture = d2->local.environment;
10508 torture_assert(tctx,
10509 fillup_printserver_info(tctx, p, d1),
10510 "failed to fillup printserver info");
10511 torture_assert(tctx,
10512 fillup_printserver_info(tctx, p, d2),
10513 "failed to fillup printserver info");
10515 if (!directory_exist(d1->local.driver_directory)) {
10516 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10519 torture_assert(tctx,
10520 upload_printer_driver(tctx, dcerpc_server_name(p), d1),
10521 "failed to upload printer driver");
10522 torture_assert(tctx,
10523 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d1->info8, add_flags, true, NULL),
10524 "failed to add driver");
10526 torture_assert(tctx,
10527 upload_printer_driver(tctx, dcerpc_server_name(p), d2),
10528 "failed to upload printer driver");
10529 torture_assert(tctx,
10530 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d2->info8, add_flags, true, NULL),
10531 "failed to add driver");
10533 /* some files are in use by a separate driver, should fail */
10534 torture_assert(tctx,
10535 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10536 d1->info8.driver_name,
10537 d1->local.environment,
10538 DPD_DELETE_ALL_FILES,
10539 d1->info8.version,
10540 WERR_PRINTER_DRIVER_IN_USE),
10541 "invalid delete driver response");
10543 /* should only delete files not in use by other driver */
10544 torture_assert(tctx,
10545 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10546 d1->info8.driver_name,
10547 d1->local.environment,
10548 DPD_DELETE_UNUSED_FILES,
10549 d1->info8.version,
10550 WERR_OK),
10551 "failed to delete driver (unused files)");
10553 /* check non-overlapping were deleted */
10554 d1->info8.driver_path = NULL;
10555 d1->info8.help_file = NULL;
10556 torture_assert(tctx,
10557 check_printer_driver_files(tctx, dcerpc_server_name(p), d1, false),
10558 "printer driver file check failed");
10559 /* d2 files should be uneffected */
10560 torture_assert(tctx,
10561 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, true),
10562 "printer driver file check failed");
10564 torture_assert(tctx,
10565 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10566 d2->info8.driver_name,
10567 d2->local.environment,
10568 DPD_DELETE_ALL_FILES,
10569 d2->info8.version,
10570 WERR_OK),
10571 "failed to delete driver");
10573 torture_assert(tctx,
10574 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, false),
10575 "printer driver file check failed");
10577 talloc_free(d1);
10578 talloc_free(d2);
10579 return true;
10582 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
10584 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
10586 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
10587 "driver", &ndr_table_spoolss);
10588 torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
10589 torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
10591 torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
10592 torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
10594 torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
10596 torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
10598 torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
10600 torture_rpc_tcase_add_test(tcase, "multiple_drivers", test_multiple_drivers);
10602 torture_rpc_tcase_add_test(tcase, "del_driver_all_files", test_del_driver_all_files);
10604 torture_rpc_tcase_add_test(tcase, "del_driver_unused_files", test_del_driver_unused_files);
10606 return suite;