s3:winbindd: also try to fallback to anonymous if we get NT_STATUS_INVALID_ACCOUNT_NAME
[Samba.git] / source4 / torture / rpc / spoolss.c
blob20e86fc16a733523fdf5ca490a6bba8e8fc93957
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 WERROR werr_expected,
3259 uint32_t *count_p,
3260 union spoolss_JobInfo **info_p)
3262 NTSTATUS status;
3263 struct spoolss_EnumJobs r;
3264 uint32_t needed;
3265 uint32_t count;
3266 union spoolss_JobInfo *info;
3268 r.in.handle = handle;
3269 r.in.firstjob = 0;
3270 r.in.numjobs = 0xffffffff;
3271 r.in.level = level;
3272 r.in.buffer = NULL;
3273 r.in.offered = 0;
3274 r.out.needed = &needed;
3275 r.out.count = &count;
3276 r.out.info = &info;
3278 torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3280 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3282 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3284 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3285 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3286 r.in.buffer = &blob;
3287 r.in.offered = needed;
3289 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3291 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3292 torture_assert_werr_equal(tctx, r.out.result, werr_expected,
3293 "EnumJobs failed");
3294 torture_assert(tctx, info, "No jobs returned");
3296 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3298 } else {
3299 torture_assert_werr_equal(tctx, r.out.result, werr_expected,
3300 "EnumJobs failed");
3303 if (count_p) {
3304 *count_p = count;
3306 if (info_p) {
3307 *info_p = info;
3310 return true;
3313 static bool test_JobPropertiesEnum(struct torture_context *tctx,
3314 struct dcerpc_binding_handle *b,
3315 struct policy_handle *handle,
3316 uint32_t job_id)
3318 struct spoolss_RpcEnumJobNamedProperties r;
3319 uint32_t pcProperties = 0;
3320 struct RPC_PrintNamedProperty *ppProperties = NULL;
3322 r.in.hPrinter = handle;
3323 r.in.JobId = job_id;
3324 r.out.pcProperties = &pcProperties;
3325 r.out.ppProperties = &ppProperties;
3327 torture_comment(tctx, "Testing RpcEnumJobNamedProperties(%d)\n", job_id);
3329 torture_assert_ntstatus_ok(tctx,
3330 dcerpc_spoolss_RpcEnumJobNamedProperties_r(b, tctx, &r),
3331 "spoolss_RpcEnumJobNamedProperties failed");
3332 torture_assert_werr_ok(tctx, r.out.result,
3333 "spoolss_RpcEnumJobNamedProperties failed");
3335 return true;
3338 static bool test_JobPropertySet(struct torture_context *tctx,
3339 struct dcerpc_binding_handle *b,
3340 struct policy_handle *handle,
3341 uint32_t job_id,
3342 struct RPC_PrintNamedProperty *property)
3344 struct spoolss_RpcSetJobNamedProperty r;
3346 r.in.hPrinter = handle;
3347 r.in.JobId = job_id;
3348 r.in.pProperty = property;
3350 torture_comment(tctx, "Testing RpcSetJobNamedProperty(%d) %s - %d\n",
3351 job_id, property->propertyName,
3352 property->propertyValue.ePropertyType);
3354 torture_assert_ntstatus_ok(tctx,
3355 dcerpc_spoolss_RpcSetJobNamedProperty_r(b, tctx, &r),
3356 "spoolss_RpcSetJobNamedProperty failed");
3357 torture_assert_werr_ok(tctx, r.out.result,
3358 "spoolss_RpcSetJobNamedProperty failed");
3360 return true;
3363 static bool test_JobPropertyGetValue(struct torture_context *tctx,
3364 struct dcerpc_binding_handle *b,
3365 struct policy_handle *handle,
3366 uint32_t job_id,
3367 const char *property_name,
3368 struct RPC_PrintPropertyValue *value)
3370 struct spoolss_RpcGetJobNamedPropertyValue r;
3372 r.in.hPrinter = handle;
3373 r.in.JobId = job_id;
3374 r.in.pszName = property_name;
3375 r.out.pValue = value;
3377 torture_comment(tctx, "Testing RpcGetJobNamedPropertyValue(%d) %s\n",
3378 job_id, property_name);
3380 torture_assert_ntstatus_ok(tctx,
3381 dcerpc_spoolss_RpcGetJobNamedPropertyValue_r(b, tctx, &r),
3382 "spoolss_RpcGetJobNamedPropertyValue failed");
3383 torture_assert_werr_ok(tctx, r.out.result,
3384 "spoolss_RpcGetJobNamedPropertyValue failed");
3386 return true;
3389 static bool test_JobPropertyDelete(struct torture_context *tctx,
3390 struct dcerpc_binding_handle *b,
3391 struct policy_handle *handle,
3392 uint32_t job_id,
3393 const char *property_name)
3395 struct spoolss_RpcDeleteJobNamedProperty r;
3397 r.in.hPrinter = handle;
3398 r.in.JobId = job_id;
3399 r.in.pszName = property_name;
3401 torture_comment(tctx, "Testing RpcDeleteJobNamedProperty(%d) %s\n",
3402 job_id, property_name);
3404 torture_assert_ntstatus_ok(tctx,
3405 dcerpc_spoolss_RpcDeleteJobNamedProperty_r(b, tctx, &r),
3406 "spoolss_RpcDeleteJobNamedProperty failed");
3407 torture_assert_werr_ok(tctx, r.out.result,
3408 "spoolss_RpcDeleteJobNamedProperty failed");
3410 return true;
3413 static bool test_DoPrintTest_add_one_job_common(struct torture_context *tctx,
3414 struct dcerpc_binding_handle *b,
3415 struct policy_handle *handle,
3416 const char *document_name,
3417 const char *datatype,
3418 uint32_t *job_id)
3420 NTSTATUS status;
3421 struct spoolss_StartDocPrinter s;
3422 struct spoolss_DocumentInfoCtr info_ctr;
3423 struct spoolss_DocumentInfo1 info1;
3424 struct spoolss_StartPagePrinter sp;
3425 struct spoolss_WritePrinter w;
3426 struct spoolss_EndPagePrinter ep;
3427 struct spoolss_EndDocPrinter e;
3428 int i;
3429 uint32_t num_written;
3431 torture_comment(tctx, "Testing StartDocPrinter\n");
3433 s.in.handle = handle;
3434 s.in.info_ctr = &info_ctr;
3435 s.out.job_id = job_id;
3437 info1.document_name = document_name;
3438 info1.output_file = NULL;
3439 info1.datatype = datatype;
3441 info_ctr.level = 1;
3442 info_ctr.info.info1 = &info1;
3444 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3445 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3446 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3448 for (i=1; i < 4; i++) {
3449 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3451 sp.in.handle = handle;
3453 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3454 torture_assert_ntstatus_ok(tctx, status,
3455 "dcerpc_spoolss_StartPagePrinter failed");
3456 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3458 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3460 w.in.handle = handle;
3461 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3462 w.out.num_written = &num_written;
3464 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3465 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3466 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3468 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3470 ep.in.handle = handle;
3472 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3473 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3474 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3477 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3479 e.in.handle = handle;
3481 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3482 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3483 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3485 return true;
3488 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3489 struct dcerpc_binding_handle *b,
3490 struct policy_handle *handle,
3491 const char *document_name,
3492 uint32_t *job_id)
3494 test_DoPrintTest_add_one_job_common(tctx, b, handle, document_name, "RAW", job_id);
3496 return true;
3499 static bool test_DoPrintTest_add_one_job_v4(struct torture_context *tctx,
3500 struct dcerpc_binding_handle *b,
3501 struct policy_handle *handle,
3502 const char *document_name,
3503 uint32_t *job_id)
3505 test_DoPrintTest_add_one_job_common(tctx, b, handle, document_name, "XPS_PASS", job_id);
3507 return true;
3511 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3512 struct dcerpc_binding_handle *b,
3513 struct policy_handle *handle,
3514 uint32_t num_jobs,
3515 uint32_t *job_ids)
3517 uint32_t count;
3518 union spoolss_JobInfo *info = NULL;
3519 int i;
3521 torture_assert(tctx,
3522 test_AddJob(tctx, b, handle),
3523 "AddJob failed");
3525 torture_assert(tctx,
3526 test_EnumJobs_args(tctx, b, handle, 1, WERR_OK, &count, &info),
3527 "EnumJobs level 1 failed");
3529 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3531 for (i=0; i < num_jobs; i++) {
3532 union spoolss_JobInfo ginfo;
3533 const char *document_name;
3534 const char *new_document_name = "any_other_docname";
3535 struct spoolss_JobInfoContainer ctr;
3536 struct spoolss_SetJobInfo1 info1;
3538 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3540 torture_assert(tctx,
3541 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3542 "failed to call test_GetJob");
3544 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3546 document_name = ginfo.info1.document_name;
3548 info1.job_id = ginfo.info1.job_id;
3549 info1.printer_name = ginfo.info1.printer_name;
3550 info1.server_name = ginfo.info1.server_name;
3551 info1.user_name = ginfo.info1.user_name;
3552 info1.document_name = new_document_name;
3553 info1.data_type = ginfo.info1.data_type;
3554 info1.text_status = ginfo.info1.text_status;
3555 info1.status = ginfo.info1.status;
3556 info1.priority = ginfo.info1.priority;
3557 info1.position = ginfo.info1.position;
3558 info1.total_pages = ginfo.info1.total_pages;
3559 info1.pages_printed = ginfo.info1.pages_printed;
3560 info1.submitted = ginfo.info1.submitted;
3562 ctr.level = 1;
3563 ctr.info.info1 = &info1;
3565 torture_assert(tctx,
3566 test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3567 "failed to call test_SetJob level 1");
3569 torture_assert(tctx,
3570 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3571 "failed to call test_GetJob");
3573 if (strequal(ginfo.info1.document_name, document_name)) {
3574 torture_warning(tctx,
3575 "document_name did *NOT* change from '%s' to '%s'\n",
3576 document_name, new_document_name);
3580 for (i=0; i < num_jobs; i++) {
3581 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3582 torture_warning(tctx, "failed to pause printjob\n");
3584 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3585 torture_warning(tctx, "failed to resume printjob\n");
3589 return true;
3592 static bool test_DoPrintTest(struct torture_context *tctx,
3593 struct dcerpc_binding_handle *b,
3594 struct policy_handle *handle)
3596 bool ret = true;
3597 uint32_t num_jobs = 8;
3598 uint32_t *job_ids;
3599 int i;
3601 torture_comment(tctx, "Testing real print operations\n");
3603 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3605 for (i=0; i < num_jobs; i++) {
3606 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3609 for (i=0; i < num_jobs; i++) {
3610 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3613 for (i=0; i < num_jobs; i++) {
3614 ret &= test_DoPrintTest_add_one_job_v4(tctx, b, handle, "TorturePrintJob v4", &job_ids[i]);
3617 for (i=0; i < num_jobs; i++) {
3618 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3621 if (ret == true) {
3622 torture_comment(tctx, "real print operations test succeeded\n\n");
3625 return ret;
3628 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3629 struct dcerpc_binding_handle *b,
3630 struct policy_handle *handle)
3632 bool ret = true;
3633 uint32_t num_jobs = 8;
3634 uint32_t *job_ids;
3635 int i;
3636 torture_comment(tctx, "Testing real print operations (extended)\n");
3638 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3640 for (i=0; i < num_jobs; i++) {
3641 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3644 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3646 for (i=0; i < num_jobs; i++) {
3647 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3650 if (ret == true) {
3651 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3654 return ret;
3657 static bool test_JobPrintProperties_equal(struct torture_context *tctx,
3658 struct RPC_PrintPropertyValue *got,
3659 struct RPC_PrintNamedProperty *exp)
3661 torture_assert_int_equal(tctx,
3662 got->ePropertyType,
3663 exp->propertyValue.ePropertyType,
3664 "ePropertyType");
3666 switch (exp->propertyValue.ePropertyType) {
3667 case kRpcPropertyTypeString:
3668 torture_assert_str_equal(tctx,
3669 got->value.propertyString,
3670 exp->propertyValue.value.propertyString,
3671 "propertyString");
3672 break;
3673 case kRpcPropertyTypeInt32:
3674 torture_assert_int_equal(tctx,
3675 got->value.propertyInt32,
3676 exp->propertyValue.value.propertyInt32,
3677 "propertyInt32");
3678 break;
3679 case kRpcPropertyTypeInt64:
3680 torture_assert_u64_equal(tctx,
3681 got->value.propertyInt64,
3682 exp->propertyValue.value.propertyInt64,
3683 "propertyInt64");
3684 break;
3685 case kRpcPropertyTypeByte:
3686 torture_assert_int_equal(tctx,
3687 got->value.propertyByte,
3688 exp->propertyValue.value.propertyByte,
3689 "propertyByte");
3690 break;
3691 case kRpcPropertyTypeBuffer:
3692 torture_assert_int_equal(tctx,
3693 got->value.propertyBlob.cbBuf,
3694 exp->propertyValue.value.propertyBlob.cbBuf,
3695 "propertyBlob.cbBuf");
3696 torture_assert_mem_equal(tctx,
3697 got->value.propertyBlob.pBuf,
3698 exp->propertyValue.value.propertyBlob.pBuf,
3699 exp->propertyValue.value.propertyBlob.cbBuf,
3700 "propertyBlob.pBuf");
3702 break;
3706 return true;
3709 static bool test_JobPrintProperties(struct torture_context *tctx,
3710 struct dcerpc_binding_handle *b,
3711 struct policy_handle *handle,
3712 uint32_t job_id)
3714 struct RPC_PrintNamedProperty in;
3715 struct RPC_PrintPropertyValue out;
3716 int i;
3717 DATA_BLOB blob = data_blob_string_const("blob");
3718 struct {
3719 const char *property_name;
3720 enum RPC_EPrintPropertyType type;
3721 union RPC_PrintPropertyValueUnion value;
3722 WERROR expected_result;
3723 } tests[] = {
3725 .property_name = "torture_property_string",
3726 .type = kRpcPropertyTypeString,
3727 .value.propertyString = "torture_property_value_string",
3729 .property_name = "torture_property_int32",
3730 .type = kRpcPropertyTypeInt32,
3731 .value.propertyInt32 = 42,
3733 .property_name = "torture_property_int64",
3734 .type = kRpcPropertyTypeInt64,
3735 .value.propertyInt64 = 0xaffe,
3737 .property_name = "torture_property_byte",
3738 .type = kRpcPropertyTypeByte,
3739 .value.propertyByte = 0xab,
3741 .property_name = "torture_property_buffer",
3742 .type = kRpcPropertyTypeBuffer,
3743 .value.propertyBlob.cbBuf = blob.length,
3744 .value.propertyBlob.pBuf = blob.data,
3748 torture_assert(tctx,
3749 test_JobPropertiesEnum(tctx, b, handle, job_id),
3750 "failed to enum properties");
3752 for (i=0; i <ARRAY_SIZE(tests); i++) {
3754 in.propertyName = tests[i].property_name;
3755 in.propertyValue.ePropertyType = tests[i].type;
3756 in.propertyValue.value = tests[i].value;
3758 torture_assert(tctx,
3759 test_JobPropertySet(tctx, b, handle, job_id, &in),
3760 "failed to set property");
3762 torture_assert(tctx,
3763 test_JobPropertyGetValue(tctx, b, handle, job_id, in.propertyName, &out),
3764 "failed to get property");
3766 torture_assert(tctx,
3767 test_JobPrintProperties_equal(tctx, &out, &in),
3768 "property unequal");
3770 torture_assert(tctx,
3771 test_JobPropertiesEnum(tctx, b, handle, job_id),
3772 "failed to enum properties");
3774 torture_assert(tctx,
3775 test_JobPropertyDelete(tctx, b, handle, job_id, in.propertyName),
3776 "failed to delete job property");
3779 torture_assert(tctx,
3780 test_JobPropertiesEnum(tctx, b, handle, job_id),
3781 "failed to enum properties");
3783 return true;
3786 static bool test_DoPrintTest_properties(struct torture_context *tctx,
3787 struct dcerpc_binding_handle *b,
3788 struct policy_handle *handle)
3790 uint32_t num_jobs = 8;
3791 uint32_t *job_ids;
3792 int i;
3793 torture_comment(tctx, "Testing real print operations (properties)\n");
3795 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3797 for (i=0; i < num_jobs; i++) {
3798 torture_assert(tctx,
3799 test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]),
3800 "failed to create print job");
3803 for (i=0; i < num_jobs; i++) {
3804 torture_assert(tctx,
3805 test_JobPrintProperties(tctx, b, handle, job_ids[i]),
3806 "failed to test job properties");
3810 for (i=0; i < num_jobs; i++) {
3811 torture_assert(tctx,
3812 test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE),
3813 "failed to delete printjob");
3816 torture_comment(tctx, "real print operations (properties) test succeeded\n\n");
3818 return true;
3821 static bool test_PausePrinter(struct torture_context *tctx,
3822 struct dcerpc_binding_handle *b,
3823 struct policy_handle *handle)
3825 NTSTATUS status;
3826 struct spoolss_SetPrinter r;
3827 struct spoolss_SetPrinterInfoCtr info_ctr;
3828 struct spoolss_DevmodeContainer devmode_ctr;
3829 struct sec_desc_buf secdesc_ctr;
3831 info_ctr.level = 0;
3832 info_ctr.info.info0 = NULL;
3834 ZERO_STRUCT(devmode_ctr);
3835 ZERO_STRUCT(secdesc_ctr);
3837 r.in.handle = handle;
3838 r.in.info_ctr = &info_ctr;
3839 r.in.devmode_ctr = &devmode_ctr;
3840 r.in.secdesc_ctr = &secdesc_ctr;
3841 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3843 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3845 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3847 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3849 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3851 return true;
3854 static bool test_ResumePrinter(struct torture_context *tctx,
3855 struct dcerpc_binding_handle *b,
3856 struct policy_handle *handle)
3858 NTSTATUS status;
3859 struct spoolss_SetPrinter r;
3860 struct spoolss_SetPrinterInfoCtr info_ctr;
3861 struct spoolss_DevmodeContainer devmode_ctr;
3862 struct sec_desc_buf secdesc_ctr;
3864 info_ctr.level = 0;
3865 info_ctr.info.info0 = NULL;
3867 ZERO_STRUCT(devmode_ctr);
3868 ZERO_STRUCT(secdesc_ctr);
3870 r.in.handle = handle;
3871 r.in.info_ctr = &info_ctr;
3872 r.in.devmode_ctr = &devmode_ctr;
3873 r.in.secdesc_ctr = &secdesc_ctr;
3874 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3876 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3878 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3880 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3882 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3884 return true;
3887 static bool test_printer_purge(struct torture_context *tctx,
3888 struct dcerpc_binding_handle *b,
3889 struct policy_handle *handle)
3891 NTSTATUS status;
3892 struct spoolss_SetPrinter r;
3893 struct spoolss_SetPrinterInfoCtr info_ctr;
3894 struct spoolss_DevmodeContainer devmode_ctr;
3895 struct sec_desc_buf secdesc_ctr;
3897 info_ctr.level = 0;
3898 info_ctr.info.info0 = NULL;
3900 ZERO_STRUCT(devmode_ctr);
3901 ZERO_STRUCT(secdesc_ctr);
3903 r.in.handle = handle;
3904 r.in.info_ctr = &info_ctr;
3905 r.in.devmode_ctr = &devmode_ctr;
3906 r.in.secdesc_ctr = &secdesc_ctr;
3907 r.in.command = SPOOLSS_PRINTER_CONTROL_PURGE;
3909 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PURGE\n");
3911 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3912 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3913 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3915 return true;
3918 static bool test_GetPrinterData_checktype(struct torture_context *tctx,
3919 struct dcerpc_binding_handle *b,
3920 struct policy_handle *handle,
3921 const char *value_name,
3922 enum winreg_Type *expected_type,
3923 enum winreg_Type *type_p,
3924 uint8_t **data_p,
3925 uint32_t *needed_p)
3927 NTSTATUS status;
3928 struct spoolss_GetPrinterData r;
3929 uint32_t needed;
3930 enum winreg_Type type;
3931 union spoolss_PrinterData data;
3933 r.in.handle = handle;
3934 r.in.value_name = value_name;
3935 r.in.offered = 0;
3936 r.out.needed = &needed;
3937 r.out.type = &type;
3938 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3940 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3942 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3943 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3945 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3946 if (expected_type) {
3947 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3949 r.in.offered = needed;
3950 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3951 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3952 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3955 torture_assert_werr_ok(tctx, r.out.result,
3956 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3958 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3960 if (type_p) {
3961 *type_p = type;
3964 if (data_p) {
3965 *data_p = r.out.data;
3968 if (needed_p) {
3969 *needed_p = needed;
3972 return true;
3975 static bool test_GetPrinterData(struct torture_context *tctx,
3976 struct dcerpc_binding_handle *b,
3977 struct policy_handle *handle,
3978 const char *value_name,
3979 enum winreg_Type *type_p,
3980 uint8_t **data_p,
3981 uint32_t *needed_p)
3983 return test_GetPrinterData_checktype(tctx, b, handle, value_name,
3984 NULL, type_p, data_p, needed_p);
3987 static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
3988 struct dcerpc_pipe *p,
3989 struct policy_handle *handle,
3990 const char *key_name,
3991 const char *value_name,
3992 enum winreg_Type *expected_type,
3993 enum winreg_Type *type_p,
3994 uint8_t **data_p,
3995 uint32_t *needed_p)
3997 NTSTATUS status;
3998 struct spoolss_GetPrinterDataEx r;
3999 enum winreg_Type type;
4000 uint32_t needed;
4001 union spoolss_PrinterData data;
4002 struct dcerpc_binding_handle *b = p->binding_handle;
4004 r.in.handle = handle;
4005 r.in.key_name = key_name;
4006 r.in.value_name = value_name;
4007 r.in.offered = 0;
4008 r.out.type = &type;
4009 r.out.needed = &needed;
4010 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
4012 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
4013 r.in.key_name, r.in.value_name);
4015 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
4016 if (!NT_STATUS_IS_OK(status)) {
4017 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
4018 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
4020 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
4023 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4024 if (expected_type) {
4025 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
4027 r.in.offered = needed;
4028 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
4029 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
4030 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
4033 torture_assert_werr_ok(tctx, r.out.result,
4034 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
4036 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
4038 if (type_p) {
4039 *type_p = type;
4042 if (data_p) {
4043 *data_p = r.out.data;
4046 if (needed_p) {
4047 *needed_p = needed;
4050 return true;
4053 static bool test_GetPrinterDataEx(struct torture_context *tctx,
4054 struct dcerpc_pipe *p,
4055 struct policy_handle *handle,
4056 const char *key_name,
4057 const char *value_name,
4058 enum winreg_Type *type_p,
4059 uint8_t **data_p,
4060 uint32_t *needed_p)
4062 return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
4063 NULL, type_p, data_p, needed_p);
4066 static bool test_get_environment(struct torture_context *tctx,
4067 struct dcerpc_binding_handle *b,
4068 struct policy_handle *handle,
4069 const char **architecture)
4071 DATA_BLOB blob;
4072 enum winreg_Type type;
4073 uint8_t *data;
4074 uint32_t needed;
4076 torture_assert(tctx,
4077 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
4078 "failed to get Architecture");
4080 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
4082 blob = data_blob_const(data, needed);
4083 *architecture = reg_val_data_string(tctx, REG_SZ, blob);
4085 return true;
4088 static bool test_GetPrinterData_list(struct torture_context *tctx,
4089 void *private_data)
4091 struct test_spoolss_context *ctx =
4092 talloc_get_type_abort(private_data, struct test_spoolss_context);
4093 struct dcerpc_pipe *p = ctx->spoolss_pipe;
4094 struct dcerpc_binding_handle *b = p->binding_handle;
4095 const char *list[] = {
4096 "W3SvcInstalled",
4097 "BeepEnabled",
4098 "EventLog",
4099 /* "NetPopup", not on w2k8 */
4100 /* "NetPopupToComputer", not on w2k8 */
4101 "MajorVersion",
4102 "MinorVersion",
4103 "DefaultSpoolDirectory",
4104 "Architecture",
4105 "DsPresent",
4106 "OSVersion",
4107 /* "OSVersionEx", not on s3 */
4108 "DNSMachineName"
4110 int i;
4112 for (i=0; i < ARRAY_SIZE(list); i++) {
4113 enum winreg_Type type, type_ex;
4114 uint8_t *data, *data_ex;
4115 uint32_t needed, needed_ex;
4117 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
4118 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
4119 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
4120 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
4121 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
4122 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
4123 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
4126 return true;
4129 static bool test_EnumPrinterData(struct torture_context *tctx,
4130 struct dcerpc_pipe *p,
4131 struct policy_handle *handle,
4132 uint32_t enum_index,
4133 uint32_t value_offered,
4134 uint32_t data_offered,
4135 enum winreg_Type *type_p,
4136 uint32_t *value_needed_p,
4137 uint32_t *data_needed_p,
4138 const char **value_name_p,
4139 uint8_t **data_p,
4140 WERROR *result_p)
4142 struct spoolss_EnumPrinterData r;
4143 uint32_t data_needed;
4144 uint32_t value_needed;
4145 enum winreg_Type type;
4146 struct dcerpc_binding_handle *b = p->binding_handle;
4148 r.in.handle = handle;
4149 r.in.enum_index = enum_index;
4150 r.in.value_offered = value_offered;
4151 r.in.data_offered = data_offered;
4152 r.out.data_needed = &data_needed;
4153 r.out.value_needed = &value_needed;
4154 r.out.type = &type;
4155 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
4156 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
4158 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
4160 torture_assert_ntstatus_ok(tctx,
4161 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
4162 "EnumPrinterData failed");
4164 if (type_p) {
4165 *type_p = type;
4167 if (value_needed_p) {
4168 *value_needed_p = value_needed;
4170 if (data_needed_p) {
4171 *data_needed_p = data_needed;
4173 if (value_name_p) {
4174 *value_name_p = r.out.value_name;
4176 if (data_p) {
4177 *data_p = r.out.data;
4179 if (result_p) {
4180 *result_p = r.out.result;
4183 return true;
4187 static bool test_EnumPrinterData_all(struct torture_context *tctx,
4188 struct dcerpc_pipe *p,
4189 struct policy_handle *handle)
4191 uint32_t enum_index = 0;
4192 enum winreg_Type type;
4193 uint32_t value_needed;
4194 uint32_t data_needed;
4195 uint8_t *data;
4196 const char *value_name;
4197 WERROR result;
4199 torture_comment(tctx, "Testing EnumPrinterData\n");
4201 do {
4202 torture_assert(tctx,
4203 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
4204 &type, &value_needed, &data_needed,
4205 &value_name, &data, &result),
4206 "EnumPrinterData failed");
4208 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
4209 break;
4212 torture_assert(tctx,
4213 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
4214 &type, &value_needed, &data_needed,
4215 &value_name, &data, &result),
4216 "EnumPrinterData failed");
4218 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
4219 break;
4222 enum_index++;
4224 } while (W_ERROR_IS_OK(result));
4226 torture_comment(tctx, "EnumPrinterData test succeeded\n");
4228 return true;
4231 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
4232 struct dcerpc_binding_handle *b,
4233 struct policy_handle *handle,
4234 const char *key_name,
4235 uint32_t *count_p,
4236 struct spoolss_PrinterEnumValues **info_p)
4238 struct spoolss_EnumPrinterDataEx r;
4239 struct spoolss_PrinterEnumValues *info;
4240 uint32_t needed;
4241 uint32_t count;
4243 r.in.handle = handle;
4244 r.in.key_name = key_name;
4245 r.in.offered = 0;
4246 r.out.needed = &needed;
4247 r.out.count = &count;
4248 r.out.info = &info;
4250 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
4252 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
4253 "EnumPrinterDataEx failed");
4254 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4255 r.in.offered = needed;
4256 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
4257 "EnumPrinterDataEx failed");
4260 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
4262 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
4264 if (count_p) {
4265 *count_p = count;
4267 if (info_p) {
4268 *info_p = info;
4271 return true;
4274 static bool test_SetPrinterData(struct torture_context *tctx,
4275 struct dcerpc_binding_handle *b,
4276 struct policy_handle *handle,
4277 const char *value_name,
4278 enum winreg_Type type,
4279 uint8_t *data,
4280 uint32_t offered);
4281 static bool test_DeletePrinterData(struct torture_context *tctx,
4282 struct dcerpc_binding_handle *b,
4283 struct policy_handle *handle,
4284 const char *value_name);
4286 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
4287 struct dcerpc_pipe *p,
4288 struct policy_handle *handle)
4290 uint32_t count;
4291 struct spoolss_PrinterEnumValues *info;
4292 int i;
4293 uint32_t value_needed, data_needed;
4294 uint32_t value_offered, data_offered;
4295 WERROR result;
4296 struct dcerpc_binding_handle *b = p->binding_handle;
4298 enum winreg_Type type;
4299 DATA_BLOB blob;
4301 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
4303 torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
4304 type = REG_SZ;
4306 torture_assert(tctx,
4307 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
4308 "SetPrinterData failed");
4310 blob = data_blob_string_const("torture_data2");
4312 torture_assert(tctx,
4313 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
4314 "SetPrinterData failed");
4316 blob = data_blob_talloc(tctx, NULL, 4);
4317 SIVAL(blob.data, 0, 0x11223344);
4319 torture_assert(tctx,
4320 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
4321 "SetPrinterData failed");
4323 torture_assert(tctx,
4324 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
4325 "failed to call EnumPrinterDataEx");
4327 /* get the max sizes for value and data */
4329 torture_assert(tctx,
4330 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
4331 NULL, &value_needed, &data_needed,
4332 NULL, NULL, &result),
4333 "EnumPrinterData failed");
4334 torture_assert_werr_ok(tctx, result, "unexpected result");
4336 /* check if the reply from the EnumPrinterData really matches max values */
4338 for (i=0; i < count; i++) {
4339 if (info[i].value_name_len > value_needed) {
4340 torture_fail(tctx,
4341 talloc_asprintf(tctx,
4342 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
4343 info[i].value_name_len, value_needed));
4345 if (info[i].data_length > data_needed) {
4346 torture_fail(tctx,
4347 talloc_asprintf(tctx,
4348 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
4349 info[i].data_length, data_needed));
4353 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
4354 * sort or not sort the replies by value name, we should be able to do
4355 * the following entry comparison */
4357 data_offered = data_needed;
4358 value_offered = value_needed;
4360 for (i=0; i < count; i++) {
4362 const char *value_name;
4363 uint8_t *data;
4365 torture_assert(tctx,
4366 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
4367 &type, &value_needed, &data_needed,
4368 &value_name, &data, &result),
4369 "EnumPrinterData failed");
4371 if (i -1 == count) {
4372 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
4373 "unexpected result");
4374 break;
4375 } else {
4376 torture_assert_werr_ok(tctx, result, "unexpected result");
4379 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
4380 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
4381 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
4382 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
4383 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
4386 torture_assert(tctx,
4387 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
4388 "DeletePrinterData failed");
4389 torture_assert(tctx,
4390 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
4391 "DeletePrinterData failed");
4392 torture_assert(tctx,
4393 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
4394 "DeletePrinterData failed");
4396 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4398 return true;
4401 static bool test_DeletePrinterData(struct torture_context *tctx,
4402 struct dcerpc_binding_handle *b,
4403 struct policy_handle *handle,
4404 const char *value_name)
4406 NTSTATUS status;
4407 struct spoolss_DeletePrinterData r;
4409 r.in.handle = handle;
4410 r.in.value_name = value_name;
4412 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
4413 r.in.value_name);
4415 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
4417 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
4418 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
4420 return true;
4423 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
4424 struct dcerpc_binding_handle *b,
4425 struct policy_handle *handle,
4426 const char *key_name,
4427 const char *value_name)
4429 struct spoolss_DeletePrinterDataEx r;
4431 r.in.handle = handle;
4432 r.in.key_name = key_name;
4433 r.in.value_name = value_name;
4435 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
4436 r.in.key_name, r.in.value_name);
4438 torture_assert_ntstatus_ok(tctx,
4439 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
4440 "DeletePrinterDataEx failed");
4441 torture_assert_werr_ok(tctx, r.out.result,
4442 "DeletePrinterDataEx failed");
4444 return true;
4447 static bool test_DeletePrinterKey(struct torture_context *tctx,
4448 struct dcerpc_binding_handle *b,
4449 struct policy_handle *handle,
4450 const char *key_name)
4452 struct spoolss_DeletePrinterKey r;
4454 r.in.handle = handle;
4455 r.in.key_name = key_name;
4457 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
4459 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
4460 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
4461 return true;
4464 torture_assert_ntstatus_ok(tctx,
4465 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
4466 "DeletePrinterKey failed");
4467 torture_assert_werr_ok(tctx, r.out.result,
4468 "DeletePrinterKey failed");
4470 return true;
4473 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4474 struct dcerpc_binding_handle *b,
4475 struct policy_handle *handle)
4477 struct winreg_OpenHKLM r;
4479 r.in.system_name = NULL;
4480 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4481 r.out.handle = handle;
4483 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4485 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4486 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4488 return true;
4491 static void init_winreg_String(struct winreg_String *name, const char *s)
4493 name->name = s;
4494 if (s) {
4495 name->name_len = 2 * (strlen_m(s) + 1);
4496 name->name_size = name->name_len;
4497 } else {
4498 name->name_len = 0;
4499 name->name_size = 0;
4503 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4504 struct dcerpc_binding_handle *b,
4505 struct policy_handle *hive_handle,
4506 const char *keyname,
4507 uint32_t options,
4508 struct policy_handle *key_handle)
4510 struct winreg_OpenKey r;
4512 r.in.parent_handle = hive_handle;
4513 init_winreg_String(&r.in.keyname, keyname);
4514 r.in.options = options;
4515 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4516 r.out.handle = key_handle;
4518 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4520 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4521 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4523 return true;
4526 static bool test_winreg_OpenKey(struct torture_context *tctx,
4527 struct dcerpc_binding_handle *b,
4528 struct policy_handle *hive_handle,
4529 const char *keyname,
4530 struct policy_handle *key_handle)
4532 return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4533 REG_OPTION_NON_VOLATILE, key_handle);
4536 static bool test_winreg_CloseKey(struct torture_context *tctx,
4537 struct dcerpc_binding_handle *b,
4538 struct policy_handle *handle)
4540 struct winreg_CloseKey r;
4542 r.in.handle = handle;
4543 r.out.handle = handle;
4545 torture_comment(tctx, "Testing winreg_CloseKey\n");
4547 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4548 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4550 return true;
4553 bool test_winreg_QueryValue(struct torture_context *tctx,
4554 struct dcerpc_binding_handle *b,
4555 struct policy_handle *handle,
4556 const char *value_name,
4557 enum winreg_Type *type_p,
4558 uint32_t *data_size_p,
4559 uint32_t *data_length_p,
4560 uint8_t **data_p)
4562 struct winreg_QueryValue r;
4563 enum winreg_Type type = REG_NONE;
4564 uint32_t data_size = 0;
4565 uint32_t data_length = 0;
4566 struct winreg_String valuename;
4567 uint8_t *data = NULL;
4569 init_winreg_String(&valuename, value_name);
4571 data = talloc_zero_array(tctx, uint8_t, 0);
4573 r.in.handle = handle;
4574 r.in.value_name = &valuename;
4575 r.in.type = &type;
4576 r.in.data_size = &data_size;
4577 r.in.data_length = &data_length;
4578 r.in.data = data;
4579 r.out.type = &type;
4580 r.out.data = data;
4581 r.out.data_size = &data_size;
4582 r.out.data_length = &data_length;
4584 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4586 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4587 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4588 *r.in.data_size = *r.out.data_size;
4589 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4590 r.in.data = data;
4591 r.out.data = data;
4592 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4594 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4596 if (type_p) {
4597 *type_p = *r.out.type;
4599 if (data_size_p) {
4600 *data_size_p = *r.out.data_size;
4602 if (data_length_p) {
4603 *data_length_p = *r.out.data_length;
4605 if (data_p) {
4606 *data_p = r.out.data;
4609 return true;
4612 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4613 struct dcerpc_binding_handle *b,
4614 struct policy_handle *handle,
4615 const char *printer_name,
4616 const char *key_name,
4617 const char *value_name,
4618 enum winreg_Type *w_type,
4619 uint32_t *w_size,
4620 uint32_t *w_length,
4621 uint8_t **w_data)
4623 const char *printer_key;
4624 struct policy_handle key_handle;
4626 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4627 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4629 torture_assert(tctx,
4630 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4632 torture_assert(tctx,
4633 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4635 torture_assert(tctx,
4636 test_winreg_CloseKey(tctx, b, &key_handle), "");
4638 return true;
4641 static bool test_GetForm_winreg(struct torture_context *tctx,
4642 struct dcerpc_binding_handle *b,
4643 struct policy_handle *handle,
4644 const char *key_name,
4645 const char *form_name,
4646 enum winreg_Type *w_type,
4647 uint32_t *w_size,
4648 uint32_t *w_length,
4649 uint8_t **w_data)
4651 struct policy_handle key_handle;
4653 torture_assert(tctx,
4654 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4656 torture_assert(tctx,
4657 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4659 torture_assert(tctx,
4660 test_winreg_CloseKey(tctx, b, &key_handle), "");
4662 return true;
4665 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4666 struct dcerpc_binding_handle *b,
4667 struct policy_handle *handle,
4668 const char *symlink_keyname,
4669 const char *symlink_destination)
4671 /* check if the first key is a symlink to the second key */
4673 enum winreg_Type w_type;
4674 uint32_t w_size;
4675 uint32_t w_length;
4676 uint8_t *w_data;
4677 struct policy_handle key_handle;
4678 DATA_BLOB blob;
4679 const char *str;
4681 if (torture_setting_bool(tctx, "samba3", false)) {
4682 torture_skip(tctx, "skip winreg symlink test against samba");
4685 torture_assert(tctx,
4686 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4687 "failed to open key link");
4689 torture_assert(tctx,
4690 test_winreg_QueryValue(tctx, b, &key_handle,
4691 "SymbolicLinkValue",
4692 &w_type, &w_size, &w_length, &w_data),
4693 "failed to query for 'SymbolicLinkValue' attribute");
4695 torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4697 blob = data_blob(w_data, w_size);
4698 str = reg_val_data_string(tctx, REG_SZ, blob);
4700 torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4702 torture_assert(tctx,
4703 test_winreg_CloseKey(tctx, b, &key_handle),
4704 "failed to close key link");
4706 return true;
4709 static const char *strip_unc(const char *unc)
4711 char *name;
4713 if (!unc) {
4714 return NULL;
4717 if (unc[0] == '\\' && unc[1] == '\\') {
4718 unc +=2;
4721 name = strchr(unc, '\\');
4722 if (name) {
4723 return name+1;
4726 return unc;
4729 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4730 struct dcerpc_binding_handle *b,
4731 struct policy_handle *handle,
4732 const char *printer_name,
4733 struct dcerpc_binding_handle *winreg_handle,
4734 struct policy_handle *hive_handle)
4736 union spoolss_PrinterInfo info;
4737 const char *keys[] = {
4738 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4739 TOP_LEVEL_PRINT_PRINTERS_KEY
4741 int i;
4742 const char *printername, *sharename;
4744 torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4746 torture_assert(tctx,
4747 test_GetPrinter_level(tctx, b, handle, 2, &info),
4748 "failed to get printer info level 2");
4750 printername = strip_unc(info.info2.printername);
4751 sharename = strip_unc(info.info2.sharename);
4753 #define test_sz(wname, iname) \
4754 do {\
4755 DATA_BLOB blob;\
4756 const char *str;\
4757 enum winreg_Type w_type;\
4758 uint32_t w_size;\
4759 uint32_t w_length;\
4760 uint8_t *w_data;\
4761 torture_assert(tctx,\
4762 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4763 &w_type, &w_size, &w_length, &w_data),\
4764 "failed to query winreg");\
4765 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4766 blob = data_blob(w_data, w_size);\
4767 str = reg_val_data_string(tctx, REG_SZ, blob);\
4768 if (w_size == 2 && iname == NULL) {\
4769 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4770 } else {\
4771 torture_assert_str_equal(tctx, str, iname,\
4772 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4774 } while(0);
4776 #define test_dword(wname, iname) \
4777 do {\
4778 uint32_t value;\
4779 enum winreg_Type w_type;\
4780 uint32_t w_size;\
4781 uint32_t w_length;\
4782 uint8_t *w_data;\
4783 torture_assert(tctx,\
4784 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4785 &w_type, &w_size, &w_length, &w_data),\
4786 "failed to query winreg");\
4787 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4788 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4789 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4790 value = IVAL(w_data, 0);\
4791 torture_assert_int_equal(tctx, value, iname,\
4792 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4793 } while(0);
4795 #define test_binary(wname, iname) \
4796 do {\
4797 enum winreg_Type w_type;\
4798 uint32_t w_size;\
4799 uint32_t w_length;\
4800 uint8_t *w_data;\
4801 torture_assert(tctx,\
4802 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4803 &w_type, &w_size, &w_length, &w_data),\
4804 "failed to query winreg");\
4805 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4806 torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4807 torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4808 "binary unequal");\
4809 } while(0);
4812 #define test_dm(wname, iname) \
4813 do {\
4814 DATA_BLOB blob;\
4815 struct spoolss_DeviceMode dm;\
4816 enum ndr_err_code ndr_err;\
4817 enum winreg_Type w_type;\
4818 uint32_t w_size;\
4819 uint32_t w_length;\
4820 uint8_t *w_data;\
4821 torture_assert(tctx,\
4822 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4823 &w_type, &w_size, &w_length, &w_data),\
4824 "failed to query winreg");\
4825 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4826 blob = data_blob(w_data, w_size);\
4827 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4828 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4829 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4830 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4831 "dm unequal");\
4832 } while(0);
4834 #define test_sd(wname, iname) \
4835 do {\
4836 DATA_BLOB blob;\
4837 struct security_descriptor sd;\
4838 enum ndr_err_code ndr_err;\
4839 enum winreg_Type w_type;\
4840 uint32_t w_size;\
4841 uint32_t w_length;\
4842 uint8_t *w_data;\
4843 torture_assert(tctx,\
4844 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4845 &w_type, &w_size, &w_length, &w_data),\
4846 "failed to query winreg");\
4847 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4848 blob = data_blob(w_data, w_size);\
4849 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4850 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4851 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4852 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4853 "sd unequal");\
4854 } while(0);
4856 #define test_multi_sz(wname, iname) \
4857 do {\
4858 DATA_BLOB blob;\
4859 const char **array;\
4860 enum winreg_Type w_type;\
4861 uint32_t w_size;\
4862 uint32_t w_length;\
4863 uint8_t *w_data;\
4864 int i;\
4865 torture_assert(tctx,\
4866 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4867 &w_type, &w_size, &w_length, &w_data),\
4868 "failed to query winreg");\
4869 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4870 blob = data_blob(w_data, w_size);\
4871 torture_assert(tctx, \
4872 pull_reg_multi_sz(tctx, &blob, &array),\
4873 "failed to pull multi sz");\
4874 for (i=0; array[i] != NULL; i++) {\
4875 torture_assert_str_equal(tctx, array[i], iname[i],\
4876 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4878 } while(0);
4880 if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4881 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4882 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4884 torture_warning(tctx, "failed to check for winreg symlink");
4887 for (i=0; i < ARRAY_SIZE(keys); i++) {
4889 const char *printer_key;
4890 struct policy_handle key_handle;
4892 printer_key = talloc_asprintf(tctx, "%s\\%s",
4893 keys[i], printer_name);
4895 torture_assert(tctx,
4896 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4898 test_sz("Name", printername);
4899 test_sz("Share Name", sharename);
4900 test_sz("Port", info.info2.portname);
4901 test_sz("Printer Driver", info.info2.drivername);
4902 test_sz("Description", info.info2.comment);
4903 test_sz("Location", info.info2.location);
4904 test_sz("Separator File", info.info2.sepfile);
4905 test_sz("Print Processor", info.info2.printprocessor);
4906 test_sz("Datatype", info.info2.datatype);
4907 test_sz("Parameters", info.info2.parameters);
4908 /* winreg: 0, spoolss not */
4909 /* test_dword("Attributes", info.info2.attributes); */
4910 test_dword("Priority", info.info2.priority);
4911 test_dword("Default Priority", info.info2.defaultpriority);
4912 /* winreg: 60, spoolss: 0 */
4913 /* test_dword("StartTime", info.info2.starttime); */
4914 /* test_dword("UntilTime", info.info2.untiltime); */
4915 /* winreg != spoolss */
4916 /* test_dword("Status", info.info2.status); */
4917 test_dm("Default DevMode", info.info2.devmode);
4918 test_sd("Security", info.info2.secdesc);
4920 torture_assert(tctx,
4921 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4924 #undef test_dm
4925 #undef test_sd
4927 torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4929 return true;
4932 static bool test_PrintProcessors(struct torture_context *tctx,
4933 struct dcerpc_binding_handle *b,
4934 const char *environment,
4935 struct dcerpc_binding_handle *winreg_handle,
4936 struct policy_handle *hive_handle)
4938 union spoolss_PrintProcessorInfo *info;
4939 uint32_t count;
4940 int i;
4942 torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4944 torture_assert(tctx,
4945 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
4946 "failed to enum print processors level 1");
4948 for (i=0; i < count; i++) {
4950 const char *processor_key;
4951 struct policy_handle key_handle;
4953 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4954 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4955 environment,
4956 info[i].info1.print_processor_name);
4958 torture_assert(tctx,
4959 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4961 /* nothing to check in there so far */
4963 torture_assert(tctx,
4964 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4967 torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4969 return true;
4972 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4973 struct dcerpc_binding_handle *b,
4974 struct policy_handle *handle,
4975 const char *driver_name,
4976 const char *architecture,
4977 uint32_t level,
4978 uint32_t client_major_version,
4979 uint32_t client_minor_version,
4980 union spoolss_DriverInfo *info_p,
4981 WERROR *result);
4983 static const char *strip_path(const char *path)
4985 char *p;
4987 if (path == NULL) {
4988 return NULL;
4991 p = strrchr(path, '\\');
4992 if (p) {
4993 return p+1;
4996 return path;
4999 static const char **strip_paths(const char **path_array)
5001 int i;
5003 if (path_array == NULL) {
5004 return NULL;
5007 for (i=0; path_array[i] != NULL; i++) {
5008 path_array[i] = strip_path(path_array[i]);
5011 return path_array;
5014 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
5016 time_t t;
5017 struct tm *tm;
5019 if (nt == 0) {
5020 return talloc_strdup(mem_ctx, "01/01/1601");
5023 t = nt_time_to_unix(nt);
5024 tm = localtime(&t);
5026 return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
5027 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
5030 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
5032 return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
5033 (unsigned)((v >> 48) & 0xFFFF),
5034 (unsigned)((v >> 32) & 0xFFFF),
5035 (unsigned)((v >> 16) & 0xFFFF),
5036 (unsigned)(v & 0xFFFF));
5039 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
5040 struct dcerpc_binding_handle *b,
5041 struct policy_handle *handle,
5042 const char *printer_name,
5043 const char *driver_name,
5044 const char *environment,
5045 enum spoolss_DriverOSVersion version,
5046 struct dcerpc_binding_handle *winreg_handle,
5047 struct policy_handle *hive_handle,
5048 const char *server_name_slash)
5050 WERROR result = WERR_OK;
5051 union spoolss_DriverInfo info;
5052 const char *driver_key;
5053 struct policy_handle key_handle;
5055 const char *driver_path;
5056 const char *data_file;
5057 const char *config_file;
5058 const char *help_file;
5059 const char **dependent_files;
5061 const char *driver_date;
5062 const char *inbox_driver_date;
5064 const char *driver_version;
5065 const char *inbox_driver_version;
5067 ZERO_STRUCT(key_handle);
5069 torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
5071 driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
5072 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
5073 environment,
5074 version,
5075 driver_name);
5077 torture_assert(tctx,
5078 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
5079 "failed to open driver key");
5081 if (torture_setting_bool(tctx, "samba3", false) ||
5082 torture_setting_bool(tctx, "w2k3", false)) {
5083 goto try_level6;
5086 if (handle) {
5087 torture_assert(tctx,
5088 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
5089 "failed to get driver info level 8");
5090 } else {
5091 torture_assert(tctx,
5092 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
5093 "failed to get driver info level 8");
5096 if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
5097 goto try_level6;
5100 driver_path = strip_path(info.info8.driver_path);
5101 data_file = strip_path(info.info8.data_file);
5102 config_file = strip_path(info.info8.config_file);
5103 help_file = strip_path(info.info8.help_file);
5104 dependent_files = strip_paths(info.info8.dependent_files);
5106 driver_date = driver_winreg_date(tctx, info.info8.driver_date);
5107 inbox_driver_date = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
5109 driver_version = driver_winreg_version(tctx, info.info8.driver_version);
5110 inbox_driver_version = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
5112 test_sz("Configuration File", config_file);
5113 test_sz("Data File", data_file);
5114 test_sz("Datatype", info.info8.default_datatype);
5115 test_sz("Driver", driver_path);
5116 test_sz("DriverDate", driver_date);
5117 test_sz("DriverVersion", driver_version);
5118 test_sz("HardwareID", info.info8.hardware_id);
5119 test_sz("Help File", help_file);
5120 test_sz("InfPath", info.info8.inf_path);
5121 test_sz("Manufacturer", info.info8.manufacturer_name);
5122 test_sz("MinInboxDriverVerDate", inbox_driver_date);
5123 test_sz("MinInboxDriverVerVersion", inbox_driver_version);
5124 test_sz("Monitor", info.info8.monitor_name);
5125 test_sz("OEM URL", info.info8.manufacturer_url);
5126 test_sz("Print Processor", info.info8.print_processor);
5127 test_sz("Provider", info.info8.provider);
5128 test_sz("VendorSetup", info.info8.vendor_setup);
5129 test_multi_sz("ColorProfiles", info.info8.color_profiles);
5130 test_multi_sz("Dependent Files", dependent_files);
5131 test_multi_sz("CoreDependencies", info.info8.core_driver_dependencies);
5132 test_multi_sz("Previous Names", info.info8.previous_names);
5133 /* test_dword("Attributes", ?); */
5134 test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
5135 test_dword("Version", info.info8.version);
5136 /* test_dword("TempDir", ?); */
5138 try_level6:
5140 if (handle) {
5141 torture_assert(tctx,
5142 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
5143 "failed to get driver info level 6");
5144 } else {
5145 torture_assert(tctx,
5146 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
5147 "failed to get driver info level 6");
5150 driver_path = strip_path(info.info6.driver_path);
5151 data_file = strip_path(info.info6.data_file);
5152 config_file = strip_path(info.info6.config_file);
5153 help_file = strip_path(info.info6.help_file);
5154 dependent_files = strip_paths(info.info6.dependent_files);
5156 driver_date = driver_winreg_date(tctx, info.info6.driver_date);
5158 driver_version = driver_winreg_version(tctx, info.info6.driver_version);
5160 test_sz("Configuration File", config_file);
5161 test_sz("Data File", data_file);
5162 test_sz("Datatype", info.info6.default_datatype);
5163 test_sz("Driver", driver_path);
5164 if (torture_setting_bool(tctx, "w2k3", false)) {
5165 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
5166 push_nttime(blob.data, 0, info.info6.driver_date);
5167 test_binary("DriverDate", blob);
5168 SBVAL(blob.data, 0, info.info6.driver_version);
5169 test_binary("DriverVersion", blob);
5170 } else {
5171 test_sz("DriverDate", driver_date);
5172 test_sz("DriverVersion", driver_version);
5174 test_sz("HardwareID", info.info6.hardware_id);
5175 test_sz("Help File", help_file);
5176 test_sz("Manufacturer", info.info6.manufacturer_name);
5177 test_sz("Monitor", info.info6.monitor_name);
5178 test_sz("OEM URL", info.info6.manufacturer_url);
5179 test_sz("Provider", info.info6.provider);
5180 test_multi_sz("Dependent Files", dependent_files);
5181 test_multi_sz("Previous Names", info.info6.previous_names);
5182 /* test_dword("Attributes", ?); */
5183 test_dword("Version", info.info6.version);
5184 /* test_dword("TempDir", ?); */
5186 if (handle) {
5187 torture_assert(tctx,
5188 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
5189 "failed to get driver info level 3");
5190 } else {
5191 torture_assert(tctx,
5192 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
5193 "failed to get driver info level 3");
5196 driver_path = strip_path(info.info3.driver_path);
5197 data_file = strip_path(info.info3.data_file);
5198 config_file = strip_path(info.info3.config_file);
5199 help_file = strip_path(info.info3.help_file);
5200 dependent_files = strip_paths(info.info3.dependent_files);
5202 test_sz("Configuration File", config_file);
5203 test_sz("Data File", data_file);
5204 test_sz("Datatype", info.info3.default_datatype);
5205 test_sz("Driver", driver_path);
5206 test_sz("Help File", help_file);
5207 test_sz("Monitor", info.info3.monitor_name);
5208 test_multi_sz("Dependent Files", dependent_files);
5209 /* test_dword("Attributes", ?); */
5210 test_dword("Version", info.info3.version);
5211 /* test_dword("TempDir", ?); */
5214 torture_assert(tctx,
5215 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
5217 torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
5219 return true;
5222 #undef test_sz
5223 #undef test_dword
5225 static bool test_SetPrinterData(struct torture_context *tctx,
5226 struct dcerpc_binding_handle *b,
5227 struct policy_handle *handle,
5228 const char *value_name,
5229 enum winreg_Type type,
5230 uint8_t *data,
5231 uint32_t offered)
5233 struct spoolss_SetPrinterData r;
5235 r.in.handle = handle;
5236 r.in.value_name = value_name;
5237 r.in.type = type;
5238 r.in.data = data;
5239 r.in.offered = offered;
5241 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
5242 r.in.value_name);
5244 torture_assert_ntstatus_ok(tctx,
5245 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
5246 "SetPrinterData failed");
5247 torture_assert_werr_ok(tctx, r.out.result,
5248 "SetPrinterData failed");
5250 return true;
5253 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
5254 struct dcerpc_binding_handle *b,
5255 struct policy_handle *handle,
5256 const char *printer_name,
5257 struct dcerpc_binding_handle *winreg_handle,
5258 struct policy_handle *hive_handle)
5260 const char *values[] = {
5261 "spootyfoot",
5262 "spooty\\foot",
5263 #if 0
5264 /* FIXME: not working with s3 atm. */
5265 "spooty,foot",
5266 "spooty,fo,ot",
5267 #endif
5268 "spooty foot",
5269 #if 0
5270 /* FIXME: not working with s3 atm. */
5271 "spooty\\fo,ot",
5272 "spooty,fo\\ot"
5273 #endif
5275 int i;
5277 for (i=0; i < ARRAY_SIZE(values); i++) {
5279 enum winreg_Type type, expected_type = REG_SZ;
5280 DATA_BLOB blob;
5281 uint8_t *data;
5282 uint32_t needed;
5284 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
5285 type = REG_SZ;
5287 torture_assert(tctx,
5288 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
5289 "SetPrinterData failed");
5291 torture_assert(tctx,
5292 test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
5293 "GetPrinterData failed");
5295 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
5296 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
5297 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
5299 if (winreg_handle && hive_handle) {
5301 enum winreg_Type w_type;
5302 uint32_t w_size;
5303 uint32_t w_length;
5304 uint8_t *w_data;
5306 torture_assert(tctx,
5307 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5308 printer_name, "PrinterDriverData", values[i],
5309 &w_type, &w_size, &w_length, &w_data), "");
5311 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
5312 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
5313 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
5314 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
5317 torture_assert(tctx,
5318 test_DeletePrinterData(tctx, b, handle, values[i]),
5319 "DeletePrinterData failed");
5322 return true;
5326 static bool test_EnumPrinterKey(struct torture_context *tctx,
5327 struct dcerpc_binding_handle *b,
5328 struct policy_handle *handle,
5329 const char *key_name,
5330 const char ***array);
5332 static bool test_SetPrinterDataEx(struct torture_context *tctx,
5333 struct dcerpc_binding_handle *b,
5334 struct policy_handle *handle,
5335 const char *key_name,
5336 const char *value_name,
5337 enum winreg_Type type,
5338 uint8_t *data,
5339 uint32_t offered)
5341 NTSTATUS status;
5342 struct spoolss_SetPrinterDataEx r;
5344 r.in.handle = handle;
5345 r.in.key_name = key_name;
5346 r.in.value_name = value_name;
5347 r.in.type = type;
5348 r.in.data = data;
5349 r.in.offered = offered;
5351 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
5352 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
5354 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
5356 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
5357 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
5359 return true;
5362 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
5363 struct dcerpc_pipe *p,
5364 struct policy_handle *handle)
5366 struct dcerpc_binding_handle *b = p->binding_handle;
5367 const char *value_name = "dog";
5368 const char *keys[] = {
5369 "torturedataex",
5370 "torture data ex",
5371 "torturedataex_with_subkey\\subkey",
5372 "torturedataex_with_subkey\\subkey:0",
5373 "torturedataex_with_subkey\\subkey:1",
5374 "torturedataex_with_subkey\\subkey\\subsubkey",
5375 "torturedataex_with_subkey\\subkey\\subsubkey:0",
5376 "torturedataex_with_subkey\\subkey\\subsubkey:1",
5377 "torture,data",
5378 "torture,data,ex",
5379 "torture,data\\ex",
5380 "torture\\data,ex",
5381 "torture/data",
5382 "torture/data ex",
5383 "torture/data ex/sub",
5384 "torture//data",
5385 "torture//data ex",
5386 "torture//data ex/sub",
5387 "torture//data ex//sub",
5389 int i;
5391 for (i=0; i < ARRAY_SIZE(keys); i++) {
5393 char *c;
5394 const char *key;
5395 enum winreg_Type type;
5396 DATA_BLOB blob_in, blob_out;
5397 const char **subkeys;
5398 uint32_t ecount;
5399 struct spoolss_PrinterEnumValues *einfo;
5400 uint32_t needed;
5402 blob_in = data_blob_talloc(tctx, NULL, 42);
5404 generate_random_buffer(blob_in.data, blob_in.length);
5406 torture_assert(tctx,
5407 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
5408 "failed to call SetPrinterDataEx");
5410 torture_assert(tctx,
5411 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
5412 "failed to call GetPrinterDataEx");
5414 blob_out.length = needed;
5415 torture_assert(tctx,
5416 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
5417 "failed to call EnumPrinterDataEx");
5419 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5420 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5421 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5423 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5424 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5425 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5426 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5427 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5428 if (einfo[0].data_length > 0) {
5429 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5432 key = talloc_strdup(tctx, keys[i]);
5434 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
5435 return false;
5438 c = strchr(key, '\\');
5439 if (c) {
5440 int k;
5442 /* we have subkeys */
5444 *c = 0;
5446 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
5447 return false;
5450 for (k=0; subkeys && subkeys[k]; k++) {
5452 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
5454 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
5455 return false;
5459 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5460 return false;
5463 } else {
5464 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5465 return false;
5470 return true;
5473 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
5474 struct dcerpc_pipe *p,
5475 struct policy_handle *handle)
5477 struct dcerpc_binding_handle *b = p->binding_handle;
5478 const char *key = "torturedataex";
5479 const char *values[] = {
5480 "torture_value",
5481 "torture value",
5482 "torture,value",
5483 "torture/value",
5484 "torture\\value",
5485 "torture\\\\value"
5487 int i;
5489 for (i=0; i < ARRAY_SIZE(values); i++) {
5491 enum winreg_Type type;
5492 DATA_BLOB blob_in, blob_out;
5493 uint32_t ecount;
5494 struct spoolss_PrinterEnumValues *einfo;
5495 uint32_t needed;
5497 if (torture_setting_bool(tctx, "samba3", false)) {
5498 char *q;
5499 q = strrchr(values[i], ',');
5500 if (q) {
5501 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
5502 values[i]);
5503 continue;
5507 blob_in = data_blob_talloc(tctx, NULL, 42);
5509 generate_random_buffer(blob_in.data, blob_in.length);
5511 torture_assert(tctx,
5512 test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
5513 "failed to call SetPrinterDataEx");
5515 torture_assert(tctx,
5516 test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
5517 "failed to call GetPrinterDataEx");
5519 blob_out.length = needed;
5520 torture_assert(tctx,
5521 test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
5522 "failed to call EnumPrinterDataEx");
5524 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5525 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5526 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5528 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5529 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5530 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5531 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5532 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5533 if (einfo[0].data_length > 0) {
5534 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5537 torture_assert(tctx,
5538 test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5539 "failed to call DeletePrinterDataEx");
5542 return true;
5546 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5547 struct dcerpc_pipe *p,
5548 struct policy_handle *handle,
5549 const char *printername,
5550 struct dcerpc_binding_handle *winreg_handle,
5551 struct policy_handle *hive_handle)
5553 struct dcerpc_binding_handle *b = p->binding_handle;
5554 const char *value_name = "dog";
5555 const char *key_name = "torturedataex";
5556 enum winreg_Type types[] = {
5557 REG_SZ,
5558 REG_MULTI_SZ,
5559 REG_DWORD,
5560 REG_BINARY
5562 const char *str = "abcdefghi";
5563 int t, s;
5565 for (t=0; t < ARRAY_SIZE(types); t++) {
5566 for (s=0; s < strlen(str); s++) {
5568 enum winreg_Type type;
5569 const char *string = talloc_strndup(tctx, str, s);
5570 const char *array[2];
5571 DATA_BLOB blob = data_blob_string_const(string);
5572 DATA_BLOB data;
5573 uint8_t *data_out;
5574 uint32_t needed, offered = 0;
5575 uint32_t ecount;
5576 struct spoolss_PrinterEnumValues *einfo;
5578 array[0] = talloc_strdup(tctx, string);
5579 array[1] = NULL;
5581 if (types[t] == REG_DWORD) {
5582 s = 0xffff;
5585 switch (types[t]) {
5586 case REG_BINARY:
5587 data = blob;
5588 offered = blob.length;
5589 break;
5590 case REG_DWORD:
5591 data = data_blob_talloc(tctx, NULL, 4);
5592 SIVAL(data.data, 0, 0x12345678);
5593 offered = 4;
5594 break;
5595 case REG_SZ:
5596 torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5597 type = REG_SZ;
5598 offered = data.length;
5599 /*strlen_m_term(data.string)*2;*/
5600 break;
5601 case REG_MULTI_SZ:
5602 torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5603 type = REG_MULTI_SZ;
5604 offered = data.length;
5605 break;
5606 default:
5607 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5610 torture_assert(tctx,
5611 test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5612 "failed to call SetPrinterDataEx");
5614 torture_assert(tctx,
5615 test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
5616 "failed to call GetPrinterDataEx");
5618 torture_assert(tctx,
5619 test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5620 "failed to call EnumPrinterDataEx");
5622 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5623 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5624 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5626 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5627 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5628 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5629 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5630 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5631 if (einfo[0].data_length > 0) {
5632 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5635 if (winreg_handle && hive_handle) {
5636 enum winreg_Type w_type;
5637 uint32_t w_size;
5638 uint32_t w_length;
5639 uint8_t *w_data;
5641 torture_assert(tctx,
5642 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5643 printername, key_name, value_name,
5644 &w_type, &w_size, &w_length, &w_data), "");
5646 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5647 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5648 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5649 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5652 torture_assert(tctx,
5653 test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5654 "failed to call DeletePrinterDataEx");
5658 return true;
5661 static bool test_PrinterData_winreg(struct torture_context *tctx,
5662 struct dcerpc_pipe *p,
5663 struct policy_handle *handle,
5664 const char *printer_name)
5666 struct dcerpc_binding_handle *b = p->binding_handle;
5667 struct dcerpc_pipe *p2;
5668 bool ret = true;
5669 struct policy_handle hive_handle;
5670 struct dcerpc_binding_handle *b2;
5672 torture_assert_ntstatus_ok(tctx,
5673 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5674 "could not open winreg pipe");
5675 b2 = p2->binding_handle;
5677 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5679 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5680 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5682 test_winreg_CloseKey(tctx, b2, &hive_handle);
5684 talloc_free(p2);
5686 return ret;
5689 static bool test_Forms_winreg(struct torture_context *tctx,
5690 struct dcerpc_binding_handle *b,
5691 struct policy_handle *handle,
5692 bool print_server,
5693 const char *printer_name)
5695 struct dcerpc_pipe *p2;
5696 bool ret = true;
5697 struct policy_handle hive_handle;
5698 struct dcerpc_binding_handle *b2;
5700 torture_assert_ntstatus_ok(tctx,
5701 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5702 "could not open winreg pipe");
5703 b2 = p2->binding_handle;
5705 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5707 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5709 test_winreg_CloseKey(tctx, b2, &hive_handle);
5711 talloc_free(p2);
5713 return ret;
5716 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5717 struct dcerpc_pipe *p,
5718 struct policy_handle *handle,
5719 const char *printer_name)
5721 struct dcerpc_binding_handle *b = p->binding_handle;
5722 struct dcerpc_pipe *p2;
5723 bool ret = true;
5724 struct policy_handle hive_handle;
5725 struct dcerpc_binding_handle *b2;
5727 torture_assert_ntstatus_ok(tctx,
5728 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5729 "could not open winreg pipe");
5730 b2 = p2->binding_handle;
5732 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5734 ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5736 test_winreg_CloseKey(tctx, b2, &hive_handle);
5738 talloc_free(p2);
5740 return ret;
5743 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5744 struct dcerpc_pipe *p,
5745 struct policy_handle *handle,
5746 const char *printer_name,
5747 const char *driver_name,
5748 const char *environment,
5749 enum spoolss_DriverOSVersion version)
5751 struct dcerpc_binding_handle *b = p->binding_handle;
5752 struct dcerpc_pipe *p2;
5753 bool ret = true;
5754 struct policy_handle hive_handle;
5755 struct dcerpc_binding_handle *b2;
5757 torture_assert_ntstatus_ok(tctx,
5758 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5759 "could not open winreg pipe");
5760 b2 = p2->binding_handle;
5762 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5764 ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
5766 test_winreg_CloseKey(tctx, b2, &hive_handle);
5768 talloc_free(p2);
5770 return ret;
5773 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5774 struct dcerpc_binding_handle *b,
5775 const char *environment)
5777 struct dcerpc_pipe *p2;
5778 bool ret = true;
5779 struct policy_handle hive_handle;
5780 struct dcerpc_binding_handle *b2;
5782 torture_assert_ntstatus_ok(tctx,
5783 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5784 "could not open winreg pipe");
5785 b2 = p2->binding_handle;
5787 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5789 ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5791 test_winreg_CloseKey(tctx, b2, &hive_handle);
5793 talloc_free(p2);
5795 return ret;
5798 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5799 struct dcerpc_pipe *p,
5800 struct policy_handle *handle,
5801 const char *printer_name)
5803 struct spoolss_SetPrinterInfoCtr info_ctr;
5804 struct spoolss_DevmodeContainer devmode_ctr;
5805 struct sec_desc_buf secdesc_ctr;
5806 union spoolss_SetPrinterInfo sinfo;
5807 union spoolss_PrinterInfo info;
5808 struct dcerpc_binding_handle *b = p->binding_handle;
5809 const char *pname;
5811 ZERO_STRUCT(info_ctr);
5812 ZERO_STRUCT(devmode_ctr);
5813 ZERO_STRUCT(secdesc_ctr);
5815 torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5817 torture_assert(tctx,
5818 test_GetPrinter_level(tctx, b, handle, 2, &info),
5819 "failed to query Printer level 2");
5821 torture_assert(tctx,
5822 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5823 "failed to convert");
5825 info_ctr.level = 2;
5826 info_ctr.info = sinfo;
5828 #define TEST_SZ(wname, iname) \
5829 do {\
5830 enum winreg_Type type;\
5831 uint8_t *data;\
5832 uint32_t needed;\
5833 DATA_BLOB blob;\
5834 const char *str;\
5835 torture_assert(tctx,\
5836 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5837 "failed to query");\
5838 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5839 blob = data_blob_const(data, needed);\
5840 torture_assert(tctx,\
5841 pull_reg_sz(tctx, &blob, &str),\
5842 "failed to pull REG_SZ");\
5843 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5844 } while(0);
5847 #define TEST_SET_SZ(wname, iname, val) \
5848 do {\
5849 enum winreg_Type type;\
5850 uint8_t *data;\
5851 uint32_t needed;\
5852 DATA_BLOB blob;\
5853 const char *str;\
5854 sinfo.info2->iname = val;\
5855 torture_assert(tctx,\
5856 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5857 "failed to call SetPrinter");\
5858 torture_assert(tctx,\
5859 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5860 "failed to query");\
5861 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5862 blob = data_blob_const(data, needed);\
5863 torture_assert(tctx,\
5864 pull_reg_sz(tctx, &blob, &str),\
5865 "failed to pull REG_SZ");\
5866 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5867 } while(0);
5869 #define TEST_SET_DWORD(wname, iname, val) \
5870 do {\
5871 enum winreg_Type type;\
5872 uint8_t *data;\
5873 uint32_t needed;\
5874 uint32_t value;\
5875 sinfo.info2->iname = val;\
5876 torture_assert(tctx,\
5877 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5878 "failed to call SetPrinter");\
5879 torture_assert(tctx,\
5880 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5881 "failed to query");\
5882 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5883 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5884 value = IVAL(data, 0); \
5885 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5886 } while(0);
5888 TEST_SET_SZ("description", comment, "newval");
5889 TEST_SET_SZ("location", location, "newval");
5890 TEST_SET_SZ("driverName", drivername, "newval");
5891 /* TEST_SET_DWORD("priority", priority, 25); */
5893 torture_assert(tctx,
5894 test_GetPrinter_level(tctx, b, handle, 2, &info),
5895 "failed to query Printer level 2");
5897 TEST_SZ("description", info.info2.comment);
5898 TEST_SZ("driverName", info.info2.drivername);
5899 TEST_SZ("location", info.info2.location);
5901 pname = strrchr(info.info2.printername, '\\');
5902 if (pname == NULL) {
5903 pname = info.info2.printername;
5904 } else {
5905 pname++;
5907 TEST_SZ("printerName", pname);
5908 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5909 /* TEST_SZ("printShareName", info.info2.sharename); */
5911 /* FIXME gd: complete the list */
5913 #undef TEST_SZ
5914 #undef TEST_SET_SZ
5915 #undef TEST_DWORD
5917 torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5919 return true;
5922 static bool test_print_processors_winreg(struct torture_context *tctx,
5923 void *private_data)
5925 struct test_spoolss_context *ctx =
5926 talloc_get_type_abort(private_data, struct test_spoolss_context);
5927 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5928 struct dcerpc_binding_handle *b = p->binding_handle;
5930 return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5933 static bool test_AddPrintProcessor(struct torture_context *tctx,
5934 struct dcerpc_binding_handle *b,
5935 const char *environment,
5936 const char *path_name,
5937 const char *print_processor_name,
5938 WERROR expected_error)
5940 struct spoolss_AddPrintProcessor r;
5942 r.in.server = NULL;
5943 r.in.architecture = environment;
5944 r.in.path_name = path_name;
5945 r.in.print_processor_name = print_processor_name;
5947 torture_comment(tctx, "Testing AddPrintProcessor(%s)\n",
5948 print_processor_name);
5950 torture_assert_ntstatus_ok(tctx,
5951 dcerpc_spoolss_AddPrintProcessor_r(b, tctx, &r),
5952 "spoolss_AddPrintProcessor failed");
5953 torture_assert_werr_equal(tctx, r.out.result, expected_error,
5954 "spoolss_AddPrintProcessor failed");
5956 return true;
5959 static bool test_DeletePrintProcessor(struct torture_context *tctx,
5960 struct dcerpc_binding_handle *b,
5961 const char *environment,
5962 const char *print_processor_name,
5963 WERROR expected_error)
5965 struct spoolss_DeletePrintProcessor r;
5967 r.in.server = NULL;
5968 r.in.architecture = environment;
5969 r.in.print_processor_name = print_processor_name;
5971 torture_comment(tctx, "Testing DeletePrintProcessor(%s)\n",
5972 print_processor_name);
5974 torture_assert_ntstatus_ok(tctx,
5975 dcerpc_spoolss_DeletePrintProcessor_r(b, tctx, &r),
5976 "spoolss_DeletePrintProcessor failed");
5977 torture_assert_werr_equal(tctx, r.out.result, expected_error,
5978 "spoolss_DeletePrintProcessor failed");
5980 return true;
5983 static bool test_add_print_processor(struct torture_context *tctx,
5984 void *private_data)
5986 struct test_spoolss_context *ctx =
5987 talloc_get_type_abort(private_data, struct test_spoolss_context);
5988 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5989 struct dcerpc_binding_handle *b = p->binding_handle;
5990 int i;
5992 struct {
5993 const char *environment;
5994 const char *path_name;
5995 const char *print_processor_name;
5996 WERROR expected_add_result;
5997 WERROR expected_del_result;
5998 } tests[] = {
6000 .environment = ctx->environment,
6001 .path_name = "",
6002 .print_processor_name = "winprint",
6003 .expected_add_result = WERR_PRINT_PROCESSOR_ALREADY_INSTALLED,
6004 .expected_del_result = WERR_CAN_NOT_COMPLETE
6006 .environment = ctx->environment,
6007 .path_name = "",
6008 .print_processor_name = "unknown",
6009 .expected_add_result = WERR_MOD_NOT_FOUND,
6010 .expected_del_result = WERR_UNKNOWN_PRINTPROCESSOR
6014 for (i=0; i < ARRAY_SIZE(tests); i++) {
6015 torture_assert(tctx,
6016 test_AddPrintProcessor(tctx, b,
6017 tests[i].environment,
6018 tests[i].path_name,
6019 tests[i].print_processor_name,
6020 tests[i].expected_add_result),
6021 "add print processor failed");
6022 torture_assert(tctx,
6023 test_DeletePrintProcessor(tctx, b,
6024 tests[i].environment,
6025 tests[i].print_processor_name,
6026 tests[i].expected_del_result),
6027 "delete print processor failed");
6030 return true;
6033 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
6034 struct dcerpc_binding_handle *b,
6035 struct policy_handle *handle,
6036 uint32_t *change_id)
6038 enum winreg_Type type;
6039 uint8_t *data;
6040 uint32_t needed;
6042 torture_assert(tctx,
6043 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
6044 "failed to call GetPrinterData");
6046 torture_assert(tctx, type == REG_DWORD, "unexpected type");
6047 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
6049 *change_id = IVAL(data, 0);
6051 return true;
6054 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
6055 struct dcerpc_pipe *p,
6056 struct policy_handle *handle,
6057 uint32_t *change_id)
6059 enum winreg_Type type;
6060 uint8_t *data;
6061 uint32_t needed;
6063 torture_assert(tctx,
6064 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
6065 "failed to call GetPrinterData");
6067 torture_assert(tctx, type == REG_DWORD, "unexpected type");
6068 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
6070 *change_id = IVAL(data, 0);
6072 return true;
6075 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
6076 struct dcerpc_binding_handle *b,
6077 struct policy_handle *handle,
6078 uint32_t *change_id)
6080 union spoolss_PrinterInfo info;
6082 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
6083 "failed to query Printer level 0");
6085 *change_id = info.info0.change_id;
6087 return true;
6090 static bool test_ChangeID(struct torture_context *tctx,
6091 struct dcerpc_pipe *p,
6092 struct policy_handle *handle)
6094 uint32_t change_id, change_id_ex, change_id_info;
6095 uint32_t change_id2, change_id_ex2, change_id_info2;
6096 union spoolss_PrinterInfo info;
6097 const char *comment;
6098 struct dcerpc_binding_handle *b = p->binding_handle;
6100 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
6102 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6103 "failed to query for ChangeID");
6104 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6105 "failed to query for ChangeID");
6106 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6107 "failed to query for ChangeID");
6109 torture_assert_int_equal(tctx, change_id, change_id_ex,
6110 "change_ids should all be equal");
6111 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
6112 "change_ids should all be equal");
6115 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
6117 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6118 "failed to query for ChangeID");
6119 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
6120 "failed to query Printer level 2");
6121 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6122 "failed to query for ChangeID");
6123 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6124 "failed to query for ChangeID");
6125 torture_assert_int_equal(tctx, change_id, change_id_ex,
6126 "change_id should not have changed");
6127 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
6128 "change_id should not have changed");
6131 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
6133 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6134 "failed to query for ChangeID");
6135 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6136 "failed to query for ChangeID");
6137 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6138 "failed to query for ChangeID");
6139 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
6140 "failed to query Printer level 2");
6141 comment = talloc_strdup(tctx, info.info2.comment);
6144 struct spoolss_SetPrinterInfoCtr info_ctr;
6145 struct spoolss_DevmodeContainer devmode_ctr;
6146 struct sec_desc_buf secdesc_ctr;
6147 union spoolss_SetPrinterInfo sinfo;
6149 ZERO_STRUCT(info_ctr);
6150 ZERO_STRUCT(devmode_ctr);
6151 ZERO_STRUCT(secdesc_ctr);
6154 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
6155 sinfo.info2->comment = "torture_comment";
6157 info_ctr.level = 2;
6158 info_ctr.info = sinfo;
6160 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6161 "failed to call SetPrinter");
6163 sinfo.info2->comment = comment;
6165 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6166 "failed to call SetPrinter");
6170 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
6171 "failed to query for ChangeID");
6172 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
6173 "failed to query for ChangeID");
6174 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
6175 "failed to query for ChangeID");
6177 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
6178 "change_ids should all be equal");
6179 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
6180 "change_ids should all be equal");
6182 torture_assert(tctx, (change_id < change_id2),
6183 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6184 change_id2, change_id));
6185 torture_assert(tctx, (change_id_ex < change_id_ex2),
6186 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6187 change_id_ex2, change_id_ex));
6188 torture_assert(tctx, (change_id_info < change_id_info2),
6189 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6190 change_id_info2, change_id_info));
6192 torture_comment(tctx, "ChangeID tests succeeded\n\n");
6194 return true;
6197 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
6198 struct dcerpc_pipe *p,
6199 struct policy_handle *handle)
6201 NTSTATUS status;
6202 const struct dcerpc_binding *binding2;
6203 struct dcerpc_pipe *p2;
6204 struct spoolss_ClosePrinter cp;
6206 /* only makes sense on SMB */
6207 if (p->conn->transport.transport != NCACN_NP) {
6208 return true;
6211 torture_comment(tctx, "Testing close on secondary pipe\n");
6213 binding2 = p->binding;
6214 status = dcerpc_secondary_connection(p, &p2, binding2);
6215 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
6217 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
6218 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
6220 cp.in.handle = handle;
6221 cp.out.handle = handle;
6223 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
6224 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
6225 "ERROR: Allowed close on secondary connection");
6227 talloc_free(p2);
6229 return true;
6232 static bool test_OpenPrinter_badname(struct torture_context *tctx,
6233 struct dcerpc_binding_handle *b, const char *name)
6235 NTSTATUS status;
6236 struct spoolss_OpenPrinter op;
6237 struct spoolss_OpenPrinterEx opEx;
6238 struct policy_handle handle;
6239 bool ret = true;
6241 op.in.printername = name;
6242 op.in.datatype = NULL;
6243 op.in.devmode_ctr.devmode= NULL;
6244 op.in.access_mask = 0;
6245 op.out.handle = &handle;
6247 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
6249 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
6250 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
6251 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
6252 "unexpected result");
6254 if (W_ERROR_IS_OK(op.out.result)) {
6255 ret &=test_ClosePrinter(tctx, b, &handle);
6258 opEx.in.printername = name;
6259 opEx.in.datatype = NULL;
6260 opEx.in.devmode_ctr.devmode = NULL;
6261 opEx.in.access_mask = 0;
6262 opEx.in.userlevel_ctr.level = 1;
6263 opEx.in.userlevel_ctr.user_info.level1 = NULL;
6264 opEx.out.handle = &handle;
6266 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
6268 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
6269 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
6270 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
6271 "unexpected result");
6273 if (W_ERROR_IS_OK(opEx.out.result)) {
6274 ret &=test_ClosePrinter(tctx, b, &handle);
6277 return ret;
6280 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
6281 void *private_data)
6283 struct test_spoolss_context *ctx =
6284 talloc_get_type_abort(private_data, struct test_spoolss_context);
6286 const char *badnames[] = {
6287 "__INVALID_PRINTER__",
6288 "\\\\__INVALID_HOST__",
6290 "\\\\\\",
6291 "\\\\\\__INVALID_PRINTER__"
6293 const char *badname;
6294 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6295 const char *server_name = dcerpc_server_name(p);
6296 struct dcerpc_binding_handle *b = p->binding_handle;
6297 int i;
6299 for (i=0; i < ARRAY_SIZE(badnames); i++) {
6300 torture_assert(tctx,
6301 test_OpenPrinter_badname(tctx, b, badnames[i]),
6302 "");
6305 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
6306 torture_assert(tctx,
6307 test_OpenPrinter_badname(tctx, b, badname),
6308 "");
6310 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
6311 torture_assert(tctx,
6312 test_OpenPrinter_badname(tctx, b, badname),
6313 "");
6315 return true;
6318 static bool test_OpenPrinter(struct torture_context *tctx,
6319 struct dcerpc_pipe *p,
6320 const char *name,
6321 const char *environment,
6322 bool open_only)
6324 NTSTATUS status;
6325 struct spoolss_OpenPrinter r;
6326 struct policy_handle handle;
6327 bool ret = true;
6328 struct dcerpc_binding_handle *b = p->binding_handle;
6330 r.in.printername = name;
6331 r.in.datatype = NULL;
6332 r.in.devmode_ctr.devmode= NULL;
6333 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6334 r.out.handle = &handle;
6336 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
6338 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
6340 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
6342 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
6344 if (open_only) {
6345 goto close_printer;
6348 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6349 ret = false;
6352 if (!torture_setting_bool(tctx, "samba3", false)) {
6353 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6354 ret = false;
6358 close_printer:
6359 if (!test_ClosePrinter(tctx, b, &handle)) {
6360 ret = false;
6363 return ret;
6366 static bool test_OpenPrinterEx(struct torture_context *tctx,
6367 struct dcerpc_binding_handle *b,
6368 const char *printername,
6369 const char *datatype,
6370 struct spoolss_DeviceMode *devmode,
6371 uint32_t access_mask,
6372 struct spoolss_UserLevelCtr *userlevel_ctr,
6373 struct policy_handle *handle,
6374 WERROR expected_result)
6376 struct spoolss_OpenPrinterEx r;
6378 r.in.printername = printername;
6379 r.in.datatype = datatype;
6380 r.in.devmode_ctr.devmode= devmode;
6381 r.in.access_mask = access_mask;
6382 r.in.userlevel_ctr = *userlevel_ctr;
6383 r.out.handle = handle;
6385 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
6387 torture_assert_ntstatus_ok(tctx,
6388 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
6389 "OpenPrinterEx failed");
6391 torture_assert_werr_equal(tctx, r.out.result, expected_result,
6392 "OpenPrinterEx failed");
6394 return true;
6397 static bool call_OpenPrinterEx(struct torture_context *tctx,
6398 struct dcerpc_pipe *p,
6399 const char *name,
6400 struct spoolss_DeviceMode *devmode,
6401 struct policy_handle *handle)
6403 struct spoolss_UserLevelCtr userlevel_ctr;
6404 struct spoolss_UserLevel1 userlevel1;
6405 struct dcerpc_binding_handle *b = p->binding_handle;
6407 userlevel1.size = 1234;
6408 userlevel1.client = "hello";
6409 userlevel1.user = "spottyfoot!";
6410 userlevel1.build = 1;
6411 userlevel1.major = 2;
6412 userlevel1.minor = 3;
6413 userlevel1.processor = 4;
6415 userlevel_ctr.level = 1;
6416 userlevel_ctr.user_info.level1 = &userlevel1;
6418 return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
6419 SEC_FLAG_MAXIMUM_ALLOWED,
6420 &userlevel_ctr,
6421 handle,
6422 WERR_OK);
6425 static bool test_printer_rename(struct torture_context *tctx,
6426 void *private_data)
6428 struct torture_printer_context *t =
6429 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6430 struct dcerpc_pipe *p = t->spoolss_pipe;
6432 bool ret = true;
6433 union spoolss_PrinterInfo info;
6434 union spoolss_SetPrinterInfo sinfo;
6435 struct spoolss_SetPrinterInfoCtr info_ctr;
6436 struct spoolss_DevmodeContainer devmode_ctr;
6437 struct sec_desc_buf secdesc_ctr;
6438 const char *printer_name;
6439 const char *printer_name_orig;
6440 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
6441 struct policy_handle new_handle;
6442 const char *q;
6443 struct dcerpc_binding_handle *b = p->binding_handle;
6445 ZERO_STRUCT(devmode_ctr);
6446 ZERO_STRUCT(secdesc_ctr);
6448 torture_comment(tctx, "Testing Printer rename operations\n");
6450 torture_assert(tctx,
6451 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
6452 "failed to call GetPrinter level 2");
6454 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
6456 q = strrchr(info.info2.printername, '\\');
6457 if (q) {
6458 torture_warning(tctx,
6459 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6462 torture_assert(tctx,
6463 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
6465 sinfo.info2->printername = printer_name_new;
6467 info_ctr.level = 2;
6468 info_ctr.info = sinfo;
6470 torture_assert(tctx,
6471 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6472 "failed to call SetPrinter level 2");
6474 torture_assert(tctx,
6475 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
6476 "failed to call GetPrinter level 2");
6478 printer_name = talloc_strdup(tctx, info.info2.printername);
6480 q = strrchr(info.info2.printername, '\\');
6481 if (q) {
6482 torture_warning(tctx,
6483 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6484 q++;
6485 printer_name = q;
6488 torture_assert_str_equal(tctx, printer_name, printer_name_new,
6489 "new printer name was not set");
6491 /* samba currently cannot fully rename printers */
6492 if (!torture_setting_bool(tctx, "samba3", false)) {
6493 torture_assert(tctx,
6494 test_OpenPrinter_badname(tctx, b, printer_name_orig),
6495 "still can open printer with oldname after rename");
6496 } else {
6497 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
6500 torture_assert(tctx,
6501 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
6502 "failed to open printer with new name");
6504 torture_assert(tctx,
6505 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
6506 "failed to call GetPrinter level 2");
6508 torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
6509 "new printer name was not set");
6511 torture_assert(tctx,
6512 test_ClosePrinter(tctx, b, &new_handle),
6513 "failed to close printer");
6515 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
6517 return ret;
6520 static bool test_openprinter(struct torture_context *tctx,
6521 struct dcerpc_binding_handle *b,
6522 const char *real_printername)
6524 struct spoolss_UserLevelCtr userlevel_ctr;
6525 struct policy_handle handle;
6526 struct spoolss_UserLevel1 userlevel1;
6527 const char *printername = NULL;
6528 int i;
6530 struct {
6531 const char *suffix;
6532 WERROR expected_result;
6533 } tests[] = {
6535 .suffix = "rubbish",
6536 .expected_result = WERR_INVALID_PRINTER_NAME
6538 .suffix = ", LocalOnl",
6539 .expected_result = WERR_INVALID_PRINTER_NAME
6541 .suffix = ", localOnly",
6542 .expected_result = WERR_INVALID_PRINTER_NAME
6544 .suffix = ", localonl",
6545 .expected_result = WERR_INVALID_PRINTER_NAME
6547 .suffix = ",LocalOnl",
6548 .expected_result = WERR_INVALID_PRINTER_NAME
6550 .suffix = ",localOnl2",
6551 .expected_result = WERR_INVALID_PRINTER_NAME
6553 .suffix = ", DrvConver2t",
6554 .expected_result = WERR_INVALID_PRINTER_NAME
6556 .suffix = ", drvconvert",
6557 .expected_result = WERR_INVALID_PRINTER_NAME
6559 .suffix = ",drvconvert",
6560 .expected_result = WERR_INVALID_PRINTER_NAME
6562 .suffix = ", DrvConvert",
6563 .expected_result = WERR_OK
6565 .suffix = " , DrvConvert",
6566 .expected_result = WERR_INVALID_PRINTER_NAME
6568 .suffix = ",DrvConvert",
6569 .expected_result = WERR_OK
6571 .suffix = ", DrvConvertsadfasdf",
6572 .expected_result = WERR_OK
6574 .suffix = ",DrvConvertasdfasd",
6575 .expected_result = WERR_OK
6577 .suffix = ", LocalOnly",
6578 .expected_result = WERR_OK
6580 .suffix = " , LocalOnly",
6581 .expected_result = WERR_INVALID_PRINTER_NAME
6583 .suffix = ",LocalOnly",
6584 .expected_result = WERR_OK
6586 .suffix = ", LocalOnlysagi4gjfkd",
6587 .expected_result = WERR_OK
6589 .suffix = ",LocalOnlysagi4gjfkd",
6590 .expected_result = WERR_OK
6594 userlevel1.size = 1234;
6595 userlevel1.client = "hello";
6596 userlevel1.user = "spottyfoot!";
6597 userlevel1.build = 1;
6598 userlevel1.major = 2;
6599 userlevel1.minor = 3;
6600 userlevel1.processor = 4;
6602 userlevel_ctr.level = 1;
6603 userlevel_ctr.user_info.level1 = &userlevel1;
6605 torture_comment(tctx, "Testing openprinterex printername pattern\n");
6607 torture_assert(tctx,
6608 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0,
6609 &userlevel_ctr, &handle,
6610 WERR_OK),
6611 "OpenPrinterEx failed");
6612 test_ClosePrinter(tctx, b, &handle);
6614 for (i=0; i < ARRAY_SIZE(tests); i++) {
6616 printername = talloc_asprintf(tctx, "%s%s",
6617 real_printername,
6618 tests[i].suffix);
6620 torture_assert(tctx,
6621 test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0,
6622 &userlevel_ctr, &handle,
6623 tests[i].expected_result),
6624 "OpenPrinterEx failed");
6625 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6626 test_ClosePrinter(tctx, b, &handle);
6630 return true;
6634 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6635 struct dcerpc_pipe *p,
6636 const char *name,
6637 const char *environment)
6639 struct policy_handle handle;
6640 bool ret = true;
6641 struct dcerpc_binding_handle *b = p->binding_handle;
6643 if (!test_openprinter(tctx, b, name)) {
6644 return false;
6647 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6648 return false;
6651 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6652 ret = false;
6655 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6656 ret = false;
6659 if (!test_EnumForms_all(tctx, b, &handle, false)) {
6660 ret = false;
6663 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6664 ret = false;
6667 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6668 ret = false;
6671 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6672 ret = false;
6675 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6676 ret = false;
6679 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6680 ret = false;
6683 if (!test_printer_all_keys(tctx, b, &handle)) {
6684 ret = false;
6687 if (!test_PausePrinter(tctx, b, &handle)) {
6688 ret = false;
6691 if (!test_DoPrintTest(tctx, b, &handle)) {
6692 ret = false;
6695 if (!test_ResumePrinter(tctx, b, &handle)) {
6696 ret = false;
6699 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
6700 ret = false;
6703 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
6704 ret = false;
6707 if (!torture_setting_bool(tctx, "samba3", false)) {
6708 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6709 ret = false;
6713 if (!test_ClosePrinter(tctx, b, &handle)) {
6714 ret = false;
6717 return ret;
6720 static bool test_EnumPrinters_old(struct torture_context *tctx,
6721 void *private_data)
6723 struct test_spoolss_context *ctx =
6724 talloc_get_type_abort(private_data, struct test_spoolss_context);
6725 struct spoolss_EnumPrinters r;
6726 NTSTATUS status;
6727 uint16_t levels[] = {1, 2, 4, 5};
6728 int i;
6729 bool ret = true;
6730 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6731 struct dcerpc_binding_handle *b = p->binding_handle;
6733 for (i=0;i<ARRAY_SIZE(levels);i++) {
6734 union spoolss_PrinterInfo *info;
6735 int j;
6736 uint32_t needed;
6737 uint32_t count;
6739 r.in.flags = PRINTER_ENUM_LOCAL;
6740 r.in.server = "";
6741 r.in.level = levels[i];
6742 r.in.buffer = NULL;
6743 r.in.offered = 0;
6744 r.out.needed = &needed;
6745 r.out.count = &count;
6746 r.out.info = &info;
6748 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6750 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6751 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6753 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6754 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6755 r.in.buffer = &blob;
6756 r.in.offered = needed;
6757 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6760 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6762 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6764 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6766 if (!info) {
6767 torture_comment(tctx, "No printers returned\n");
6768 return true;
6771 for (j=0;j<count;j++) {
6772 if (r.in.level == 1) {
6773 char *unc = talloc_strdup(tctx, info[j].info1.name);
6774 char *slash, *name, *full_name;
6775 name = unc;
6776 if (unc[0] == '\\' && unc[1] == '\\') {
6777 unc +=2;
6779 slash = strchr(unc, '\\');
6780 if (slash) {
6781 slash++;
6782 name = slash;
6784 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6785 dcerpc_server_name(p), name);
6786 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6787 ret = false;
6789 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6790 ret = false;
6792 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6793 ret = false;
6795 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6796 ret = false;
6802 return ret;
6805 static bool test_EnumPrinters_level(struct torture_context *tctx,
6806 struct dcerpc_binding_handle *b,
6807 uint32_t flags,
6808 const char *servername,
6809 uint32_t level,
6810 uint32_t *count_p,
6811 union spoolss_PrinterInfo **info_p)
6813 struct spoolss_EnumPrinters r;
6814 union spoolss_PrinterInfo *info;
6815 uint32_t needed;
6816 uint32_t count;
6818 r.in.flags = flags;
6819 r.in.server = servername;
6820 r.in.level = level;
6821 r.in.buffer = NULL;
6822 r.in.offered = 0;
6823 r.out.needed = &needed;
6824 r.out.count = &count;
6825 r.out.info = &info;
6827 torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6828 r.in.server, r.in.level);
6830 torture_assert_ntstatus_ok(tctx,
6831 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6832 "EnumPrinters failed");
6833 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6834 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6835 r.in.buffer = &blob;
6836 r.in.offered = needed;
6837 torture_assert_ntstatus_ok(tctx,
6838 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6839 "EnumPrinters failed");
6842 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6844 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6846 if (count_p) {
6847 *count_p = count;
6849 if (info_p) {
6850 *info_p = info;
6853 return true;
6856 static const char *get_short_printername(struct torture_context *tctx,
6857 const char *name)
6859 const char *short_name;
6861 if (name[0] == '\\' && name[1] == '\\') {
6862 name += 2;
6863 short_name = strchr(name, '\\');
6864 if (short_name) {
6865 return talloc_strdup(tctx, short_name+1);
6869 return name;
6872 static const char *get_full_printername(struct torture_context *tctx,
6873 const char *name)
6875 const char *full_name = talloc_strdup(tctx, name);
6876 char *p;
6878 if (name && name[0] == '\\' && name[1] == '\\') {
6879 name += 2;
6880 p = strchr(name, '\\');
6881 if (p) {
6882 return full_name;
6886 return NULL;
6889 static bool test_OnePrinter_servername(struct torture_context *tctx,
6890 struct dcerpc_pipe *p,
6891 struct dcerpc_binding_handle *b,
6892 const char *servername,
6893 const char *printername)
6895 union spoolss_PrinterInfo info;
6896 const char *short_name = get_short_printername(tctx, printername);
6897 const char *full_name = get_full_printername(tctx, printername);
6899 if (short_name) {
6900 struct policy_handle handle;
6901 torture_assert(tctx,
6902 call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
6903 "failed to open printer");
6905 torture_assert(tctx,
6906 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6907 "failed to get printer info");
6909 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
6910 "unexpected servername");
6911 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
6912 "unexpected printername");
6914 if (info.info2.devmode) {
6915 const char *expected_devicename;
6916 expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
6917 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6918 "unexpected devicemode devicename");
6921 torture_assert(tctx,
6922 test_ClosePrinter(tctx, b, &handle),
6923 "failed to close printer");
6926 if (full_name) {
6927 struct policy_handle handle;
6929 torture_assert(tctx,
6930 call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
6931 "failed to open printer");
6933 torture_assert(tctx,
6934 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6935 "failed to get printer info");
6937 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
6938 "unexpected servername");
6939 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
6940 "unexpected printername");
6942 if (info.info2.devmode) {
6943 const char *expected_devicename;
6944 expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
6945 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6946 "unexpected devicemode devicename");
6949 torture_assert(tctx,
6950 test_ClosePrinter(tctx, b, &handle),
6951 "failed to close printer");
6954 return true;
6957 static bool test_EnumPrinters_servername(struct torture_context *tctx,
6958 void *private_data)
6960 struct test_spoolss_context *ctx =
6961 talloc_get_type_abort(private_data, struct test_spoolss_context);
6962 int i;
6963 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6964 struct dcerpc_binding_handle *b = p->binding_handle;
6965 uint32_t count;
6966 union spoolss_PrinterInfo *info;
6967 const char *servername;
6968 uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
6970 torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6972 servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6974 torture_assert(tctx,
6975 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6976 "failed to enumerate printers");
6978 for (i=0; i < count; i++) {
6980 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
6981 "unexpected servername");
6983 torture_assert(tctx,
6984 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6985 "failed to check printer");
6988 servername = "";
6990 torture_assert(tctx,
6991 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6992 "failed to enumerate printers");
6994 for (i=0; i < count; i++) {
6996 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
6997 "unexpected servername");
6999 torture_assert(tctx,
7000 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
7001 "failed to check printer");
7005 return true;
7008 #if 0
7009 static bool test_GetPrinterDriver(struct torture_context *tctx,
7010 struct dcerpc_binding_handle *b,
7011 struct policy_handle *handle,
7012 const char *driver_name)
7014 struct spoolss_GetPrinterDriver r;
7015 uint32_t needed;
7017 r.in.handle = handle;
7018 r.in.architecture = "W32X86";
7019 r.in.level = 1;
7020 r.in.buffer = NULL;
7021 r.in.offered = 0;
7022 r.out.needed = &needed;
7024 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
7026 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
7027 "failed to call GetPrinterDriver");
7028 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
7029 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7030 r.in.buffer = &blob;
7031 r.in.offered = needed;
7032 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
7033 "failed to call GetPrinterDriver");
7036 torture_assert_werr_ok(tctx, r.out.result,
7037 "failed to call GetPrinterDriver");
7039 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
7041 return true;
7043 #endif
7045 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
7046 struct dcerpc_binding_handle *b,
7047 struct policy_handle *handle,
7048 const char *driver_name,
7049 const char *architecture,
7050 uint32_t level,
7051 uint32_t client_major_version,
7052 uint32_t client_minor_version,
7053 union spoolss_DriverInfo *info_p,
7054 WERROR *result_p)
7057 struct spoolss_GetPrinterDriver2 r;
7058 uint32_t needed;
7059 uint32_t server_major_version;
7060 uint32_t server_minor_version;
7062 r.in.handle = handle;
7063 r.in.architecture = architecture;
7064 r.in.client_major_version = client_major_version;
7065 r.in.client_minor_version = client_minor_version;
7066 r.in.buffer = NULL;
7067 r.in.offered = 0;
7068 r.in.level = level;
7069 r.out.needed = &needed;
7070 r.out.server_major_version = &server_major_version;
7071 r.out.server_minor_version = &server_minor_version;
7073 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
7074 driver_name, r.in.level);
7076 torture_assert_ntstatus_ok(tctx,
7077 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
7078 "failed to call GetPrinterDriver2");
7079 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
7080 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7081 r.in.buffer = &blob;
7082 r.in.offered = needed;
7083 torture_assert_ntstatus_ok(tctx,
7084 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
7085 "failed to call GetPrinterDriver2");
7088 if (result_p) {
7089 *result_p = r.out.result;
7092 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
7093 switch (r.in.level) {
7094 case 101:
7095 case 8:
7096 torture_comment(tctx,
7097 "level %d not implemented, not considering as an error\n",
7098 r.in.level);
7099 return true;
7100 default:
7101 break;
7105 torture_assert_werr_ok(tctx, r.out.result,
7106 "failed to call GetPrinterDriver2");
7108 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
7110 if (info_p) {
7111 *info_p = *r.out.info;
7114 return true;
7117 static bool test_GetPrinterDriver2(struct torture_context *tctx,
7118 struct dcerpc_binding_handle *b,
7119 struct policy_handle *handle,
7120 const char *driver_name,
7121 const char *architecture)
7123 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
7124 int i;
7127 for (i=0;i<ARRAY_SIZE(levels);i++) {
7129 torture_assert(tctx,
7130 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
7131 "");
7134 return true;
7137 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
7138 void *private_data)
7140 struct test_spoolss_context *ctx =
7141 talloc_get_type_abort(private_data, struct test_spoolss_context);
7142 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
7143 int i;
7144 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7145 struct dcerpc_binding_handle *b = p->binding_handle;
7146 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7148 for (i=0;i<ARRAY_SIZE(levels);i++) {
7150 uint32_t count;
7151 union spoolss_DriverInfo *info;
7153 torture_assert(tctx,
7154 test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
7155 "failed to enumerate drivers");
7157 if (!info) {
7158 torture_comment(tctx, "No printer drivers returned\n");
7159 break;
7163 return true;
7166 static bool test_DeletePrinter(struct torture_context *tctx,
7167 struct dcerpc_binding_handle *b,
7168 struct policy_handle *handle)
7170 struct spoolss_DeletePrinter r;
7172 torture_comment(tctx, "Testing DeletePrinter\n");
7174 r.in.handle = handle;
7176 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
7177 "failed to delete printer");
7178 torture_assert_werr_ok(tctx, r.out.result,
7179 "failed to delete printer");
7181 return true;
7184 static bool test_EnumPrinters_findname(struct torture_context *tctx,
7185 struct dcerpc_binding_handle *b,
7186 uint32_t flags,
7187 uint32_t level,
7188 const char *name,
7189 bool *found)
7191 struct spoolss_EnumPrinters e;
7192 uint32_t count;
7193 union spoolss_PrinterInfo *info;
7194 uint32_t needed;
7195 int i;
7197 *found = false;
7199 e.in.flags = flags;
7200 e.in.server = NULL;
7201 e.in.level = level;
7202 e.in.buffer = NULL;
7203 e.in.offered = 0;
7204 e.out.count = &count;
7205 e.out.info = &info;
7206 e.out.needed = &needed;
7208 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
7209 "failed to enum printers");
7211 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
7212 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7213 e.in.buffer = &blob;
7214 e.in.offered = needed;
7216 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
7217 "failed to enum printers");
7220 torture_assert_werr_ok(tctx, e.out.result,
7221 "failed to enum printers");
7223 for (i=0; i < count; i++) {
7225 const char *current = NULL;
7226 const char *q;
7228 switch (level) {
7229 case 1:
7230 current = info[i].info1.name;
7231 break;
7234 if (strequal(current, name)) {
7235 *found = true;
7236 break;
7239 q = strrchr(current, '\\');
7240 if (q) {
7241 if (!e.in.server) {
7242 torture_warning(tctx,
7243 "server returns printername %s incl. servername although we did not set servername", current);
7245 q++;
7246 if (strequal(q, name)) {
7247 *found = true;
7248 break;
7253 return true;
7256 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
7257 struct dcerpc_pipe *p,
7258 const char *printername,
7259 bool ex)
7261 WERROR result;
7262 struct spoolss_AddPrinter r;
7263 struct spoolss_AddPrinterEx rex;
7264 struct spoolss_SetPrinterInfoCtr info_ctr;
7265 struct spoolss_SetPrinterInfo1 info1;
7266 struct spoolss_DevmodeContainer devmode_ctr;
7267 struct sec_desc_buf secdesc_ctr;
7268 struct spoolss_UserLevelCtr userlevel_ctr;
7269 struct policy_handle handle;
7270 bool found = false;
7271 struct dcerpc_binding_handle *b = p->binding_handle;
7273 ZERO_STRUCT(devmode_ctr);
7274 ZERO_STRUCT(secdesc_ctr);
7275 ZERO_STRUCT(userlevel_ctr);
7276 ZERO_STRUCT(info1);
7278 torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
7279 ex ? "Ex":"", printername);
7281 /* try to add printer to wellknown printer list (level 1) */
7283 userlevel_ctr.level = 1;
7285 info_ctr.info.info1 = &info1;
7286 info_ctr.level = 1;
7288 rex.in.server = NULL;
7289 rex.in.info_ctr = &info_ctr;
7290 rex.in.devmode_ctr = &devmode_ctr;
7291 rex.in.secdesc_ctr = &secdesc_ctr;
7292 rex.in.userlevel_ctr = &userlevel_ctr;
7293 rex.out.handle = &handle;
7295 r.in.server = NULL;
7296 r.in.info_ctr = &info_ctr;
7297 r.in.devmode_ctr = &devmode_ctr;
7298 r.in.secdesc_ctr = &secdesc_ctr;
7299 r.out.handle = &handle;
7301 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7302 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7303 "failed to add printer");
7304 result = ex ? rex.out.result : r.out.result;
7305 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
7306 "unexpected result code");
7308 info1.name = printername;
7309 info1.flags = PRINTER_ATTRIBUTE_SHARED;
7311 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7312 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7313 "failed to add printer");
7314 result = ex ? rex.out.result : r.out.result;
7315 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7316 "unexpected result code");
7318 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7319 better do a real check to see the printer is really there */
7321 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7322 PRINTER_ENUM_NETWORK, 1,
7323 printername,
7324 &found),
7325 "failed to enum printers");
7327 torture_assert(tctx, found, "failed to find newly added printer");
7329 info1.flags = 0;
7331 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7332 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7333 "failed to add printer");
7334 result = ex ? rex.out.result : r.out.result;
7335 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7336 "unexpected result code");
7338 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7339 better do a real check to see the printer has really been removed
7340 from the well known printer list */
7342 found = false;
7344 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7345 PRINTER_ENUM_NETWORK, 1,
7346 printername,
7347 &found),
7348 "failed to enum printers");
7349 #if 0
7350 torture_assert(tctx, !found, "printer still in well known printer list");
7351 #endif
7352 return true;
7355 static bool test_AddPrinter_normal(struct torture_context *tctx,
7356 struct dcerpc_pipe *p,
7357 struct policy_handle *handle_p,
7358 const char *printername,
7359 const char *drivername,
7360 const char *portname,
7361 struct spoolss_DeviceMode *devmode,
7362 bool ex)
7364 WERROR result;
7365 struct spoolss_AddPrinter r;
7366 struct spoolss_AddPrinterEx rex;
7367 struct spoolss_SetPrinterInfoCtr info_ctr;
7368 struct spoolss_SetPrinterInfo2 info2;
7369 struct spoolss_DevmodeContainer devmode_ctr;
7370 struct sec_desc_buf secdesc_ctr;
7371 struct spoolss_UserLevelCtr userlevel_ctr;
7372 struct policy_handle handle;
7373 bool found = false;
7374 bool existing_printer_deleted = false;
7375 struct dcerpc_binding_handle *b = p->binding_handle;
7377 ZERO_STRUCT(devmode_ctr);
7378 ZERO_STRUCT(secdesc_ctr);
7379 ZERO_STRUCT(userlevel_ctr);
7381 torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
7382 ex ? "Ex":"", printername);
7384 devmode_ctr.devmode = devmode;
7386 userlevel_ctr.level = 1;
7388 rex.in.server = NULL;
7389 rex.in.info_ctr = &info_ctr;
7390 rex.in.devmode_ctr = &devmode_ctr;
7391 rex.in.secdesc_ctr = &secdesc_ctr;
7392 rex.in.userlevel_ctr = &userlevel_ctr;
7393 rex.out.handle = &handle;
7395 r.in.server = NULL;
7396 r.in.info_ctr = &info_ctr;
7397 r.in.devmode_ctr = &devmode_ctr;
7398 r.in.secdesc_ctr = &secdesc_ctr;
7399 r.out.handle = &handle;
7401 again:
7403 /* try to add printer to printer list (level 2) */
7405 ZERO_STRUCT(info2);
7407 info_ctr.info.info2 = &info2;
7408 info_ctr.level = 2;
7410 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7411 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7412 "failed to add printer");
7413 result = ex ? rex.out.result : r.out.result;
7414 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
7415 "unexpected result code");
7417 info2.printername = printername;
7419 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7420 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7421 "failed to add printer");
7422 result = ex ? rex.out.result : r.out.result;
7424 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
7425 struct policy_handle printer_handle;
7427 if (existing_printer_deleted) {
7428 torture_fail(tctx, "already deleted printer still existing?");
7431 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
7432 "failed to open printer handle");
7434 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
7435 "failed to delete printer");
7437 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
7438 "failed to close server handle");
7440 existing_printer_deleted = true;
7442 goto again;
7445 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
7446 "unexpected result code");
7448 info2.portname = portname;
7450 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7451 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7452 "failed to add printer");
7453 result = ex ? rex.out.result : r.out.result;
7454 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
7455 "unexpected result code");
7457 info2.drivername = drivername;
7459 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7460 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7461 "failed to add printer");
7462 result = ex ? rex.out.result : r.out.result;
7464 /* w2k8r2 allows to add printer w/o defining printprocessor */
7466 if (!W_ERROR_IS_OK(result)) {
7467 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
7468 "unexpected result code");
7470 info2.printprocessor = "winprint";
7472 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7473 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7474 "failed to add printer");
7475 result = ex ? rex.out.result : r.out.result;
7476 torture_assert_werr_ok(tctx, result,
7477 "failed to add printer");
7480 *handle_p = handle;
7482 /* we are paranoid, really check if the printer is there now */
7484 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7485 PRINTER_ENUM_LOCAL, 1,
7486 printername,
7487 &found),
7488 "failed to enum printers");
7489 torture_assert(tctx, found, "failed to find newly added printer");
7491 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7492 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7493 "failed to add printer");
7494 result = ex ? rex.out.result : r.out.result;
7495 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7496 "unexpected result code");
7498 return true;
7501 static bool test_printer_info(struct torture_context *tctx,
7502 void *private_data)
7504 struct torture_printer_context *t =
7505 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7506 struct dcerpc_pipe *p = t->spoolss_pipe;
7507 struct dcerpc_binding_handle *b = p->binding_handle;
7509 bool ret = true;
7511 if (torture_setting_bool(tctx, "samba3", false)) {
7512 torture_skip(tctx, "skipping printer info cross tests against samba 3");
7515 if (!test_PrinterInfo(tctx, b, &t->handle)) {
7516 ret = false;
7519 if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
7520 ret = false;
7523 return ret;
7526 static bool test_EnumPrinterKey(struct torture_context *tctx,
7527 struct dcerpc_binding_handle *b,
7528 struct policy_handle *handle,
7529 const char *key_name,
7530 const char ***array)
7532 struct spoolss_EnumPrinterKey r;
7533 uint32_t needed = 0;
7534 union spoolss_KeyNames key_buffer;
7535 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7536 uint32_t _ndr_size;
7537 int i;
7539 r.in.handle = handle;
7540 r.in.key_name = key_name;
7541 r.out.key_buffer = &key_buffer;
7542 r.out.needed = &needed;
7543 r.out._ndr_size = &_ndr_size;
7545 for (i=0; i < ARRAY_SIZE(offered); i++) {
7547 if (offered[i] < 0 && needed) {
7548 if (needed <= 4) {
7549 continue;
7551 r.in.offered = needed + offered[i];
7552 } else {
7553 r.in.offered = offered[i];
7556 ZERO_STRUCT(key_buffer);
7558 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
7560 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7561 "failed to call EnumPrinterKey");
7562 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
7564 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7565 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7566 _ndr_size, r.in.offered/2));
7568 r.in.offered = needed;
7569 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7570 "failed to call EnumPrinterKey");
7573 if (offered[i] > 0) {
7574 torture_assert_werr_ok(tctx, r.out.result,
7575 "failed to call EnumPrinterKey");
7578 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7579 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7580 _ndr_size, r.in.offered/2));
7582 torture_assert(tctx, (*r.out.needed <= r.in.offered),
7583 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
7585 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
7586 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
7588 if (key_buffer.string_array) {
7589 uint32_t calc_needed = 0;
7590 int s;
7591 for (s=0; key_buffer.string_array[s]; s++) {
7592 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7594 if (!key_buffer.string_array[0]) {
7595 calc_needed += 2;
7597 calc_needed += 2;
7599 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7600 "EnumPrinterKey unexpected size");
7604 if (array) {
7605 *array = key_buffer.string_array;
7608 return true;
7611 bool test_printer_all_keys(struct torture_context *tctx,
7612 struct dcerpc_binding_handle *b,
7613 struct policy_handle *handle)
7615 const char **key_array = NULL;
7616 int i;
7618 torture_comment(tctx, "Testing Printer Keys\n");
7620 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7621 "failed to call test_EnumPrinterKey");
7623 for (i=0; key_array && key_array[i]; i++) {
7624 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7625 "failed to call test_EnumPrinterKey");
7627 for (i=0; key_array && key_array[i]; i++) {
7628 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7629 "failed to call test_EnumPrinterDataEx");
7632 torture_comment(tctx, "Printer Keys test succeeded\n\n");
7634 return true;
7637 static bool test_openprinter_wrap(struct torture_context *tctx,
7638 void *private_data)
7640 struct torture_printer_context *t =
7641 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7642 struct dcerpc_pipe *p = t->spoolss_pipe;
7643 struct dcerpc_binding_handle *b = p->binding_handle;
7644 const char *printername = t->info2.printername;
7646 return test_openprinter(tctx, b, printername);
7649 static bool test_csetprinter(struct torture_context *tctx,
7650 void *private_data)
7652 struct torture_printer_context *t =
7653 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7654 struct dcerpc_pipe *p = t->spoolss_pipe;
7656 const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7657 const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7658 const char *portname = t->info2.portname;
7660 union spoolss_PrinterInfo info;
7661 struct policy_handle new_handle, new_handle2;
7662 struct dcerpc_binding_handle *b = p->binding_handle;
7664 torture_comment(tctx, "Testing c_setprinter\n");
7666 torture_assert(tctx,
7667 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7668 "failed to get level 0 printer info");
7669 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7670 info.info0.c_setprinter);
7672 /* check if c_setprinter on 1st handle increases after a printer has
7673 * been added */
7675 torture_assert(tctx,
7676 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7677 "failed to add new printer");
7678 torture_assert(tctx,
7679 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7680 "failed to get level 0 printer info");
7681 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7682 info.info0.c_setprinter);
7684 /* check if c_setprinter on new handle increases after a printer has
7685 * been added */
7687 torture_assert(tctx,
7688 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7689 "failed to get level 0 printer info");
7690 torture_comment(tctx, "csetprinter on created handle: %d\n",
7691 info.info0.c_setprinter);
7693 /* open the new printer and check if c_setprinter increases */
7695 torture_assert(tctx,
7696 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7697 "failed to open created printer");
7698 torture_assert(tctx,
7699 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
7700 "failed to get level 0 printer info");
7701 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
7702 info.info0.c_setprinter);
7704 /* cleanup */
7706 torture_assert(tctx,
7707 test_ClosePrinter(tctx, b, &new_handle2),
7708 "failed to close printer");
7709 torture_assert(tctx,
7710 test_DeletePrinter(tctx, b, &new_handle),
7711 "failed to delete new printer");
7713 return true;
7716 static bool compose_local_driver_directory(struct torture_context *tctx,
7717 const char *environment,
7718 const char *local_dir,
7719 const char **path)
7721 char *p;
7723 p = strrchr(local_dir, '/');
7724 if (!p) {
7725 return NULL;
7727 p++;
7729 if (strequal(environment, "Windows x64")) {
7730 if (!strequal(p, "x64")) {
7731 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
7733 } else if (strequal(environment, "Windows NT x86")) {
7734 if (!strequal(p, "i386")) {
7735 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
7737 } else {
7738 torture_assert(tctx, "unknown environment: '%s'\n", environment);
7741 return true;
7744 #if 0
7745 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
7746 const char *devicename)
7748 struct spoolss_DeviceMode *r;
7750 r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
7751 if (r == NULL) {
7752 return NULL;
7755 r->devicename = talloc_strdup(r, devicename);
7756 r->specversion = DMSPEC_NT4_AND_ABOVE;
7757 r->driverversion = 0x0600;
7758 r->size = 0x00dc;
7759 r->__driverextra_length = 0;
7760 r->fields = DEVMODE_FORMNAME |
7761 DEVMODE_TTOPTION |
7762 DEVMODE_PRINTQUALITY |
7763 DEVMODE_DEFAULTSOURCE |
7764 DEVMODE_COPIES |
7765 DEVMODE_SCALE |
7766 DEVMODE_PAPERSIZE |
7767 DEVMODE_ORIENTATION;
7768 r->orientation = DMORIENT_PORTRAIT;
7769 r->papersize = DMPAPER_LETTER;
7770 r->paperlength = 0;
7771 r->paperwidth = 0;
7772 r->scale = 100;
7773 r->copies = 55;
7774 r->defaultsource = DMBIN_FORMSOURCE;
7775 r->printquality = DMRES_HIGH;
7776 r->color = DMRES_MONOCHROME;
7777 r->duplex = DMDUP_SIMPLEX;
7778 r->yresolution = 0;
7779 r->ttoption = DMTT_SUBDEV;
7780 r->collate = DMCOLLATE_FALSE;
7781 r->formname = talloc_strdup(r, "Letter");
7783 return r;
7785 #endif
7787 static bool test_architecture_buffer(struct torture_context *tctx,
7788 void *private_data)
7790 struct test_spoolss_context *ctx =
7791 talloc_get_type_abort(private_data, struct test_spoolss_context);
7793 struct spoolss_OpenPrinterEx r;
7794 struct spoolss_UserLevel1 u1;
7795 struct policy_handle handle;
7796 uint32_t architectures[] = {
7797 PROCESSOR_ARCHITECTURE_INTEL,
7798 PROCESSOR_ARCHITECTURE_IA64,
7799 PROCESSOR_ARCHITECTURE_AMD64
7801 uint32_t needed[3];
7802 int i;
7803 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7804 struct dcerpc_binding_handle *b = p->binding_handle;
7806 for (i=0; i < ARRAY_SIZE(architectures); i++) {
7808 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7810 u1.size = 0;
7811 u1.client = NULL;
7812 u1.user = NULL;
7813 u1.build = 0;
7814 u1.major = 3;
7815 u1.minor = 0;
7816 u1.processor = architectures[i];
7818 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7819 r.in.datatype = NULL;
7820 r.in.devmode_ctr.devmode= NULL;
7821 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7822 r.in.userlevel_ctr.level = 1;
7823 r.in.userlevel_ctr.user_info.level1 = &u1;
7824 r.out.handle = &handle;
7826 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7827 torture_assert_werr_ok(tctx, r.out.result, "");
7830 struct spoolss_EnumPrinters e;
7831 uint32_t count;
7832 union spoolss_PrinterInfo *info;
7834 e.in.flags = PRINTER_ENUM_LOCAL;
7835 e.in.server = NULL;
7836 e.in.level = 2;
7837 e.in.buffer = NULL;
7838 e.in.offered = 0;
7839 e.out.count = &count;
7840 e.out.info = &info;
7841 e.out.needed = &needed[i];
7843 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7844 #if 0
7845 torture_comment(tctx, "needed was %d\n", needed[i]);
7846 #endif
7849 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7852 for (i=1; i < ARRAY_SIZE(architectures); i++) {
7853 if (needed[i-1] != needed[i]) {
7854 torture_fail(tctx,
7855 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7856 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7860 return true;
7863 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
7864 void *private_data)
7866 struct test_spoolss_context *ctx =
7867 talloc_get_type_abort(private_data, struct test_spoolss_context);
7868 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7869 struct dcerpc_binding_handle *b = p->binding_handle;
7871 return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
7874 static bool test_PrintServer_Forms(struct torture_context *tctx,
7875 void *private_data)
7877 struct test_spoolss_context *ctx =
7878 talloc_get_type_abort(private_data, struct test_spoolss_context);
7879 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7880 struct dcerpc_binding_handle *b = p->binding_handle;
7882 return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
7885 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
7886 void *private_data)
7888 struct test_spoolss_context *ctx =
7889 talloc_get_type_abort(private_data, struct test_spoolss_context);
7890 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7891 struct dcerpc_binding_handle *b = p->binding_handle;
7893 return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
7896 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
7898 NTSTATUS status;
7900 status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
7902 torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
7904 torture_assert(tctx,
7905 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
7906 "failed to open printserver");
7907 torture_assert(tctx,
7908 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
7909 "failed to get environment");
7911 return true;
7914 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
7916 struct test_spoolss_context *t;
7918 *data = t = talloc_zero(tctx, struct test_spoolss_context);
7920 return torture_rpc_spoolss_setup_common(tctx, t);
7923 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
7925 test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
7927 return true;
7930 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
7932 struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
7933 bool ret;
7935 ret = torture_rpc_spoolss_teardown_common(tctx, t);
7936 talloc_free(t);
7938 return ret;
7941 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
7943 struct dcerpc_pipe *p;
7944 struct dcerpc_binding_handle *b;
7945 const char *server_name_slash;
7946 const char *driver_name;
7947 const char *printer_name;
7948 const char *port_name;
7950 torture_assert_ntstatus_ok(tctx,
7951 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
7952 "Error connecting to server");
7954 p = t->spoolss_pipe;
7955 b = p->binding_handle;
7956 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7958 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
7959 t->driver.info8.driver_name = TORTURE_DRIVER;
7960 t->driver.info8.driver_path = "pscript5.dll";
7961 t->driver.info8.data_file = "cups6.ppd";
7962 t->driver.info8.config_file = "ps5ui.dll";
7963 t->driver.info8.help_file = "pscript.hlp";
7964 t->driver.info8.default_datatype = "RAW";
7965 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
7966 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
7967 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
7968 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
7969 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
7970 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
7971 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
7972 t->driver.info8.dependent_files->string[5] = "cups6.ini";
7973 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
7974 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
7976 t->driver.local.driver_directory= "/usr/share/cups/drivers";
7978 t->info2.portname = "LPT1:";
7980 printer_name = t->info2.printername;
7981 port_name = t->info2.portname;
7983 torture_assert(tctx,
7984 fillup_printserver_info(tctx, p, &t->driver),
7985 "failed to fillup printserver info");
7987 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
7989 torture_assert(tctx,
7990 compose_local_driver_directory(tctx, t->driver.remote.environment,
7991 t->driver.local.driver_directory,
7992 &t->driver.local.driver_directory),
7993 "failed to compose local driver directory");
7995 t->info2.drivername = "Microsoft XPS Document Writer";
7997 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7998 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7999 t->info2.drivername, t->driver.remote.environment);
8000 t->have_driver = true;
8001 goto try_add;
8004 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
8005 t->info2.drivername, t->driver.remote.environment);
8007 t->info2.drivername = "Microsoft XPS Document Writer v4";
8009 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
8010 torture_comment(tctx, "driver '%s' (architecture: %s, version: 4) is present on server\n",
8011 t->info2.drivername, t->driver.remote.environment);
8012 t->have_driver = true;
8013 goto try_add;
8016 torture_comment(tctx, "trying to upload own driver\n");
8018 if (!directory_exist(t->driver.local.driver_directory)) {
8019 torture_warning(tctx, "no local driver is available!");
8020 t->have_driver = false;
8021 goto try_add;
8024 torture_assert(tctx,
8025 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
8026 "failed to upload printer driver");
8028 torture_assert(tctx,
8029 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
8030 "failed to add driver");
8032 t->added_driver = true;
8033 t->have_driver = true;
8035 try_add:
8036 driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
8038 if (t->wellknown) {
8039 torture_assert(tctx,
8040 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
8041 "failed to add wellknown printer");
8042 } else {
8043 torture_assert(tctx,
8044 test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
8045 "failed to add printer");
8048 return true;
8051 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
8053 struct torture_printer_context *t;
8055 *data = t = talloc_zero(tctx, struct torture_printer_context);
8057 t->ex = false;
8058 t->wellknown = false;
8059 t->info2.printername = TORTURE_PRINTER;
8060 t->devmode = NULL;
8062 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8065 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
8067 struct torture_printer_context *t;
8069 *data = t = talloc_zero(tctx, struct torture_printer_context);
8071 t->ex = true;
8072 t->wellknown = false;
8073 t->info2.printername = TORTURE_PRINTER_EX;
8074 t->devmode = NULL;
8076 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8079 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
8081 struct torture_printer_context *t;
8083 *data = t = talloc_zero(tctx, struct torture_printer_context);
8085 t->ex = false;
8086 t->wellknown = true;
8087 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
8088 t->devmode = NULL;
8090 /* FIXME */
8091 if (t->wellknown) {
8092 torture_skip(tctx, "skipping AddPrinter level 1");
8095 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8098 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
8100 struct torture_printer_context *t;
8102 *data = t = talloc_zero(tctx, struct torture_printer_context);
8104 t->ex = true;
8105 t->wellknown = true;
8106 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
8107 t->devmode = NULL;
8109 /* FIXME */
8110 if (t->wellknown) {
8111 torture_skip(tctx, "skipping AddPrinterEx level 1");
8114 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8117 #if 0
8118 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
8120 struct torture_printer_context *t;
8122 *data = t = talloc_zero(tctx, struct torture_printer_context);
8124 t->ex = true;
8125 t->wellknown = false;
8126 t->info2.printername = TORTURE_PRINTER_EX;
8127 t->devmode = torture_devicemode(t, TORTURE_PRINTER_EX);
8129 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8131 #endif
8133 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
8135 bool found = false;
8136 struct dcerpc_pipe *p = t->spoolss_pipe;
8137 struct dcerpc_binding_handle *b;
8138 const char *printer_name = t->info2.printername;
8140 if (t->added_driver) {
8141 torture_assert(tctx,
8142 remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
8143 "failed to remove printer driver");
8146 if (p && !t->wellknown) {
8147 b = p->binding_handle;
8149 torture_assert(tctx,
8150 test_DeletePrinter(tctx, b, &t->handle),
8151 "failed to delete printer");
8153 torture_assert(tctx,
8154 test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
8155 printer_name, &found),
8156 "failed to enumerate printers");
8158 torture_assert(tctx, !found, "deleted printer still there");
8161 return true;
8164 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
8166 struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
8167 bool ret;
8169 ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
8170 talloc_free(t);
8172 return ret;
8175 static bool test_print_test(struct torture_context *tctx,
8176 void *private_data)
8178 struct torture_printer_context *t =
8179 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8180 struct dcerpc_pipe *p = t->spoolss_pipe;
8181 struct dcerpc_binding_handle *b = p->binding_handle;
8183 torture_assert(tctx,
8184 test_PausePrinter(tctx, b, &t->handle),
8185 "failed to pause printer");
8187 torture_assert(tctx,
8188 test_DoPrintTest(tctx, b, &t->handle),
8189 "failed to do print test");
8191 torture_assert(tctx,
8192 test_ResumePrinter(tctx, b, &t->handle),
8193 "failed to resume printer");
8195 return true;
8198 static bool test_print_test_extended(struct torture_context *tctx,
8199 void *private_data)
8201 struct torture_printer_context *t =
8202 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8203 struct dcerpc_pipe *p = t->spoolss_pipe;
8204 struct dcerpc_binding_handle *b = p->binding_handle;
8205 bool ret = true;
8207 torture_assert(tctx,
8208 test_PausePrinter(tctx, b, &t->handle),
8209 "failed to pause printer");
8211 ret = test_DoPrintTest_extended(tctx, b, &t->handle);
8212 if (ret == false) {
8213 torture_comment(tctx, "WARNING! failed to do extended print test\n");
8214 if (torture_setting_bool(tctx, "samba3", false)) {
8215 torture_comment(tctx, "non-critical for samba3\n");
8216 ret = true;
8217 tctx->last_result = TORTURE_SKIP;
8221 torture_assert(tctx,
8222 test_ResumePrinter(tctx, b, &t->handle),
8223 "failed to resume printer");
8225 return ret;
8228 static bool test_print_test_properties(struct torture_context *tctx,
8229 void *private_data)
8231 struct torture_printer_context *t =
8232 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8233 struct dcerpc_pipe *p = t->spoolss_pipe;
8234 struct dcerpc_binding_handle *b = p->binding_handle;
8236 if (torture_setting_bool(tctx, "samba3", false)) {
8237 torture_skip(tctx, "skip printer job property tests against samba");
8240 torture_assert(tctx,
8241 test_PausePrinter(tctx, b, &t->handle),
8242 "failed to pause printer");
8244 torture_assert(tctx,
8245 test_DoPrintTest_properties(tctx, b, &t->handle),
8246 "failed to test print job properties");
8248 torture_assert(tctx,
8249 test_ResumePrinter(tctx, b, &t->handle),
8250 "failed to resume printer");
8252 return true;
8255 /* use smbd file IO to spool a print job */
8256 static bool test_print_test_smbd(struct torture_context *tctx,
8257 void *private_data)
8259 struct torture_printer_context *t =
8260 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8261 struct dcerpc_pipe *p = t->spoolss_pipe;
8262 struct dcerpc_binding_handle *b = p->binding_handle;
8263 NTSTATUS status;
8264 uint32_t count;
8265 union spoolss_JobInfo *info = NULL;
8266 int i;
8268 struct smb2_tree *tree;
8269 struct smb2_handle job_h;
8270 struct cli_credentials *credentials = cmdline_credentials;
8271 struct smbcli_options options;
8272 TALLOC_CTX *mem_ctx = talloc_new(tctx);
8274 * Do not test against the dynamically added printers, printing via
8275 * smbd means that a different spoolss process may handle the
8276 * OpenPrinter request to the one that handled the AddPrinter request.
8277 * This currently leads to an ugly race condition where one process
8278 * sees the new printer and one doesn't.
8280 const char *share = TORTURE_PRINTER_STATIC1;
8282 torture_comment(tctx, "Testing smbd job spooling\n");
8283 lpcfg_smbcli_options(tctx->lp_ctx, &options);
8285 status = smb2_connect(mem_ctx,
8286 torture_setting_string(tctx, "host", NULL),
8287 lpcfg_smb_ports(tctx->lp_ctx),
8288 share,
8289 lpcfg_resolve_context(tctx->lp_ctx),
8290 credentials,
8291 &tree,
8292 tctx->ev,
8293 &options,
8294 lpcfg_socket_options(tctx->lp_ctx),
8295 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
8296 if (!NT_STATUS_IS_OK(status)) {
8297 printf("Failed to connect to SMB2 printer %s - %s\n",
8298 share, nt_errstr(status));
8299 return false;
8302 status = torture_smb2_testfile(tree, "smbd_spooler_job", &job_h);
8303 torture_assert_ntstatus_ok(tctx, status, "smbd spool job create");
8305 status = smb2_util_write(tree, job_h, "exciting print job data", 0,
8306 sizeof("exciting print job data"));
8307 torture_assert_ntstatus_ok(tctx, status, "smbd spool job write");
8309 /* check back end spoolss job was created */
8310 torture_assert(tctx,
8311 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
8312 &count, &info),
8313 "EnumJobs level 1 failed");
8315 for (i = 0; i < count; i++) {
8316 if (!strcmp(info[i].info1.document_name, "smbd_spooler_job")) {
8317 break;
8320 torture_assert(tctx, (i != count), "smbd_spooler_job not found");
8322 status = smb2_util_close(tree, job_h);
8323 torture_assert_ntstatus_ok(tctx, status, "smbd spool job close");
8325 /* disconnect from printer share */
8326 talloc_free(mem_ctx);
8328 return true;
8331 static bool test_print_test_purge(struct torture_context *tctx,
8332 void *private_data)
8334 struct torture_printer_context *t =
8335 (struct torture_printer_context *)talloc_get_type_abort(private_data,
8336 struct torture_printer_context);
8337 struct dcerpc_pipe *p = t->spoolss_pipe;
8338 struct dcerpc_binding_handle *b = p->binding_handle;
8339 uint32_t num_jobs = 8;
8340 uint32_t *job_ids;
8341 int i;
8342 bool ret = true;
8343 uint32_t count;
8344 union spoolss_JobInfo *info;
8346 torture_assert(tctx,
8347 test_PausePrinter(tctx, b, &t->handle),
8348 "failed to pause printer");
8350 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
8351 for (i=0; i < num_jobs; i++) {
8352 ret = test_DoPrintTest_add_one_job(tctx, b, &t->handle,
8353 "TorturePrintJob",
8354 &job_ids[i]);
8355 torture_assert(tctx, ret, "failed to add print job");
8358 torture_assert(tctx,
8359 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
8360 &count, &info),
8361 "EnumJobs level 1 failed");
8363 torture_assert_int_equal(tctx, count, num_jobs,
8364 "unexpected number of jobs in queue");
8366 torture_assert(tctx,
8367 test_printer_purge(tctx, b, &t->handle),
8368 "failed to purge printer");
8370 torture_assert(tctx,
8371 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
8372 &count, &info),
8373 "EnumJobs level 1 failed");
8375 torture_assert_int_equal(tctx, count, 0,
8376 "unexpected number of jobs in queue");
8378 torture_assert(tctx,
8379 test_ResumePrinter(tctx, b, &t->handle),
8380 "failed to resume printer");
8382 return true;
8385 static bool test_printer_sd(struct torture_context *tctx,
8386 void *private_data)
8388 struct torture_printer_context *t =
8389 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8390 struct dcerpc_pipe *p = t->spoolss_pipe;
8391 struct dcerpc_binding_handle *b = p->binding_handle;
8393 torture_assert(tctx,
8394 test_PrinterInfo_SD(tctx, b, &t->handle),
8395 "failed to test security descriptors");
8397 return true;
8400 static bool test_printer_dm(struct torture_context *tctx,
8401 void *private_data)
8403 struct torture_printer_context *t =
8404 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8405 struct dcerpc_pipe *p = t->spoolss_pipe;
8407 torture_assert(tctx,
8408 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
8409 "failed to test devicemodes");
8411 return true;
8414 static bool test_printer_info_winreg(struct torture_context *tctx,
8415 void *private_data)
8417 struct torture_printer_context *t =
8418 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8419 struct dcerpc_pipe *p = t->spoolss_pipe;
8421 torture_assert(tctx,
8422 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
8423 "failed to test printer info winreg");
8425 return true;
8428 static bool test_printer_change_id(struct torture_context *tctx,
8429 void *private_data)
8431 struct torture_printer_context *t =
8432 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8433 struct dcerpc_pipe *p = t->spoolss_pipe;
8435 torture_assert(tctx,
8436 test_ChangeID(tctx, p, &t->handle),
8437 "failed to test change id");
8439 return true;
8442 static bool test_printer_keys(struct torture_context *tctx,
8443 void *private_data)
8445 struct torture_printer_context *t =
8446 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8447 struct dcerpc_pipe *p = t->spoolss_pipe;
8448 struct dcerpc_binding_handle *b = p->binding_handle;
8450 torture_assert(tctx,
8451 test_printer_all_keys(tctx, b, &t->handle),
8452 "failed to test printer keys");
8454 return true;
8457 static bool test_printer_data_consistency(struct torture_context *tctx,
8458 void *private_data)
8460 struct torture_printer_context *t =
8461 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8462 struct dcerpc_pipe *p = t->spoolss_pipe;
8464 torture_assert(tctx,
8465 test_EnumPrinterData_consistency(tctx, p, &t->handle),
8466 "failed to test printer data consistency");
8468 return true;
8471 static bool test_printer_data_keys(struct torture_context *tctx,
8472 void *private_data)
8474 struct torture_printer_context *t =
8475 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8476 struct dcerpc_pipe *p = t->spoolss_pipe;
8478 torture_assert(tctx,
8479 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
8480 "failed to test printer data keys");
8482 return true;
8485 static bool test_printer_data_values(struct torture_context *tctx,
8486 void *private_data)
8488 struct torture_printer_context *t =
8489 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8490 struct dcerpc_pipe *p = t->spoolss_pipe;
8492 torture_assert(tctx,
8493 test_SetPrinterDataEx_values(tctx, p, &t->handle),
8494 "failed to test printer data values");
8496 return true;
8499 static bool test_printer_data_set(struct torture_context *tctx,
8500 void *private_data)
8502 struct torture_printer_context *t =
8503 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8504 struct dcerpc_pipe *p = t->spoolss_pipe;
8506 torture_assert(tctx,
8507 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
8508 "failed to test printer data set");
8510 return true;
8513 static bool test_printer_data_winreg(struct torture_context *tctx,
8514 void *private_data)
8516 struct torture_printer_context *t =
8517 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8518 struct dcerpc_pipe *p = t->spoolss_pipe;
8520 torture_assert(tctx,
8521 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
8522 "failed to test printer data winreg");
8524 return true;
8527 static bool test_printer_data_dsspooler(struct torture_context *tctx,
8528 void *private_data)
8530 struct torture_printer_context *t =
8531 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8532 struct dcerpc_pipe *p = t->spoolss_pipe;
8534 torture_assert(tctx,
8535 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
8536 "failed to test printer data winreg dsspooler");
8538 return true;
8541 static bool test_printer_ic(struct torture_context *tctx,
8542 void *private_data)
8544 struct torture_printer_context *t =
8545 talloc_get_type_abort(private_data,
8546 struct torture_printer_context);
8547 struct dcerpc_pipe *p = t->spoolss_pipe;
8548 struct dcerpc_binding_handle *b = p->binding_handle;
8549 struct policy_handle gdi_handle;
8551 if (torture_setting_bool(tctx, "samba3", false)) {
8552 torture_skip(tctx, "skip printer information context tests against samba");
8556 struct spoolss_CreatePrinterIC r;
8557 struct spoolss_DevmodeContainer devmode_ctr;
8559 ZERO_STRUCT(devmode_ctr);
8561 r.in.handle = &t->handle;
8562 r.in.devmode_ctr = &devmode_ctr;
8563 r.out.gdi_handle = &gdi_handle;
8565 torture_assert_ntstatus_ok(tctx,
8566 dcerpc_spoolss_CreatePrinterIC_r(b, tctx, &r),
8567 "CreatePrinterIC failed");
8568 torture_assert_werr_ok(tctx, r.out.result,
8569 "CreatePrinterIC failed");
8573 struct spoolss_PlayGDIScriptOnPrinterIC r;
8574 DATA_BLOB in,out;
8575 int i;
8576 uint32_t num_fonts = 0;
8578 in = data_blob_string_const("");
8580 r.in.gdi_handle = &gdi_handle;
8581 r.in.pIn = in.data;
8582 r.in.cIn = in.length;
8583 r.in.ul = 0;
8585 for (i = 0; i < 4; i++) {
8587 out = data_blob_talloc_zero(tctx, i);
8589 r.in.cOut = out.length;
8590 r.out.pOut = out.data;
8592 torture_assert_ntstatus_ok(tctx,
8593 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8594 "PlayGDIScriptOnPrinterIC failed");
8595 torture_assert_werr_equal(tctx, r.out.result, WERR_NOMEM,
8596 "PlayGDIScriptOnPrinterIC failed");
8599 out = data_blob_talloc_zero(tctx, 4);
8601 r.in.cOut = out.length;
8602 r.out.pOut = out.data;
8604 torture_assert_ntstatus_ok(tctx,
8605 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8606 "PlayGDIScriptOnPrinterIC failed");
8607 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
8608 "PlayGDIScriptOnPrinterIC failed");
8610 /* now we should have the required length, so retry with a
8611 * buffer which is large enough to carry all font ids */
8613 num_fonts = IVAL(r.out.pOut, 0);
8615 torture_comment(tctx, "PlayGDIScriptOnPrinterIC gave font count of %d\n", num_fonts);
8617 out = data_blob_talloc_zero(tctx,
8618 num_fonts * sizeof(struct UNIVERSAL_FONT_ID) + 4);
8620 r.in.cOut = out.length;
8621 r.out.pOut = out.data;
8623 torture_assert_ntstatus_ok(tctx,
8624 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8625 "PlayGDIScriptOnPrinterIC failed");
8626 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
8627 "PlayGDIScriptOnPrinterIC failed");
8632 struct spoolss_DeletePrinterIC r;
8634 r.in.gdi_handle = &gdi_handle;
8635 r.out.gdi_handle = &gdi_handle;
8637 torture_assert_ntstatus_ok(tctx,
8638 dcerpc_spoolss_DeletePrinterIC_r(b, tctx, &r),
8639 "DeletePrinterIC failed");
8640 torture_assert_werr_ok(tctx, r.out.result,
8641 "DeletePrinterIC failed");
8645 return true;
8648 static bool test_printer_bidi(struct torture_context *tctx,
8649 void *private_data)
8651 struct torture_printer_context *t =
8652 talloc_get_type_abort(private_data,
8653 struct torture_printer_context);
8654 struct dcerpc_pipe *p = t->spoolss_pipe;
8655 struct dcerpc_binding_handle *b = p->binding_handle;
8656 struct spoolss_RpcSendRecvBidiData r;
8657 struct RPC_BIDI_REQUEST_CONTAINER bidi_req;
8658 struct RPC_BIDI_RESPONSE_CONTAINER *bidi_rep = NULL;
8660 if (torture_setting_bool(tctx, "samba3", false)) {
8661 torture_skip(tctx, "skip printer bidirectional tests against samba");
8664 ZERO_STRUCT(bidi_req);
8666 r.in.hPrinter = t->handle;
8667 r.in.pAction = "foobar";
8668 r.in.pReqData = &bidi_req;
8669 r.out.ppRespData = &bidi_rep;
8671 torture_assert_ntstatus_ok(tctx,
8672 dcerpc_spoolss_RpcSendRecvBidiData_r(b, tctx, &r),
8673 "RpcSendRecvBidiData failed");
8674 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
8675 "RpcSendRecvBidiData failed");
8677 if (!(t->info2.attributes & PRINTER_ATTRIBUTE_ENABLE_BIDI)) {
8678 torture_skip(tctx, "skipping further tests as printer is not BIDI enabled");
8681 r.in.pAction = BIDI_ACTION_ENUM_SCHEMA;
8683 torture_assert_ntstatus_ok(tctx,
8684 dcerpc_spoolss_RpcSendRecvBidiData_r(b, tctx, &r),
8685 "RpcSendRecvBidiData failed");
8686 torture_assert_werr_ok(tctx, r.out.result,
8687 "RpcSendRecvBidiData failed");
8689 return true;
8692 static bool test_printer_set_publish(struct torture_context *tctx,
8693 struct dcerpc_binding_handle *b,
8694 struct policy_handle *handle)
8696 union spoolss_PrinterInfo info;
8697 struct spoolss_SetPrinterInfo7 info7;
8698 struct spoolss_SetPrinterInfoCtr info_ctr;
8699 struct spoolss_DevmodeContainer devmode_ctr;
8700 struct sec_desc_buf secdesc_ctr;
8702 info7.guid = "";
8703 info7.action = DSPRINT_PUBLISH;
8705 ZERO_STRUCT(info_ctr);
8706 ZERO_STRUCT(devmode_ctr);
8707 ZERO_STRUCT(secdesc_ctr);
8708 info_ctr.level = 7;
8709 info_ctr.info.info7 = &info7;
8711 torture_assert(tctx,
8712 test_SetPrinter(tctx, b, handle, &info_ctr,
8713 &devmode_ctr, &secdesc_ctr, 0), "");
8715 torture_assert(tctx,
8716 test_GetPrinter_level(tctx, b, handle, 2, &info),
8717 "");
8718 torture_assert(tctx,
8719 (info.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED),
8720 "info2 publish flag not set");
8721 torture_assert(tctx,
8722 test_GetPrinter_level(tctx, b, handle, 7, &info),
8723 "");
8724 if (info.info7.action & DSPRINT_PENDING) {
8725 torture_comment(tctx, "publish is pending\n");
8726 torture_assert_int_equal(tctx,
8727 info.info7.action,
8728 (DSPRINT_PENDING | DSPRINT_PUBLISH),
8729 "info7 publish flag not set");
8730 } else {
8731 struct GUID guid;
8732 torture_assert_int_equal(tctx,
8733 info.info7.action,
8734 DSPRINT_PUBLISH,
8735 "info7 publish flag not set");
8736 torture_assert_ntstatus_ok(tctx,
8737 GUID_from_string(info.info7.guid,
8738 &guid),
8739 "invalid published printer GUID");
8742 return true;
8745 static bool test_printer_set_unpublish(struct torture_context *tctx,
8746 struct dcerpc_binding_handle *b,
8747 struct policy_handle *handle)
8749 union spoolss_PrinterInfo info;
8750 struct spoolss_SetPrinterInfo7 info7;
8751 struct spoolss_SetPrinterInfoCtr info_ctr;
8752 struct spoolss_DevmodeContainer devmode_ctr;
8753 struct sec_desc_buf secdesc_ctr;
8755 info7.action = DSPRINT_UNPUBLISH;
8756 info7.guid = "";
8758 ZERO_STRUCT(info_ctr);
8759 ZERO_STRUCT(devmode_ctr);
8760 ZERO_STRUCT(secdesc_ctr);
8761 info_ctr.level = 7;
8762 info_ctr.info.info7 = &info7;
8764 torture_assert(tctx,
8765 test_SetPrinter(tctx, b, handle, &info_ctr,
8766 &devmode_ctr, &secdesc_ctr, 0), "");
8768 torture_assert(tctx,
8769 test_GetPrinter_level(tctx, b, handle, 2, &info),
8770 "");
8771 torture_assert(tctx,
8772 !(info.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED),
8773 "info2 publish flag still set");
8774 torture_assert(tctx,
8775 test_GetPrinter_level(tctx, b, handle, 7, &info),
8776 "");
8778 if (info.info7.action & DSPRINT_PENDING) {
8779 struct GUID guid;
8780 torture_comment(tctx, "unpublish is pending\n");
8781 torture_assert_int_equal(tctx,
8782 info.info7.action,
8783 (DSPRINT_PENDING | DSPRINT_UNPUBLISH),
8784 "info7 unpublish flag not set");
8785 torture_assert_ntstatus_ok(tctx,
8786 GUID_from_string(info.info7.guid,
8787 &guid),
8788 "invalid printer GUID");
8789 } else {
8790 torture_assert_int_equal(tctx,
8791 info.info7.action, DSPRINT_UNPUBLISH,
8792 "info7 unpublish flag not set");
8795 return true;
8798 static bool test_printer_publish_toggle(struct torture_context *tctx,
8799 void *private_data)
8801 struct torture_printer_context *t =
8802 talloc_get_type_abort(private_data,
8803 struct torture_printer_context);
8804 struct dcerpc_pipe *p = t->spoolss_pipe;
8805 struct dcerpc_binding_handle *b = p->binding_handle;
8806 struct policy_handle *handle = &t->handle;
8807 union spoolss_PrinterInfo info7;
8808 union spoolss_PrinterInfo info2;
8810 /* check publish status via level 7 and level 2 */
8811 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 7, &info7),
8812 "");
8813 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info2),
8814 "");
8816 if (info2.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
8817 torture_assert_int_equal(tctx,
8818 info7.info7.action, DSPRINT_PUBLISH,
8819 "info7 publish flag not set");
8820 torture_assert(tctx, test_printer_set_unpublish(tctx, b, handle), "");
8821 torture_assert(tctx, test_printer_set_publish(tctx, b, handle), "");
8822 } else {
8823 torture_assert_int_equal(tctx,
8824 info7.info7.action, DSPRINT_UNPUBLISH,
8825 "info7 unpublish flag not set");
8826 torture_assert(tctx, test_printer_set_publish(tctx, b, handle), "");
8827 torture_assert(tctx, test_printer_set_unpublish(tctx, b, handle), "");
8830 return true;
8833 static bool test_driver_info_winreg(struct torture_context *tctx,
8834 void *private_data)
8836 struct torture_printer_context *t =
8837 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8838 struct dcerpc_pipe *p = t->spoolss_pipe;
8839 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
8841 if (!t->have_driver) {
8842 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
8845 torture_assert(tctx,
8846 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
8847 "failed to test driver info winreg");
8849 return true;
8852 static bool test_print_job_enum(struct torture_context *tctx,
8853 void *private_data)
8855 struct torture_printer_context *t =
8856 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8857 struct dcerpc_pipe *p = t->spoolss_pipe;
8858 struct dcerpc_binding_handle *b = p->binding_handle;
8859 bool ret = true;
8860 uint32_t num_jobs = 8;
8861 uint32_t *job_ids;
8862 int i;
8863 union spoolss_JobInfo *info = NULL;
8864 uint32_t count;
8866 torture_assert(tctx,
8867 test_PausePrinter(tctx, b, &t->handle),
8868 "failed to pause printer");
8870 /* purge in case of any jobs from previous tests */
8871 torture_assert(tctx,
8872 test_printer_purge(tctx, b, &t->handle),
8873 "failed to purge printer");
8875 /* enum before jobs, valid level */
8876 torture_assert(tctx,
8877 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
8878 &count, &info),
8879 "EnumJobs with valid level");
8880 torture_assert_int_equal(tctx, count, 0, "EnumJobs count");
8881 torture_assert(tctx,
8882 test_EnumJobs_args(tctx, b, &t->handle, 2, WERR_OK,
8883 &count, &info),
8884 "EnumJobs with valid level");
8885 torture_assert_int_equal(tctx, count, 0, "EnumJobs count");
8886 /* enum before jobs, invalid level - expect failure */
8887 torture_assert(tctx,
8888 test_EnumJobs_args(tctx, b, &t->handle, 100,
8889 WERR_INVALID_LEVEL,
8890 &count, &info),
8891 "EnumJobs with invalid level");
8893 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
8895 for (i = 0; i < num_jobs; i++) {
8896 ret = test_DoPrintTest_add_one_job(tctx, b, &t->handle,
8897 "TorturePrintJob",
8898 &job_ids[i]);
8899 torture_assert(tctx, ret, "failed to add print job");
8902 /* enum after jobs, valid level */
8903 torture_assert(tctx,
8904 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
8905 &count, &info),
8906 "EnumJobs with valid level");
8907 torture_assert_int_equal(tctx, count, num_jobs, "EnumJobs count");
8908 torture_assert(tctx,
8909 test_EnumJobs_args(tctx, b, &t->handle, 2, WERR_OK,
8910 &count, &info),
8911 "EnumJobs with valid level");
8912 torture_assert_int_equal(tctx, count, num_jobs, "EnumJobs count");
8913 /* enum after jobs, invalid level - expect failure */
8914 torture_assert(tctx,
8915 test_EnumJobs_args(tctx, b, &t->handle, 100,
8916 WERR_INVALID_LEVEL,
8917 &count, &info),
8918 "EnumJobs with invalid level");
8920 for (i = 0; i < num_jobs; i++) {
8921 test_SetJob(tctx, b, &t->handle, job_ids[i], NULL,
8922 SPOOLSS_JOB_CONTROL_DELETE);
8925 torture_assert(tctx,
8926 test_ResumePrinter(tctx, b, &t->handle),
8927 "failed to resume printer");
8929 return true;
8932 void torture_tcase_printer(struct torture_tcase *tcase)
8934 torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
8935 torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
8936 torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
8937 torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
8938 torture_tcase_add_simple_test(tcase, "print_test_smbd", test_print_test_smbd);
8939 torture_tcase_add_simple_test(tcase, "print_test_properties", test_print_test_properties);
8940 torture_tcase_add_simple_test(tcase, "print_test_purge", test_print_test_purge);
8941 torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
8942 torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
8943 torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
8944 torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
8945 torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
8946 torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
8947 torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
8948 torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
8949 torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
8950 torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
8951 torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
8952 torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
8953 torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
8954 torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
8955 torture_tcase_add_simple_test(tcase, "printer_ic", test_printer_ic);
8956 torture_tcase_add_simple_test(tcase, "bidi", test_printer_bidi);
8957 torture_tcase_add_simple_test(tcase, "publish_toggle",
8958 test_printer_publish_toggle);
8959 torture_tcase_add_simple_test(tcase, "print_job_enum", test_print_job_enum);
8962 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
8964 struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
8965 struct torture_tcase *tcase;
8967 tcase = torture_suite_add_tcase(suite, "addprinter");
8969 torture_tcase_set_fixture(tcase,
8970 torture_rpc_spoolss_printer_setup,
8971 torture_rpc_spoolss_printer_teardown);
8973 torture_tcase_printer(tcase);
8975 tcase = torture_suite_add_tcase(suite, "addprinterex");
8977 torture_tcase_set_fixture(tcase,
8978 torture_rpc_spoolss_printerex_setup,
8979 torture_rpc_spoolss_printer_teardown);
8981 torture_tcase_printer(tcase);
8983 tcase = torture_suite_add_tcase(suite, "addprinterwkn");
8985 torture_tcase_set_fixture(tcase,
8986 torture_rpc_spoolss_printerwkn_setup,
8987 torture_rpc_spoolss_printer_teardown);
8989 tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
8991 torture_tcase_set_fixture(tcase,
8992 torture_rpc_spoolss_printerexwkn_setup,
8993 torture_rpc_spoolss_printer_teardown);
8995 #if 0
8996 /* test is not correct */
8997 tcase = torture_suite_add_tcase(suite, "addprinterdm");
8999 torture_tcase_set_fixture(tcase,
9000 torture_rpc_spoolss_printerdm_setup,
9001 torture_rpc_spoolss_printer_teardown);
9003 torture_tcase_printer(tcase);
9004 #endif
9005 return suite;
9008 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
9010 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
9011 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
9013 torture_tcase_set_fixture(tcase,
9014 torture_rpc_spoolss_setup,
9015 torture_rpc_spoolss_teardown);
9017 torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
9018 torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
9019 torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
9020 torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
9021 torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
9022 torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
9023 torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
9024 torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
9025 torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
9026 torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
9027 torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
9028 torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
9029 torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
9030 torture_tcase_add_simple_test(tcase, "add_processor", test_add_print_processor);
9031 torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
9032 torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
9033 torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
9034 torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
9035 torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
9036 torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
9037 torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
9039 torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
9041 return suite;
9044 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
9045 struct dcerpc_binding_handle *b,
9046 const char *server,
9047 const char *environment,
9048 const char **dir_p)
9050 struct spoolss_GetPrinterDriverDirectory r;
9051 uint32_t needed;
9053 r.in.server = server;
9054 r.in.environment = environment;
9055 r.in.level = 1;
9056 r.in.buffer = NULL;
9057 r.in.offered = 0;
9058 r.out.needed = &needed;
9060 torture_assert_ntstatus_ok(tctx,
9061 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
9062 "failed to query driver directory");
9064 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
9065 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
9066 r.in.buffer = &blob;
9067 r.in.offered = needed;
9069 torture_assert_ntstatus_ok(tctx,
9070 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
9071 "failed to query driver directory");
9074 torture_assert_werr_ok(tctx, r.out.result,
9075 "failed to query driver directory");
9077 if (dir_p) {
9078 *dir_p = r.out.info->info1.directory_name;
9081 return true;
9084 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
9086 if (info_ctr == NULL) {
9087 return NULL;
9090 switch (info_ctr->level) {
9091 case 1:
9092 return info_ctr->info.info1->driver_name;
9093 case 2:
9094 return info_ctr->info.info2->driver_name;
9095 case 3:
9096 return info_ctr->info.info3->driver_name;
9097 case 4:
9098 return info_ctr->info.info4->driver_name;
9099 case 6:
9100 return info_ctr->info.info6->driver_name;
9101 case 8:
9102 return info_ctr->info.info8->driver_name;
9103 default:
9104 return NULL;
9108 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
9110 if (info_ctr == NULL) {
9111 return NULL;
9114 switch (info_ctr->level) {
9115 case 2:
9116 return info_ctr->info.info2->architecture;
9117 case 3:
9118 return info_ctr->info.info3->architecture;
9119 case 4:
9120 return info_ctr->info.info4->architecture;
9121 case 6:
9122 return info_ctr->info.info6->architecture;
9123 case 8:
9124 return info_ctr->info.info8->architecture;
9125 default:
9126 return NULL;
9131 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
9132 struct dcerpc_binding_handle *b,
9133 const char *servername,
9134 struct spoolss_AddDriverInfoCtr *info_ctr,
9135 WERROR expected_result)
9137 struct spoolss_AddPrinterDriver r;
9138 const char *drivername = get_driver_from_info(info_ctr);
9139 const char *environment = get_environment_from_info(info_ctr);
9141 r.in.servername = servername;
9142 r.in.info_ctr = info_ctr;
9144 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
9145 drivername, info_ctr->level, environment);
9147 torture_assert_ntstatus_ok(tctx,
9148 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
9149 "spoolss_AddPrinterDriver failed");
9150 torture_assert_werr_equal(tctx, r.out.result, expected_result,
9151 "spoolss_AddPrinterDriver failed with unexpected result");
9153 return true;
9157 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
9158 struct dcerpc_binding_handle *b,
9159 const char *servername,
9160 struct spoolss_AddDriverInfoCtr *info_ctr,
9161 uint32_t flags,
9162 WERROR expected_result)
9164 struct spoolss_AddPrinterDriverEx r;
9165 const char *drivername = get_driver_from_info(info_ctr);
9166 const char *environment = get_environment_from_info(info_ctr);
9168 r.in.servername = servername;
9169 r.in.info_ctr = info_ctr;
9170 r.in.flags = flags;
9172 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
9173 drivername, info_ctr->level, environment);
9175 torture_assert_ntstatus_ok(tctx,
9176 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
9177 "AddPrinterDriverEx failed");
9178 torture_assert_werr_equal(tctx, r.out.result, expected_result,
9179 "AddPrinterDriverEx failed with unexpected result");
9181 return true;
9184 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
9185 if (path && strlen(path)) {\
9186 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
9189 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
9190 struct dcerpc_binding_handle *b,
9191 const char *server_name,
9192 struct spoolss_AddDriverInfo8 *r,
9193 uint32_t flags,
9194 bool ex,
9195 const char *remote_driver_dir)
9197 struct spoolss_AddDriverInfoCtr info_ctr;
9198 struct spoolss_AddDriverInfo1 info1;
9200 ZERO_STRUCT(info1);
9202 info_ctr.level = 1;
9203 info_ctr.info.info1 = &info1;
9205 if (ex) {
9206 torture_assert(tctx,
9207 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
9208 "failed to test AddPrinterDriverEx level 1");
9209 } else {
9210 torture_assert(tctx,
9211 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9212 "failed to test AddPrinterDriver level 1");
9215 info1.driver_name = r->driver_name;
9217 if (ex) {
9218 torture_assert(tctx,
9219 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
9220 "failed to test AddPrinterDriverEx level 1");
9221 } else {
9222 torture_assert(tctx,
9223 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9224 "failed to test AddPrinterDriver level 1");
9227 return true;
9230 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
9231 struct dcerpc_binding_handle *b,
9232 const char *server_name,
9233 struct spoolss_AddDriverInfo8 *r,
9234 uint32_t flags,
9235 bool ex,
9236 const char *remote_driver_dir)
9238 struct spoolss_AddDriverInfoCtr info_ctr;
9239 struct spoolss_AddDriverInfo2 info2;
9240 union spoolss_DriverInfo info;
9242 ZERO_STRUCT(info2);
9244 info_ctr.level = 2;
9245 info_ctr.info.info2 = &info2;
9247 if (ex) {
9248 torture_assert(tctx,
9249 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9250 "failed to test AddPrinterDriverEx level 2");
9251 } else {
9252 torture_assert(tctx,
9253 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9254 "failed to test AddPrinterDriver level 2");
9257 info2.driver_name = r->driver_name;
9259 if (ex) {
9260 torture_assert(tctx,
9261 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9262 "failed to test AddPrinterDriverEx level 2");
9263 } else {
9264 torture_assert(tctx,
9265 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9266 "failed to test AddPrinterDriver level 2");
9269 info2.version = r->version;
9271 if (ex) {
9272 torture_assert(tctx,
9273 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9274 "failed to test AddPrinterDriverEx level 2");
9275 } else {
9276 torture_assert(tctx,
9277 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9278 "failed to test AddPrinterDriver level 2");
9281 info2.architecture = r->architecture;
9283 if (ex) {
9284 torture_assert(tctx,
9285 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9286 "failed to test AddPrinterDriverEx level 2");
9287 } else {
9288 torture_assert(tctx,
9289 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9290 "failed to test AddPrinterDriver level 2");
9293 info2.driver_path = r->driver_path;
9295 if (ex) {
9296 torture_assert(tctx,
9297 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9298 "failed to test AddPrinterDriverEx level 2");
9299 } else {
9300 torture_assert(tctx,
9301 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9302 "failed to test AddPrinterDriver level 2");
9305 info2.data_file = r->data_file;
9307 if (ex) {
9308 torture_assert(tctx,
9309 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9310 "failed to test AddPrinterDriverEx level 2");
9311 } else {
9312 torture_assert(tctx,
9313 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9314 "failed to test AddPrinterDriver level 2");
9317 info2.config_file = r->config_file;
9319 if (ex) {
9320 torture_assert(tctx,
9321 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
9322 "failed to test AddPrinterDriverEx");
9325 if (ex) {
9326 torture_assert(tctx,
9327 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9328 "failed to test AddPrinterDriverEx level 2");
9329 } else {
9330 torture_assert(tctx,
9331 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
9332 "failed to test AddPrinterDriver level 2");
9335 torture_assert(tctx,
9336 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
9337 "failed to find added printer driver");
9339 if (remote_driver_dir) {
9340 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
9341 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
9342 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
9345 return true;
9348 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
9349 struct dcerpc_binding_handle *b,
9350 const char *server_name,
9351 struct spoolss_AddDriverInfo8 *r,
9352 uint32_t flags,
9353 bool ex,
9354 const char *remote_driver_dir)
9356 struct spoolss_AddDriverInfoCtr info_ctr;
9357 struct spoolss_AddDriverInfo3 info3;
9358 union spoolss_DriverInfo info;
9360 info3.driver_name = r->driver_name;
9361 info3.version = r->version;
9362 info3.architecture = r->architecture;
9363 info3.driver_path = r->driver_path;
9364 info3.data_file = r->data_file;
9365 info3.config_file = r->config_file;
9366 info3.help_file = r->help_file;
9367 info3.monitor_name = r->monitor_name;
9368 info3.default_datatype = r->default_datatype;
9369 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
9370 info3.dependent_files = r->dependent_files;
9372 info_ctr.level = 3;
9373 info_ctr.info.info3 = &info3;
9375 if (ex) {
9376 torture_assert(tctx,
9377 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9378 "failed to test AddPrinterDriverEx level 3");
9379 } else {
9380 torture_assert(tctx,
9381 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
9382 "failed to test AddPrinterDriver level 3");
9385 torture_assert(tctx,
9386 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
9387 "failed to find added printer driver");
9389 if (remote_driver_dir) {
9390 int i;
9391 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
9392 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
9393 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
9394 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
9395 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
9396 ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
9400 return true;
9403 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
9404 struct dcerpc_binding_handle *b,
9405 const char *server_name,
9406 struct spoolss_AddDriverInfo8 *r,
9407 uint32_t flags,
9408 bool ex,
9409 const char *remote_driver_dir)
9411 struct spoolss_AddDriverInfoCtr info_ctr;
9412 struct spoolss_AddDriverInfo4 info4;
9413 union spoolss_DriverInfo info;
9415 info4.version = r->version;
9416 info4.driver_name = r->driver_name;
9417 info4.architecture = r->architecture;
9418 info4.driver_path = r->driver_path;
9419 info4.data_file = r->data_file;
9420 info4.config_file = r->config_file;
9421 info4.help_file = r->help_file;
9422 info4.monitor_name = r->monitor_name;
9423 info4.default_datatype = r->default_datatype;
9424 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
9425 info4.dependent_files = r->dependent_files;
9426 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
9427 info4.previous_names = r->previous_names;
9429 info_ctr.level = 4;
9430 info_ctr.info.info4 = &info4;
9432 if (ex) {
9433 torture_assert(tctx,
9434 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9435 "failed to test AddPrinterDriverEx level 4");
9436 } else {
9437 torture_assert(tctx,
9438 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
9439 "failed to test AddPrinterDriver level 4");
9442 torture_assert(tctx,
9443 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
9444 "failed to find added printer driver");
9446 if (remote_driver_dir) {
9447 int i;
9448 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
9449 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
9450 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
9451 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
9452 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
9453 ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
9457 return true;
9460 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
9461 struct dcerpc_binding_handle *b,
9462 const char *server_name,
9463 struct spoolss_AddDriverInfo8 *r,
9464 uint32_t flags,
9465 bool ex,
9466 const char *remote_driver_dir)
9468 struct spoolss_AddDriverInfoCtr info_ctr;
9469 struct spoolss_AddDriverInfo6 info6;
9470 union spoolss_DriverInfo info;
9472 info6.version = r->version;
9473 info6.driver_name = r->driver_name;
9474 info6.architecture = r->architecture;
9475 info6.driver_path = r->driver_path;
9476 info6.data_file = r->data_file;
9477 info6.config_file = r->config_file;
9478 info6.help_file = r->help_file;
9479 info6.monitor_name = r->monitor_name;
9480 info6.default_datatype = r->default_datatype;
9481 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
9482 info6.dependent_files = r->dependent_files;
9483 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
9484 info6.previous_names = r->previous_names;
9485 info6.driver_date = r->driver_date;
9486 info6.driver_version = r->driver_version;
9487 info6.manufacturer_name = r->manufacturer_name;
9488 info6.manufacturer_url = r->manufacturer_url;
9489 info6.hardware_id = r->hardware_id;
9490 info6.provider = r->provider;
9492 info_ctr.level = 6;
9493 info_ctr.info.info6 = &info6;
9495 if (ex) {
9496 torture_assert(tctx,
9497 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9498 "failed to test AddPrinterDriverEx level 6");
9499 } else {
9500 torture_assert(tctx,
9501 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9502 "failed to test AddPrinterDriver level 6");
9505 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9507 if (!ex) {
9508 return true;
9511 torture_assert(tctx,
9512 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
9513 "failed to find added printer driver");
9515 if (remote_driver_dir) {
9516 int i;
9517 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
9518 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
9519 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
9520 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
9521 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
9522 ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
9526 torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
9527 torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
9529 return true;
9532 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
9533 struct dcerpc_binding_handle *b,
9534 const char *server_name,
9535 struct spoolss_AddDriverInfo8 *r,
9536 uint32_t flags,
9537 bool ex,
9538 const char *remote_driver_dir)
9540 struct spoolss_AddDriverInfoCtr info_ctr;
9541 union spoolss_DriverInfo info;
9543 info_ctr.level = 8;
9544 info_ctr.info.info8 = r;
9546 if (ex) {
9547 torture_assert(tctx,
9548 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9549 "failed to test AddPrinterDriverEx level 8");
9550 } else {
9551 torture_assert(tctx,
9552 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9553 "failed to test AddPrinterDriver level 8");
9556 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9558 if (!ex) {
9559 return true;
9562 torture_assert(tctx,
9563 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
9564 "failed to find added printer driver");
9566 if (remote_driver_dir) {
9567 int i;
9568 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
9569 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
9570 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
9571 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
9572 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
9573 ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
9577 torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
9578 torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
9580 return true;
9583 #undef ASSERT_DRIVER_PATH
9585 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
9586 struct dcerpc_binding_handle *b,
9587 const char *server,
9588 const char *driver,
9589 const char *environment,
9590 WERROR expected_result)
9592 struct spoolss_DeletePrinterDriver r;
9594 r.in.server = server;
9595 r.in.architecture = environment;
9596 r.in.driver = driver;
9598 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
9600 torture_assert_ntstatus_ok(tctx,
9601 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
9602 "DeletePrinterDriver failed");
9603 torture_assert_werr_equal(tctx, r.out.result, expected_result,
9604 "DeletePrinterDriver failed with unexpected result");
9606 return true;
9609 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
9610 struct dcerpc_binding_handle *b,
9611 const char *server,
9612 const char *driver,
9613 const char *environment,
9614 uint32_t delete_flags,
9615 uint32_t version,
9616 WERROR expected_result)
9618 struct spoolss_DeletePrinterDriverEx r;
9620 r.in.server = server;
9621 r.in.architecture = environment;
9622 r.in.driver = driver;
9623 r.in.delete_flags = delete_flags;
9624 r.in.version = version;
9626 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
9628 torture_assert_ntstatus_ok(tctx,
9629 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
9630 "DeletePrinterDriverEx failed");
9631 torture_assert_werr_equal(tctx, r.out.result, expected_result,
9632 "DeletePrinterDriverEx failed with unexpected result");
9634 return true;
9637 static bool test_DeletePrinterDriver(struct torture_context *tctx,
9638 struct dcerpc_binding_handle *b,
9639 const char *server_name,
9640 const char *driver,
9641 const char *environment)
9643 torture_assert(tctx,
9644 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
9645 "failed to delete driver");
9647 torture_assert(tctx,
9648 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
9649 "failed to delete driver");
9651 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
9652 torture_fail(tctx, "deleted driver still enumerated");
9655 torture_assert(tctx,
9656 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
9657 "2nd delete failed");
9659 return true;
9662 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
9663 struct dcerpc_binding_handle *b,
9664 const char *server_name,
9665 const char *driver,
9666 const char *environment,
9667 uint32_t delete_flags,
9668 uint32_t version)
9670 torture_assert(tctx,
9671 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
9672 "failed to delete driver");
9674 torture_assert(tctx,
9675 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
9676 "failed to delete driver");
9678 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
9679 torture_fail(tctx, "deleted driver still enumerated");
9682 torture_assert(tctx,
9683 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
9684 "2nd delete failed");
9686 return true;
9689 static bool test_PrinterDriver_args(struct torture_context *tctx,
9690 struct dcerpc_binding_handle *b,
9691 const char *server_name,
9692 uint32_t level,
9693 struct spoolss_AddDriverInfo8 *r,
9694 uint32_t add_flags,
9695 uint32_t delete_flags,
9696 uint32_t delete_version,
9697 bool ex,
9698 const char *remote_driver_dir)
9700 bool ret = true;
9702 switch (level) {
9703 case 1:
9704 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9705 break;
9706 case 2:
9707 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9708 break;
9709 case 3:
9710 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9711 break;
9712 case 4:
9713 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9714 break;
9715 case 6:
9716 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9717 break;
9718 case 8:
9719 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9720 break;
9721 default:
9722 return false;
9725 if (ret == false) {
9726 return ret;
9729 if (level == 1) {
9730 return ret;
9733 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9735 if (!ex && (level == 6 || level == 8)) {
9736 return ret;
9740 struct dcerpc_pipe *p2;
9741 struct policy_handle hive_handle;
9742 struct dcerpc_binding_handle *b2;
9744 torture_assert_ntstatus_ok(tctx,
9745 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
9746 "could not open winreg pipe");
9747 b2 = p2->binding_handle;
9749 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
9751 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
9753 test_winreg_CloseKey(tctx, b2, &hive_handle);
9755 talloc_free(p2);
9758 if (ex) {
9759 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
9760 } else {
9761 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
9765 static bool fillup_printserver_info(struct torture_context *tctx,
9766 struct dcerpc_pipe *p,
9767 struct torture_driver_context *d)
9769 struct policy_handle server_handle;
9770 struct dcerpc_binding_handle *b = p->binding_handle;
9771 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9773 torture_assert(tctx,
9774 test_OpenPrinter_server(tctx, p, &server_handle),
9775 "failed to open printserver");
9776 torture_assert(tctx,
9777 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
9778 "failed to get environment");
9779 torture_assert(tctx,
9780 test_ClosePrinter(tctx, b, &server_handle),
9781 "failed to close printserver");
9783 torture_assert(tctx,
9784 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
9785 d->local.environment ? d->local.environment : d->remote.environment,
9786 &d->remote.driver_directory),
9787 "failed to get driver directory");
9789 return true;
9792 static const char *driver_directory_dir(const char *driver_directory)
9794 char *p;
9796 p = strrchr(driver_directory, '\\');
9797 if (p) {
9798 return p+1;
9801 return NULL;
9804 static const char *driver_directory_share(struct torture_context *tctx,
9805 const char *driver_directory)
9807 const char *p;
9808 char *tok;
9810 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
9811 driver_directory += 2;
9814 p = talloc_strdup(tctx, driver_directory);
9816 torture_assert(tctx,
9817 next_token_talloc(tctx, &p, &tok, "\\"),
9818 "cannot explode uri");
9819 torture_assert(tctx,
9820 next_token_talloc(tctx, &p, &tok, "\\"),
9821 "cannot explode uri");
9823 return tok;
9826 static bool upload_printer_driver_file(struct torture_context *tctx,
9827 struct smbcli_state *cli,
9828 struct torture_driver_context *d,
9829 const char *file_name)
9831 XFILE *f;
9832 int fnum;
9833 uint8_t *buf;
9834 int maxwrite = 64512;
9835 off_t nread = 0;
9836 size_t start = 0;
9837 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
9838 const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
9839 const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
9841 if (!file_name || strlen(file_name) == 0) {
9842 return true;
9845 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
9847 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
9848 if (fnum == -1) {
9849 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
9852 f = x_fopen(local_name, O_RDONLY, 0);
9853 if (f == NULL) {
9854 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
9857 buf = talloc_array(tctx, uint8_t, maxwrite);
9858 if (!buf) {
9859 x_fclose(f);
9860 return false;
9863 while (!x_feof(f)) {
9864 int n = maxwrite;
9865 int ret;
9867 if ((n = x_fread(buf, 1, n, f)) < 1) {
9868 if((n == 0) && x_feof(f))
9869 break; /* Empty local file. */
9871 torture_warning(tctx,
9872 "failed to read file: %s\n", strerror(errno));
9873 break;
9876 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
9878 if (n != ret) {
9879 torture_warning(tctx,
9880 "failed to write file: %s\n", smbcli_errstr(cli->tree));
9881 break;
9884 nread += n;
9887 x_fclose(f);
9889 torture_assert_ntstatus_ok(tctx,
9890 smbcli_close(cli->tree, fnum),
9891 "failed to close file");
9893 return true;
9896 static bool connect_printer_driver_share(struct torture_context *tctx,
9897 const char *server_name,
9898 const char *share_name,
9899 struct smbcli_state **cli)
9901 struct smbcli_options smb_options;
9902 struct smbcli_session_options smb_session_options;
9904 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
9905 share_name, server_name);
9907 lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
9908 lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
9910 torture_assert_ntstatus_ok(tctx,
9911 smbcli_full_connection(tctx, cli, server_name,
9912 lpcfg_smb_ports(tctx->lp_ctx),
9913 share_name, NULL,
9914 lpcfg_socket_options(tctx->lp_ctx),
9915 cmdline_credentials,
9916 lpcfg_resolve_context(tctx->lp_ctx),
9917 tctx->ev,
9918 &smb_options,
9919 &smb_session_options,
9920 lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
9921 "failed to open driver share");
9923 return true;
9926 static bool upload_printer_driver(struct torture_context *tctx,
9927 const char *server_name,
9928 struct torture_driver_context *d)
9930 struct smbcli_state *cli;
9931 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9932 int i;
9934 torture_assert(tctx,
9935 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9936 "failed to connect to driver share");
9938 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
9939 server_name, share_name);
9941 torture_assert(tctx,
9942 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
9943 "failed to upload driver_path");
9944 torture_assert(tctx,
9945 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
9946 "failed to upload data_file");
9947 torture_assert(tctx,
9948 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
9949 "failed to upload config_file");
9950 torture_assert(tctx,
9951 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
9952 "failed to upload help_file");
9953 if (d->info8.dependent_files) {
9954 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9955 torture_assert(tctx,
9956 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9957 "failed to upload dependent_files");
9961 talloc_free(cli);
9963 return true;
9966 static bool check_printer_driver_file(struct torture_context *tctx,
9967 struct smbcli_state *cli,
9968 struct torture_driver_context *d,
9969 const char *file_name)
9971 const char *remote_arch_dir = driver_directory_dir(d->remote.driver_directory);
9972 const char *remote_name = talloc_asprintf(tctx, "%s\\%d\\%s",
9973 remote_arch_dir,
9974 d->info8.version,
9975 file_name);
9976 int fnum;
9978 torture_assert(tctx, (file_name && strlen(file_name) != 0), "invalid filename");
9980 torture_comment(tctx, "checking for driver file at %s\n", remote_name);
9982 fnum = smbcli_open(cli->tree, remote_name, O_RDONLY, DENY_NONE);
9983 if (fnum == -1) {
9984 return false;
9987 torture_assert_ntstatus_ok(tctx,
9988 smbcli_close(cli->tree, fnum),
9989 "failed to close driver file");
9991 return true;
9994 static bool check_printer_driver_files(struct torture_context *tctx,
9995 const char *server_name,
9996 struct torture_driver_context *d,
9997 bool expect_exist)
9999 struct smbcli_state *cli;
10000 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
10001 int i;
10003 torture_assert(tctx,
10004 connect_printer_driver_share(tctx, server_name, share_name, &cli),
10005 "failed to connect to driver share");
10007 torture_comment(tctx, "checking %sexistent driver files at \\\\%s\\%s\n",
10008 (expect_exist ? "": "non-"),
10009 server_name, share_name);
10011 if (d->info8.driver_path && d->info8.driver_path[0]) {
10012 torture_assert(tctx,
10013 check_printer_driver_file(tctx, cli, d, d->info8.driver_path) == expect_exist,
10014 "failed driver_path check");
10016 if (d->info8.data_file && d->info8.data_file[0]) {
10017 torture_assert(tctx,
10018 check_printer_driver_file(tctx, cli, d, d->info8.data_file) == expect_exist,
10019 "failed data_file check");
10021 if (d->info8.config_file && d->info8.config_file[0]) {
10022 torture_assert(tctx,
10023 check_printer_driver_file(tctx, cli, d, d->info8.config_file) == expect_exist,
10024 "failed config_file check");
10026 if (d->info8.help_file && d->info8.help_file[0]) {
10027 torture_assert(tctx,
10028 check_printer_driver_file(tctx, cli, d, d->info8.help_file) == expect_exist,
10029 "failed help_file check");
10031 if (d->info8.dependent_files) {
10032 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
10033 torture_assert(tctx,
10034 check_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]) == expect_exist,
10035 "failed dependent_files check");
10039 talloc_free(cli);
10041 return true;
10044 static bool remove_printer_driver_file(struct torture_context *tctx,
10045 struct smbcli_state *cli,
10046 struct torture_driver_context *d,
10047 const char *file_name)
10049 const char *remote_name;
10050 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
10052 if (!file_name || strlen(file_name) == 0) {
10053 return true;
10056 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
10058 torture_comment(tctx, "Removing %s\n", remote_name);
10060 torture_assert_ntstatus_ok(tctx,
10061 smbcli_unlink(cli->tree, remote_name),
10062 "failed to unlink");
10064 return true;
10067 static bool remove_printer_driver(struct torture_context *tctx,
10068 const char *server_name,
10069 struct torture_driver_context *d)
10071 struct smbcli_state *cli;
10072 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
10073 int i;
10075 torture_assert(tctx,
10076 connect_printer_driver_share(tctx, server_name, share_name, &cli),
10077 "failed to connect to driver share");
10079 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
10080 server_name, share_name);
10082 torture_assert(tctx,
10083 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
10084 "failed to remove driver_path");
10085 torture_assert(tctx,
10086 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
10087 "failed to remove data_file");
10088 if (!strequal(d->info8.config_file, d->info8.driver_path)) {
10089 torture_assert(tctx,
10090 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
10091 "failed to remove config_file");
10093 torture_assert(tctx,
10094 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
10095 "failed to remove help_file");
10096 if (d->info8.dependent_files) {
10097 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
10098 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
10099 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
10100 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
10101 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
10102 continue;
10104 torture_assert(tctx,
10105 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
10106 "failed to remove dependent_files");
10110 talloc_free(cli);
10112 return true;
10116 static bool test_add_driver_arg(struct torture_context *tctx,
10117 struct dcerpc_pipe *p,
10118 struct torture_driver_context *d)
10120 bool ret = true;
10121 struct dcerpc_binding_handle *b = p->binding_handle;
10122 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10123 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
10124 int i;
10125 struct spoolss_AddDriverInfo8 info8;
10126 uint32_t add_flags = APD_COPY_NEW_FILES;
10127 uint32_t delete_flags = 0;
10129 ZERO_STRUCT(info8);
10131 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
10132 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
10134 torture_assert(tctx,
10135 fillup_printserver_info(tctx, p, d),
10136 "failed to fillup printserver info");
10138 if (!directory_exist(d->local.driver_directory)) {
10139 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10142 torture_assert(tctx,
10143 upload_printer_driver(tctx, dcerpc_server_name(p), d),
10144 "failed to upload printer driver");
10146 info8 = d->info8;
10147 if (d->info8.dependent_files) {
10148 info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
10149 if (d->info8.dependent_files->string) {
10150 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
10152 info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
10153 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
10154 info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
10158 info8.architecture = d->local.environment;
10160 for (i=0; i < ARRAY_SIZE(levels); i++) {
10162 if (torture_setting_bool(tctx, "samba3", false)) {
10163 switch (levels[i]) {
10164 case 2:
10165 case 4:
10166 case 8:
10167 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
10168 continue;
10169 default:
10170 break;
10173 if (torture_setting_bool(tctx, "w2k3", false)) {
10174 switch (levels[i]) {
10175 case 8:
10176 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
10177 continue;
10178 default:
10179 break;
10183 torture_comment(tctx,
10184 "Testing PrinterDriver%s '%s' add & delete level %d\n",
10185 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
10187 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);
10190 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
10191 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
10192 if (d->info8.config_file) {
10193 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
10195 if (d->info8.help_file) {
10196 info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
10198 if (d->info8.dependent_files && d->info8.dependent_files->string) {
10199 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
10200 info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
10204 for (i=0; i < ARRAY_SIZE(levels); i++) {
10206 if (torture_setting_bool(tctx, "samba3", false)) {
10207 switch (levels[i]) {
10208 case 2:
10209 case 4:
10210 case 8:
10211 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
10212 continue;
10213 default:
10214 break;
10217 if (torture_setting_bool(tctx, "w2k3", false)) {
10218 switch (levels[i]) {
10219 case 8:
10220 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
10221 continue;
10222 default:
10223 break;
10227 torture_comment(tctx,
10228 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
10229 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
10231 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);
10234 torture_assert(tctx,
10235 remove_printer_driver(tctx, dcerpc_server_name(p), d),
10236 "failed to remove printer driver");
10238 torture_comment(tctx, "\n");
10240 return ret;
10243 static bool test_add_driver_ex_64(struct torture_context *tctx,
10244 struct dcerpc_pipe *p)
10246 struct torture_driver_context *d;
10248 d = talloc_zero(tctx, struct torture_driver_context);
10250 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10251 d->info8.driver_name = TORTURE_DRIVER_EX;
10252 d->info8.architecture = NULL;
10253 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10254 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10255 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10256 d->local.environment = talloc_strdup(d, "Windows x64");
10257 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
10258 d->ex = true;
10260 return test_add_driver_arg(tctx, p, d);
10263 static bool test_add_driver_ex_32(struct torture_context *tctx,
10264 struct dcerpc_pipe *p)
10266 struct torture_driver_context *d;
10268 d = talloc_zero(tctx, struct torture_driver_context);
10270 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10271 d->info8.driver_name = TORTURE_DRIVER_EX;
10272 d->info8.architecture = NULL;
10273 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10274 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10275 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10276 d->local.environment = talloc_strdup(d, "Windows NT x86");
10277 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10278 d->ex = true;
10280 return test_add_driver_arg(tctx, p, d);
10283 static bool test_add_driver_64(struct torture_context *tctx,
10284 struct dcerpc_pipe *p)
10286 struct torture_driver_context *d;
10288 d = talloc_zero(tctx, struct torture_driver_context);
10290 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10291 d->info8.driver_name = TORTURE_DRIVER;
10292 d->info8.architecture = NULL;
10293 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10294 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10295 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10296 d->local.environment = talloc_strdup(d, "Windows x64");
10297 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
10298 d->ex = false;
10300 return test_add_driver_arg(tctx, p, d);
10303 static bool test_add_driver_32(struct torture_context *tctx,
10304 struct dcerpc_pipe *p)
10306 struct torture_driver_context *d;
10308 d = talloc_zero(tctx, struct torture_driver_context);
10310 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10311 d->info8.driver_name = TORTURE_DRIVER;
10312 d->info8.architecture = NULL;
10313 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10314 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10315 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10316 d->local.environment = talloc_strdup(d, "Windows NT x86");
10317 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10318 d->ex = false;
10320 return test_add_driver_arg(tctx, p, d);
10323 static bool test_add_driver_adobe(struct torture_context *tctx,
10324 struct dcerpc_pipe *p)
10326 struct torture_driver_context *d;
10328 if (!torture_setting_bool(tctx, "samba3", false)) {
10329 torture_skip(tctx, "skipping adobe test which only works against samba3");
10332 d = talloc_zero(tctx, struct torture_driver_context);
10334 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
10335 d->info8.driver_name = TORTURE_DRIVER_ADOBE;
10336 d->info8.architecture = NULL;
10337 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
10338 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
10339 d->info8.config_file = talloc_strdup(d, "ADOBEPS4.DRV");
10340 #if 0
10341 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
10342 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
10343 #endif
10344 d->local.environment = talloc_strdup(d, "Windows 4.0");
10345 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
10346 d->ex = false;
10348 return test_add_driver_arg(tctx, p, d);
10351 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
10352 struct dcerpc_pipe *p)
10354 struct torture_driver_context *d;
10355 struct spoolss_StringArray *a;
10357 if (!torture_setting_bool(tctx, "samba3", false)) {
10358 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
10361 d = talloc_zero(tctx, struct torture_driver_context);
10363 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
10364 d->info8.driver_name = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
10365 d->info8.architecture = NULL;
10366 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
10367 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
10368 d->info8.config_file = NULL;
10369 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
10370 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
10371 d->info8.default_datatype = talloc_strdup(d, "RAW");
10373 a = talloc_zero(d, struct spoolss_StringArray);
10374 a->string = talloc_zero_array(a, const char *, 7);
10375 a->string[0] = talloc_strdup(a->string, "ADOBEPS4.DRV");
10376 a->string[1] = talloc_strdup(a->string, "DEFPRTR2.PPD");
10377 a->string[2] = talloc_strdup(a->string, "ADOBEPS4.HLP");
10378 a->string[3] = talloc_strdup(a->string, "PSMON.DLL");
10379 a->string[4] = talloc_strdup(a->string, "ADFONTS.MFM");
10380 a->string[5] = talloc_strdup(a->string, "ICONLIB.DLL");
10382 d->info8.dependent_files = a;
10383 d->local.environment = talloc_strdup(d, "Windows 4.0");
10384 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
10385 d->ex = false;
10387 return test_add_driver_arg(tctx, p, d);
10390 static bool test_add_driver_timestamps(struct torture_context *tctx,
10391 struct dcerpc_pipe *p)
10393 struct torture_driver_context *d;
10394 struct timeval t = timeval_current();
10396 d = talloc_zero(tctx, struct torture_driver_context);
10398 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10399 d->info8.driver_name = TORTURE_DRIVER_TIMESTAMPS;
10400 d->info8.architecture = NULL;
10401 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10402 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10403 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10404 d->info8.driver_date = timeval_to_nttime(&t);
10405 d->local.environment = talloc_strdup(d, "Windows NT x86");
10406 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10407 d->ex = true;
10409 torture_assert(tctx,
10410 test_add_driver_arg(tctx, p, d),
10411 "");
10413 unix_to_nt_time(&d->info8.driver_date, 1);
10415 torture_assert(tctx,
10416 test_add_driver_arg(tctx, p, d),
10417 "");
10419 return true;
10422 static bool test_multiple_drivers(struct torture_context *tctx,
10423 struct dcerpc_pipe *p)
10425 struct torture_driver_context *d;
10426 struct dcerpc_binding_handle *b = p->binding_handle;
10427 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10428 int i;
10429 struct spoolss_AddDriverInfo8 info8;
10430 uint32_t add_flags = APD_COPY_NEW_FILES;
10431 uint32_t delete_flags = 0;
10433 d = talloc_zero(tctx, struct torture_driver_context);
10435 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10436 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10437 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10438 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10439 d->local.environment = talloc_strdup(d, "Windows NT x86");
10440 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10441 d->ex = true;
10443 torture_assert(tctx,
10444 fillup_printserver_info(tctx, p, d),
10445 "failed to fillup printserver info");
10447 if (!directory_exist(d->local.driver_directory)) {
10448 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10451 torture_assert(tctx,
10452 upload_printer_driver(tctx, dcerpc_server_name(p), d),
10453 "failed to upload printer driver");
10455 info8 = d->info8;
10456 info8.architecture = d->local.environment;
10458 for (i=0; i < 3; i++) {
10459 info8.driver_name = talloc_asprintf(d, "torture_test_driver_%d", i);
10461 torture_assert(tctx,
10462 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &info8, add_flags, true, NULL),
10463 "failed to add driver");
10466 torture_assert(tctx,
10467 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_0", info8.architecture, delete_flags, info8.version),
10468 "failed to delete driver");
10470 torture_assert(tctx,
10471 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_1", NULL),
10472 "torture_test_driver_1 no longer on the server");
10474 torture_assert(tctx,
10475 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
10476 "torture_test_driver_2 no longer on the server");
10478 torture_assert(tctx,
10479 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_1", info8.architecture, delete_flags, info8.version),
10480 "failed to delete driver");
10482 torture_assert(tctx,
10483 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
10484 "torture_test_driver_2 no longer on the server");
10486 torture_assert(tctx,
10487 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_2", info8.architecture, delete_flags, info8.version),
10488 "failed to delete driver");
10490 torture_assert(tctx,
10491 remove_printer_driver(tctx, dcerpc_server_name(p), d),
10492 "failed to remove printer driver");
10494 return true;
10497 static bool test_del_driver_all_files(struct torture_context *tctx,
10498 struct dcerpc_pipe *p)
10500 struct torture_driver_context *d;
10501 struct spoolss_StringArray *a;
10502 uint32_t add_flags = APD_COPY_NEW_FILES;
10503 uint32_t delete_flags = DPD_DELETE_ALL_FILES;
10504 struct dcerpc_binding_handle *b = p->binding_handle;
10505 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10507 d = talloc_zero(tctx, struct torture_driver_context);
10509 d->ex = true;
10510 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10511 d->info8.driver_name = TORTURE_DRIVER_DELETER;
10512 d->info8.architecture = NULL;
10513 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10514 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10515 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10516 d->info8.help_file = talloc_strdup(d, "pscript.hlp");
10517 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
10518 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
10520 a = talloc_zero(d, struct spoolss_StringArray);
10521 a->string = talloc_zero_array(a, const char *, 3);
10522 a->string[0] = talloc_strdup(a->string, "cups6.inf");
10523 a->string[1] = talloc_strdup(a->string, "cups6.ini");
10525 d->info8.dependent_files = a;
10526 d->info8.architecture = d->local.environment;
10528 torture_assert(tctx,
10529 fillup_printserver_info(tctx, p, d),
10530 "failed to fillup printserver info");
10532 if (!directory_exist(d->local.driver_directory)) {
10533 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10536 torture_assert(tctx,
10537 upload_printer_driver(tctx, dcerpc_server_name(p), d),
10538 "failed to upload printer driver");
10540 torture_assert(tctx,
10541 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d->info8, add_flags, true, NULL),
10542 "failed to add driver");
10544 torture_assert(tctx,
10545 test_DeletePrinterDriverEx(tctx, b, server_name_slash,
10546 d->info8.driver_name,
10547 d->local.environment,
10548 delete_flags,
10549 d->info8.version),
10550 "failed to delete driver");
10552 torture_assert(tctx,
10553 check_printer_driver_files(tctx, dcerpc_server_name(p), d, false),
10554 "printer driver file check failed");
10556 talloc_free(d);
10557 return true;
10560 static bool test_del_driver_unused_files(struct torture_context *tctx,
10561 struct dcerpc_pipe *p)
10563 struct torture_driver_context *d1;
10564 struct torture_driver_context *d2;
10565 uint32_t add_flags = APD_COPY_NEW_FILES;
10566 struct dcerpc_binding_handle *b = p->binding_handle;
10567 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10569 d1 = talloc_zero(tctx, struct torture_driver_context);
10570 d1->ex = true;
10571 d1->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10572 d1->info8.driver_name = TORTURE_DRIVER_DELETER;
10573 d1->info8.architecture = NULL;
10574 d1->info8.driver_path = talloc_strdup(d1, "pscript5.dll");
10575 d1->info8.data_file = talloc_strdup(d1, "cups6.ppd");
10576 d1->info8.config_file = talloc_strdup(d1, "cupsui6.dll");
10577 d1->info8.help_file = talloc_strdup(d1, "pscript.hlp");
10578 d1->local.environment = talloc_strdup(d1, SPOOLSS_ARCHITECTURE_x64);
10579 d1->local.driver_directory = talloc_strdup(d1, "/usr/share/cups/drivers/x64");
10580 d1->info8.architecture = d1->local.environment;
10582 d2 = talloc_zero(tctx, struct torture_driver_context);
10583 d2->ex = true;
10584 d2->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10585 d2->info8.driver_name = TORTURE_DRIVER_DELETERIN;
10586 d2->info8.architecture = NULL;
10587 d2->info8.driver_path = talloc_strdup(d2, "pscript5.dll"); /* overlapping */
10588 d2->info8.data_file = talloc_strdup(d2, "cupsps6.dll");
10589 d2->info8.config_file = talloc_strdup(d2, "cups6.ini");
10590 d2->info8.help_file = talloc_strdup(d2, "pscript.hlp"); /* overlapping */
10591 d2->local.environment = talloc_strdup(d2, SPOOLSS_ARCHITECTURE_x64);
10592 d2->local.driver_directory = talloc_strdup(d2, "/usr/share/cups/drivers/x64");
10593 d2->info8.architecture = d2->local.environment;
10595 torture_assert(tctx,
10596 fillup_printserver_info(tctx, p, d1),
10597 "failed to fillup printserver info");
10598 torture_assert(tctx,
10599 fillup_printserver_info(tctx, p, d2),
10600 "failed to fillup printserver info");
10602 if (!directory_exist(d1->local.driver_directory)) {
10603 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10606 torture_assert(tctx,
10607 upload_printer_driver(tctx, dcerpc_server_name(p), d1),
10608 "failed to upload printer driver");
10609 torture_assert(tctx,
10610 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d1->info8, add_flags, true, NULL),
10611 "failed to add driver");
10613 torture_assert(tctx,
10614 upload_printer_driver(tctx, dcerpc_server_name(p), d2),
10615 "failed to upload printer driver");
10616 torture_assert(tctx,
10617 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d2->info8, add_flags, true, NULL),
10618 "failed to add driver");
10620 /* some files are in use by a separate driver, should fail */
10621 torture_assert(tctx,
10622 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10623 d1->info8.driver_name,
10624 d1->local.environment,
10625 DPD_DELETE_ALL_FILES,
10626 d1->info8.version,
10627 WERR_PRINTER_DRIVER_IN_USE),
10628 "invalid delete driver response");
10630 /* should only delete files not in use by other driver */
10631 torture_assert(tctx,
10632 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10633 d1->info8.driver_name,
10634 d1->local.environment,
10635 DPD_DELETE_UNUSED_FILES,
10636 d1->info8.version,
10637 WERR_OK),
10638 "failed to delete driver (unused files)");
10640 /* check non-overlapping were deleted */
10641 d1->info8.driver_path = NULL;
10642 d1->info8.help_file = NULL;
10643 torture_assert(tctx,
10644 check_printer_driver_files(tctx, dcerpc_server_name(p), d1, false),
10645 "printer driver file check failed");
10646 /* d2 files should be uneffected */
10647 torture_assert(tctx,
10648 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, true),
10649 "printer driver file check failed");
10651 torture_assert(tctx,
10652 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10653 d2->info8.driver_name,
10654 d2->local.environment,
10655 DPD_DELETE_ALL_FILES,
10656 d2->info8.version,
10657 WERR_OK),
10658 "failed to delete driver");
10660 torture_assert(tctx,
10661 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, false),
10662 "printer driver file check failed");
10664 talloc_free(d1);
10665 talloc_free(d2);
10666 return true;
10669 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
10671 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
10673 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
10674 "driver", &ndr_table_spoolss);
10675 torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
10676 torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
10678 torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
10679 torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
10681 torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
10683 torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
10685 torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
10687 torture_rpc_tcase_add_test(tcase, "multiple_drivers", test_multiple_drivers);
10689 torture_rpc_tcase_add_test(tcase, "del_driver_all_files", test_del_driver_all_files);
10691 torture_rpc_tcase_add_test(tcase, "del_driver_unused_files", test_del_driver_unused_files);
10693 return suite;