s4-torture: add test for spoolss_RpcEnumJobNamedProperties.
[Samba/gebeck_regimport.git] / source4 / torture / rpc / spoolss.c
blob5b24b1575657dc39d3ad00818b005dd998f78c79
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[8];
81 union spoolss_DriverInfo *drivers[8];
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_args(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 *count_p,
522 union spoolss_DriverInfo **info_p)
524 struct spoolss_EnumPrinterDrivers r;
525 uint32_t needed;
526 uint32_t count;
527 union spoolss_DriverInfo *info;
529 r.in.server = server_name;
530 r.in.environment = environment;
531 r.in.level = level;
532 r.in.buffer = NULL;
533 r.in.offered = 0;
534 r.out.needed = &needed;
535 r.out.count = &count;
536 r.out.info = &info;
538 torture_comment(tctx, "Testing EnumPrinterDrivers(%s) level %u\n",
539 r.in.environment, r.in.level);
541 torture_assert_ntstatus_ok(tctx,
542 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
543 "EnumPrinterDrivers failed");
544 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
545 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
546 r.in.buffer = &blob;
547 r.in.offered = needed;
549 torture_assert_ntstatus_ok(tctx,
550 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
551 "EnumPrinterDrivers failed");
554 torture_assert_werr_ok(tctx, r.out.result,
555 "EnumPrinterDrivers failed");
557 if (count_p) {
558 *count_p = count;
560 if (info_p) {
561 *info_p = info;
564 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, needed, 4);
566 return true;
570 static bool test_EnumPrinterDrivers_findone(struct torture_context *tctx,
571 struct dcerpc_binding_handle *b,
572 const char *server_name,
573 const char *environment,
574 uint32_t level,
575 const char *driver_name,
576 union spoolss_DriverInfo *info_p)
578 uint32_t count;
579 union spoolss_DriverInfo *info;
580 int i;
581 const char *environment_ret = NULL;
583 torture_assert(tctx,
584 test_EnumPrinterDrivers_args(tctx, b, server_name, environment, level, &count, &info),
585 "failed to enumerate printer drivers");
587 for (i=0; i < count; i++) {
588 const char *driver_name_ret;
589 switch (level) {
590 case 1:
591 driver_name_ret = info[i].info1.driver_name;
592 break;
593 case 2:
594 driver_name_ret = info[i].info2.driver_name;
595 environment_ret = info[i].info2.architecture;
596 break;
597 case 3:
598 driver_name_ret = info[i].info3.driver_name;
599 environment_ret = info[i].info3.architecture;
600 break;
601 case 4:
602 driver_name_ret = info[i].info4.driver_name;
603 environment_ret = info[i].info4.architecture;
604 break;
605 case 5:
606 driver_name_ret = info[i].info5.driver_name;
607 environment_ret = info[i].info5.architecture;
608 break;
609 case 6:
610 driver_name_ret = info[i].info6.driver_name;
611 environment_ret = info[i].info6.architecture;
612 break;
613 case 7:
614 driver_name_ret = info[i].info7.driver_name;
615 break;
616 case 8:
617 driver_name_ret = info[i].info8.driver_name;
618 environment_ret = info[i].info8.architecture;
619 break;
620 default:
621 break;
623 if (environment_ret) {
624 torture_assert_str_equal(tctx, environment, environment_ret, "architecture mismatch");
626 if (strequal(driver_name, driver_name_ret)) {
627 if (info_p) {
628 *info_p = info[i];
630 return true;
634 return false;
637 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
638 void *private_data)
640 struct test_spoolss_context *ctx =
641 talloc_get_type_abort(private_data, struct test_spoolss_context);
642 struct dcerpc_pipe *p = ctx->spoolss_pipe;
643 struct dcerpc_binding_handle *b = p->binding_handle;
644 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
645 int i, j, a;
647 /* FIXME: gd, come back and fix "" as server, and handle
648 * priority of returned error codes in torture test and samba 3
649 * server */
650 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
651 const char *environments[2];
653 environments[0] = SPOOLSS_ARCHITECTURE_ALL;
654 environments[1] = ctx->environment;
656 for (a=0;a<ARRAY_SIZE(environments);a++) {
658 for (i=0;i<ARRAY_SIZE(levels);i++) {
659 int level = levels[i];
660 uint32_t count;
661 union spoolss_DriverInfo *info;
663 torture_assert(tctx,
664 test_EnumPrinterDrivers_args(tctx, b, server_name, environments[a], level, &count, &info),
665 "failed to enumerate drivers");
667 ctx->driver_count[level] = count;
668 ctx->drivers[level] = info;
671 for (i=1;i<ARRAY_SIZE(levels);i++) {
672 int level = levels[i];
673 int old_level = levels[i-1];
675 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
676 "EnumPrinterDrivers invalid value");
679 for (i=0;i<ARRAY_SIZE(levels);i++) {
680 int level = levels[i];
682 for (j=0;j<ctx->driver_count[level - 1];j++) {
683 union spoolss_DriverInfo *cur = &ctx->drivers[level - 1][j];
684 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
686 switch (level) {
687 case 1:
688 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
689 break;
690 case 2:
691 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
692 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
693 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
694 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
695 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
696 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
697 break;
698 case 3:
699 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
700 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
701 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
702 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
703 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
704 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
705 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
706 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
707 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
708 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
709 break;
710 case 4:
711 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
712 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
713 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
714 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
715 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
716 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
717 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
718 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
719 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
720 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
721 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
722 break;
723 case 5:
724 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
725 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
726 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
727 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
728 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
729 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
730 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
731 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
732 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
733 break;
734 case 6:
735 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
736 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
737 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
738 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
739 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
740 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
741 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
742 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
743 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
744 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
745 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
746 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
747 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
748 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
749 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
750 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
751 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
752 break;
753 case 8:
754 /* level 8 is our reference, and it makes no sense to compare it to itself */
755 break;
761 return true;
764 static bool test_EnumMonitors(struct torture_context *tctx,
765 void *private_data)
767 struct test_spoolss_context *ctx =
768 talloc_get_type_abort(private_data, struct test_spoolss_context);
769 struct dcerpc_pipe *p = ctx->spoolss_pipe;
770 struct dcerpc_binding_handle *b = p->binding_handle;
771 NTSTATUS status;
772 struct spoolss_EnumMonitors r;
773 uint16_t levels[] = { 1, 2 };
774 int i, j;
776 for (i=0;i<ARRAY_SIZE(levels);i++) {
777 int level = levels[i];
778 DATA_BLOB blob;
779 uint32_t needed;
780 uint32_t count;
781 union spoolss_MonitorInfo *info;
783 r.in.servername = "";
784 r.in.level = level;
785 r.in.buffer = NULL;
786 r.in.offered = 0;
787 r.out.needed = &needed;
788 r.out.count = &count;
789 r.out.info = &info;
791 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
793 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
794 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
795 if (W_ERROR_IS_OK(r.out.result)) {
796 /* TODO: do some more checks here */
797 continue;
799 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
800 "EnumMonitors failed");
802 blob = data_blob_talloc_zero(ctx, needed);
803 r.in.buffer = &blob;
804 r.in.offered = needed;
806 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
807 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
809 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
811 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, needed, 4);
813 ctx->monitor_count[level] = count;
814 ctx->monitors[level] = info;
817 for (i=1;i<ARRAY_SIZE(levels);i++) {
818 int level = levels[i];
819 int old_level = levels[i-1];
820 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
821 "EnumMonitors invalid value");
824 for (i=0;i<ARRAY_SIZE(levels);i++) {
825 int level = levels[i];
826 for (j=0;j<ctx->monitor_count[level];j++) {
827 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
828 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
829 switch (level) {
830 case 1:
831 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
832 break;
833 case 2:
834 /* level 2 is our reference, and it makes no sense to compare it to itself */
835 break;
840 return true;
843 static bool test_EnumPrintProcessors_level(struct torture_context *tctx,
844 struct dcerpc_binding_handle *b,
845 const char *environment,
846 uint32_t level,
847 uint32_t *count_p,
848 union spoolss_PrintProcessorInfo **info_p,
849 WERROR expected_result)
851 struct spoolss_EnumPrintProcessors r;
852 DATA_BLOB blob;
853 uint32_t needed;
854 uint32_t count;
855 union spoolss_PrintProcessorInfo *info;
857 r.in.servername = "";
858 r.in.environment = environment;
859 r.in.level = level;
860 r.in.buffer = NULL;
861 r.in.offered = 0;
862 r.out.needed = &needed;
863 r.out.count = &count;
864 r.out.info = &info;
866 torture_comment(tctx, "Testing EnumPrintProcessors(%s) level %u\n",
867 r.in.environment, r.in.level);
869 torture_assert_ntstatus_ok(tctx,
870 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
871 "EnumPrintProcessors failed");
872 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
873 blob = data_blob_talloc_zero(tctx, needed);
874 r.in.buffer = &blob;
875 r.in.offered = needed;
876 torture_assert_ntstatus_ok(tctx,
877 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
878 "EnumPrintProcessors failed");
880 torture_assert_werr_equal(tctx, r.out.result, expected_result,
881 "EnumPrintProcessors failed");
883 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, level, count, needed, 4);
885 if (count_p) {
886 *count_p = count;
888 if (info_p) {
889 *info_p = info;
892 return true;
895 static bool test_EnumPrintProcessors(struct torture_context *tctx,
896 void *private_data)
898 struct test_spoolss_context *ctx =
899 talloc_get_type_abort(private_data, struct test_spoolss_context);
901 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
902 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
903 int i;
904 struct dcerpc_pipe *p = ctx->spoolss_pipe;
905 struct dcerpc_binding_handle *b = p->binding_handle;
907 torture_assert(tctx,
908 test_EnumPrintProcessors_level(tctx, b, "phantasy", 1, NULL, NULL, WERR_INVALID_ENVIRONMENT),
909 "test_EnumPrintProcessors_level failed");
911 for (i=0;i<ARRAY_SIZE(levels);i++) {
912 union spoolss_PrintProcessorInfo *info;
913 uint32_t count;
914 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
916 torture_assert(tctx,
917 test_EnumPrintProcessors_level(tctx, b, ctx->environment, levels[i], &count, &info, expected_result),
918 "test_EnumPrintProcessors_level failed");
921 return true;
924 static bool test_EnumPrintProcDataTypes_level(struct torture_context *tctx,
925 struct dcerpc_binding_handle *b,
926 const char *print_processor_name,
927 uint32_t level,
928 uint32_t *count_p,
929 union spoolss_PrintProcDataTypesInfo **info_p,
930 WERROR expected_result)
932 struct spoolss_EnumPrintProcDataTypes r;
933 DATA_BLOB blob;
934 uint32_t needed;
935 uint32_t count;
936 union spoolss_PrintProcDataTypesInfo *info;
938 r.in.servername = "";
939 r.in.print_processor_name = print_processor_name;
940 r.in.level = level;
941 r.in.buffer = NULL;
942 r.in.offered = 0;
943 r.out.needed = &needed;
944 r.out.count = &count;
945 r.out.info = &info;
947 torture_comment(tctx, "Testing EnumPrintProcDataTypes(%s) level %u\n",
948 r.in.print_processor_name, r.in.level);
950 torture_assert_ntstatus_ok(tctx,
951 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
952 "EnumPrintProcDataTypes failed");
953 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
954 blob = data_blob_talloc_zero(tctx, needed);
955 r.in.buffer = &blob;
956 r.in.offered = needed;
957 torture_assert_ntstatus_ok(tctx,
958 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
959 "EnumPrintProcDataTypes failed");
961 torture_assert_werr_equal(tctx, r.out.result, expected_result,
962 "EnumPrintProcDataTypes failed");
964 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, level, count, needed, 4);
966 if (count_p) {
967 *count_p = count;
969 if (info_p) {
970 *info_p = info;
973 return true;
976 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
977 void *private_data)
979 struct test_spoolss_context *ctx =
980 talloc_get_type_abort(private_data, struct test_spoolss_context);
982 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
983 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
984 int i;
985 struct dcerpc_pipe *p = ctx->spoolss_pipe;
986 struct dcerpc_binding_handle *b = p->binding_handle;
988 torture_assert(tctx,
989 test_EnumPrintProcDataTypes_level(tctx, b, NULL, 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
990 "test_EnumPrintProcDataTypes_level failed");
992 torture_assert(tctx,
993 test_EnumPrintProcDataTypes_level(tctx, b, "nonexisting", 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
994 "test_EnumPrintProcDataTypes_level failed");
996 for (i=0;i<ARRAY_SIZE(levels);i++) {
997 int level = levels[i];
998 uint32_t count;
999 union spoolss_PrintProcDataTypesInfo *info;
1000 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
1002 torture_assert(tctx,
1003 test_EnumPrintProcDataTypes_level(tctx, b, "winprint", level, &count, &info, expected_result),
1004 "test_EnumPrintProcDataTypes_level failed");
1008 union spoolss_PrintProcessorInfo *info;
1009 uint32_t count;
1011 torture_assert(tctx,
1012 test_EnumPrintProcessors_level(tctx, b, ctx->environment, 1, &count, &info, WERR_OK),
1013 "test_EnumPrintProcessors_level failed");
1015 for (i=0; i < count; i++) {
1016 torture_assert(tctx,
1017 test_EnumPrintProcDataTypes_level(tctx, b, info[i].info1.print_processor_name, 1, NULL, NULL, WERR_OK),
1018 "test_EnumPrintProcDataTypes_level failed");
1023 return true;
1026 static bool test_EnumPrinters(struct torture_context *tctx,
1027 void *private_data)
1029 struct test_spoolss_context *ctx =
1030 talloc_get_type_abort(private_data, struct test_spoolss_context);
1031 struct dcerpc_pipe *p = ctx->spoolss_pipe;
1032 struct dcerpc_binding_handle *b = p->binding_handle;
1033 struct spoolss_EnumPrinters r;
1034 NTSTATUS status;
1035 uint16_t levels[] = { 0, 1, 2, 4, 5 };
1036 int i, j;
1038 for (i=0;i<ARRAY_SIZE(levels);i++) {
1039 int level = levels[i];
1040 DATA_BLOB blob;
1041 uint32_t needed;
1042 uint32_t count;
1043 union spoolss_PrinterInfo *info;
1045 r.in.flags = PRINTER_ENUM_LOCAL;
1046 r.in.server = "";
1047 r.in.level = level;
1048 r.in.buffer = NULL;
1049 r.in.offered = 0;
1050 r.out.needed = &needed;
1051 r.out.count = &count;
1052 r.out.info = &info;
1054 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1056 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1057 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1058 if (W_ERROR_IS_OK(r.out.result)) {
1059 /* TODO: do some more checks here */
1060 continue;
1062 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
1063 "EnumPrinters unexpected return code");
1065 blob = data_blob_talloc_zero(ctx, needed);
1066 r.in.buffer = &blob;
1067 r.in.offered = needed;
1069 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1070 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1072 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1074 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
1076 ctx->printer_count[level] = count;
1077 ctx->printers[level] = info;
1080 for (i=1;i<ARRAY_SIZE(levels);i++) {
1081 int level = levels[i];
1082 int old_level = levels[i-1];
1083 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
1084 "EnumPrinters invalid value");
1087 for (i=0;i<ARRAY_SIZE(levels);i++) {
1088 int level = levels[i];
1089 for (j=0;j<ctx->printer_count[level];j++) {
1090 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
1091 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
1092 switch (level) {
1093 case 0:
1094 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
1095 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
1096 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
1097 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
1098 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
1099 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
1100 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
1101 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
1102 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
1103 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
1104 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
1105 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
1106 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
1107 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
1108 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
1109 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
1110 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
1111 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
1112 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
1113 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
1114 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
1115 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
1116 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
1117 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
1118 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
1119 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
1120 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
1121 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
1122 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
1123 break;
1124 case 1:
1125 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
1126 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
1127 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
1128 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
1129 break;
1130 case 2:
1131 /* level 2 is our reference, and it makes no sense to compare it to itself */
1132 break;
1133 case 4:
1134 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
1135 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
1136 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
1137 break;
1138 case 5:
1139 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
1140 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
1141 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
1142 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
1143 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
1144 break;
1149 /* TODO:
1150 * - verify that the port of a printer was in the list returned by EnumPorts
1153 return true;
1156 static bool test_GetPrinterDriver2(struct torture_context *tctx,
1157 struct dcerpc_binding_handle *b,
1158 struct policy_handle *handle,
1159 const char *driver_name,
1160 const char *environment);
1162 bool test_GetPrinter_level(struct torture_context *tctx,
1163 struct dcerpc_binding_handle *b,
1164 struct policy_handle *handle,
1165 uint32_t level,
1166 union spoolss_PrinterInfo *info)
1168 struct spoolss_GetPrinter r;
1169 uint32_t needed;
1171 r.in.handle = handle;
1172 r.in.level = level;
1173 r.in.buffer = NULL;
1174 r.in.offered = 0;
1175 r.out.needed = &needed;
1177 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
1179 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1180 "GetPrinter failed");
1182 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1183 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
1184 r.in.buffer = &blob;
1185 r.in.offered = needed;
1187 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1188 "GetPrinter failed");
1191 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
1193 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, needed, 4);
1195 if (info && r.out.info) {
1196 *info = *r.out.info;
1199 return true;
1203 static bool test_GetPrinter(struct torture_context *tctx,
1204 struct dcerpc_binding_handle *b,
1205 struct policy_handle *handle,
1206 const char *environment)
1208 uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1209 int i;
1211 for (i=0;i<ARRAY_SIZE(levels);i++) {
1213 union spoolss_PrinterInfo info;
1215 ZERO_STRUCT(info);
1217 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
1218 "failed to call GetPrinter");
1220 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
1221 torture_assert(tctx,
1222 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
1223 "failed to call test_GetPrinterDriver2");
1227 return true;
1230 static bool test_SetPrinter(struct torture_context *tctx,
1231 struct dcerpc_binding_handle *b,
1232 struct policy_handle *handle,
1233 struct spoolss_SetPrinterInfoCtr *info_ctr,
1234 struct spoolss_DevmodeContainer *devmode_ctr,
1235 struct sec_desc_buf *secdesc_ctr,
1236 enum spoolss_PrinterControl command)
1238 struct spoolss_SetPrinter r;
1240 r.in.handle = handle;
1241 r.in.info_ctr = info_ctr;
1242 r.in.devmode_ctr = devmode_ctr;
1243 r.in.secdesc_ctr = secdesc_ctr;
1244 r.in.command = command;
1246 torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1248 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1249 "failed to call SetPrinter");
1250 torture_assert_werr_ok(tctx, r.out.result,
1251 "failed to call SetPrinter");
1253 return true;
1256 static bool test_SetPrinter_errors(struct torture_context *tctx,
1257 struct dcerpc_binding_handle *b,
1258 struct policy_handle *handle)
1260 struct spoolss_SetPrinter r;
1261 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1262 int i;
1264 struct spoolss_SetPrinterInfoCtr info_ctr;
1265 struct spoolss_DevmodeContainer devmode_ctr;
1266 struct sec_desc_buf secdesc_ctr;
1268 info_ctr.level = 0;
1269 info_ctr.info.info0 = NULL;
1271 ZERO_STRUCT(devmode_ctr);
1272 ZERO_STRUCT(secdesc_ctr);
1274 r.in.handle = handle;
1275 r.in.info_ctr = &info_ctr;
1276 r.in.devmode_ctr = &devmode_ctr;
1277 r.in.secdesc_ctr = &secdesc_ctr;
1278 r.in.command = 0;
1280 torture_comment(tctx, "Testing SetPrinter all zero\n");
1282 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1283 "failed to call SetPrinter");
1284 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1285 "failed to call SetPrinter");
1287 again:
1288 for (i=0; i < ARRAY_SIZE(levels); i++) {
1290 struct spoolss_SetPrinterInfo0 info0;
1291 struct spoolss_SetPrinterInfo1 info1;
1292 struct spoolss_SetPrinterInfo2 info2;
1293 struct spoolss_SetPrinterInfo3 info3;
1294 struct spoolss_SetPrinterInfo4 info4;
1295 struct spoolss_SetPrinterInfo5 info5;
1296 struct spoolss_SetPrinterInfo6 info6;
1297 struct spoolss_SetPrinterInfo7 info7;
1298 struct spoolss_SetPrinterInfo8 info8;
1299 struct spoolss_SetPrinterInfo9 info9;
1302 info_ctr.level = levels[i];
1303 switch (levels[i]) {
1304 case 0:
1305 ZERO_STRUCT(info0);
1306 info_ctr.info.info0 = &info0;
1307 break;
1308 case 1:
1309 ZERO_STRUCT(info1);
1310 info_ctr.info.info1 = &info1;
1311 break;
1312 case 2:
1313 ZERO_STRUCT(info2);
1314 info_ctr.info.info2 = &info2;
1315 break;
1316 case 3:
1317 ZERO_STRUCT(info3);
1318 info_ctr.info.info3 = &info3;
1319 break;
1320 case 4:
1321 ZERO_STRUCT(info4);
1322 info_ctr.info.info4 = &info4;
1323 break;
1324 case 5:
1325 ZERO_STRUCT(info5);
1326 info_ctr.info.info5 = &info5;
1327 break;
1328 case 6:
1329 ZERO_STRUCT(info6);
1330 info_ctr.info.info6 = &info6;
1331 break;
1332 case 7:
1333 ZERO_STRUCT(info7);
1334 info_ctr.info.info7 = &info7;
1335 break;
1336 case 8:
1337 ZERO_STRUCT(info8);
1338 info_ctr.info.info8 = &info8;
1339 break;
1340 case 9:
1341 ZERO_STRUCT(info9);
1342 info_ctr.info.info9 = &info9;
1343 break;
1346 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1347 info_ctr.level, r.in.command);
1349 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1350 "failed to call SetPrinter");
1352 switch (r.in.command) {
1353 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1354 /* is ignored for all levels other then 0 */
1355 if (info_ctr.level > 0) {
1356 /* ignored then */
1357 break;
1359 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1360 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1361 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1362 if (info_ctr.level > 0) {
1363 /* is invalid for all levels other then 0 */
1364 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1365 "unexpected error code returned");
1366 continue;
1367 } else {
1368 torture_assert_werr_ok(tctx, r.out.result,
1369 "failed to call SetPrinter with non 0 command");
1370 continue;
1372 break;
1374 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1375 /* FIXME: gd needs further investigation */
1376 default:
1377 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1378 "unexpected error code returned");
1379 continue;
1382 switch (info_ctr.level) {
1383 case 1:
1384 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1385 "unexpected error code returned");
1386 break;
1387 case 2:
1388 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1389 "unexpected error code returned");
1390 break;
1391 case 3:
1392 case 4:
1393 case 5:
1394 case 7:
1395 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1396 "unexpected error code returned");
1397 break;
1398 case 9:
1399 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1400 "unexpected error code returned");
1401 break;
1402 default:
1403 torture_assert_werr_ok(tctx, r.out.result,
1404 "failed to call SetPrinter");
1405 break;
1409 if (r.in.command < 5) {
1410 r.in.command++;
1411 goto again;
1414 return true;
1417 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1419 if ((r->level == 2) && (r->info.info2)) {
1420 r->info.info2->secdesc_ptr = NULL;
1421 r->info.info2->devmode_ptr = NULL;
1425 static bool test_PrinterInfo(struct torture_context *tctx,
1426 struct dcerpc_binding_handle *b,
1427 struct policy_handle *handle)
1429 NTSTATUS status;
1430 struct spoolss_SetPrinter s;
1431 struct spoolss_GetPrinter q;
1432 struct spoolss_GetPrinter q0;
1433 struct spoolss_SetPrinterInfoCtr info_ctr;
1434 union spoolss_PrinterInfo info;
1435 struct spoolss_DevmodeContainer devmode_ctr;
1436 struct sec_desc_buf secdesc_ctr;
1437 uint32_t needed;
1438 bool ret = true;
1439 int i;
1441 torture_skip(tctx, "Printer Info test is currently broken, skipping");
1443 uint32_t status_list[] = {
1444 /* these do not stick
1445 PRINTER_STATUS_PAUSED,
1446 PRINTER_STATUS_ERROR,
1447 PRINTER_STATUS_PENDING_DELETION, */
1448 PRINTER_STATUS_PAPER_JAM,
1449 PRINTER_STATUS_PAPER_OUT,
1450 PRINTER_STATUS_MANUAL_FEED,
1451 PRINTER_STATUS_PAPER_PROBLEM,
1452 PRINTER_STATUS_OFFLINE,
1453 PRINTER_STATUS_IO_ACTIVE,
1454 PRINTER_STATUS_BUSY,
1455 PRINTER_STATUS_PRINTING,
1456 PRINTER_STATUS_OUTPUT_BIN_FULL,
1457 PRINTER_STATUS_NOT_AVAILABLE,
1458 PRINTER_STATUS_WAITING,
1459 PRINTER_STATUS_PROCESSING,
1460 PRINTER_STATUS_INITIALIZING,
1461 PRINTER_STATUS_WARMING_UP,
1462 PRINTER_STATUS_TONER_LOW,
1463 PRINTER_STATUS_NO_TONER,
1464 PRINTER_STATUS_PAGE_PUNT,
1465 PRINTER_STATUS_USER_INTERVENTION,
1466 PRINTER_STATUS_OUT_OF_MEMORY,
1467 PRINTER_STATUS_DOOR_OPEN,
1468 PRINTER_STATUS_SERVER_UNKNOWN,
1469 PRINTER_STATUS_POWER_SAVE,
1470 /* these do not stick
1471 0x02000000,
1472 0x04000000,
1473 0x08000000,
1474 0x10000000,
1475 0x20000000,
1476 0x40000000,
1477 0x80000000 */
1479 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1480 uint32_t attribute_list[] = {
1481 PRINTER_ATTRIBUTE_QUEUED,
1482 /* fails with WERR_INVALID_DATATYPE:
1483 PRINTER_ATTRIBUTE_DIRECT, */
1484 /* does not stick
1485 PRINTER_ATTRIBUTE_DEFAULT, */
1486 PRINTER_ATTRIBUTE_SHARED,
1487 /* does not stick
1488 PRINTER_ATTRIBUTE_NETWORK, */
1489 PRINTER_ATTRIBUTE_HIDDEN,
1490 PRINTER_ATTRIBUTE_LOCAL,
1491 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1492 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1493 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1494 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1495 /* does not stick
1496 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1497 /* fails with WERR_INVALID_DATATYPE:
1498 PRINTER_ATTRIBUTE_RAW_ONLY, */
1499 /* these do not stick
1500 PRINTER_ATTRIBUTE_PUBLISHED,
1501 PRINTER_ATTRIBUTE_FAX,
1502 PRINTER_ATTRIBUTE_TS,
1503 0x00010000,
1504 0x00020000,
1505 0x00040000,
1506 0x00080000,
1507 0x00100000,
1508 0x00200000,
1509 0x00400000,
1510 0x00800000,
1511 0x01000000,
1512 0x02000000,
1513 0x04000000,
1514 0x08000000,
1515 0x10000000,
1516 0x20000000,
1517 0x40000000,
1518 0x80000000 */
1521 ZERO_STRUCT(devmode_ctr);
1522 ZERO_STRUCT(secdesc_ctr);
1524 s.in.handle = handle;
1525 s.in.command = 0;
1526 s.in.info_ctr = &info_ctr;
1527 s.in.devmode_ctr = &devmode_ctr;
1528 s.in.secdesc_ctr = &secdesc_ctr;
1530 q.in.handle = handle;
1531 q.out.info = &info;
1532 q0 = q;
1534 #define TESTGETCALL(call, r) \
1535 r.in.buffer = NULL; \
1536 r.in.offered = 0;\
1537 r.out.needed = &needed; \
1538 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1539 if (!NT_STATUS_IS_OK(status)) { \
1540 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1541 r.in.level, nt_errstr(status), __location__); \
1542 ret = false; \
1543 break; \
1545 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1546 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1547 r.in.buffer = &blob; \
1548 r.in.offered = needed; \
1550 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1551 if (!NT_STATUS_IS_OK(status)) { \
1552 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1553 r.in.level, nt_errstr(status), __location__); \
1554 ret = false; \
1555 break; \
1557 if (!W_ERROR_IS_OK(r.out.result)) { \
1558 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1559 r.in.level, win_errstr(r.out.result), __location__); \
1560 ret = false; \
1561 break; \
1565 #define TESTSETCALL_EXP(call, r, err) \
1566 clear_info2(&info_ctr);\
1567 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1568 if (!NT_STATUS_IS_OK(status)) { \
1569 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1570 r.in.info_ctr->level, nt_errstr(status), __location__); \
1571 ret = false; \
1572 break; \
1574 if (!W_ERROR_IS_OK(err)) { \
1575 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1576 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1577 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1578 ret = false; \
1580 break; \
1582 if (!W_ERROR_IS_OK(r.out.result)) { \
1583 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1584 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1585 ret = false; \
1586 break; \
1589 #define TESTSETCALL(call, r) \
1590 TESTSETCALL_EXP(call, r, WERR_OK)
1592 #define STRING_EQUAL(s1, s2, field) \
1593 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1594 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1595 #field, s2, __location__); \
1596 ret = false; \
1597 break; \
1600 #define MEM_EQUAL(s1, s2, length, field) \
1601 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1602 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1603 #field, (const char *)s2, __location__); \
1604 ret = false; \
1605 break; \
1608 #define INT_EQUAL(i1, i2, field) \
1609 if (i1 != i2) { \
1610 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1611 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1612 ret = false; \
1613 break; \
1616 #define SD_EQUAL(sd1, sd2, field) \
1617 if (!security_descriptor_equal(sd1, sd2)) { \
1618 torture_comment(tctx, "Failed to set %s (%s)\n", \
1619 #field, __location__); \
1620 ret = false; \
1621 break; \
1624 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1625 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1626 q.in.level = lvl1; \
1627 TESTGETCALL(GetPrinter, q) \
1628 info_ctr.level = lvl1; \
1629 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1630 info_ctr.info.info ## lvl1->field1 = value;\
1631 TESTSETCALL_EXP(SetPrinter, s, err) \
1632 info_ctr.info.info ## lvl1->field1 = ""; \
1633 TESTGETCALL(GetPrinter, q) \
1634 info_ctr.info.info ## lvl1->field1 = value; \
1635 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1636 q.in.level = lvl2; \
1637 TESTGETCALL(GetPrinter, q) \
1638 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1639 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1640 } while (0)
1642 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1643 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1644 } while (0);
1646 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1647 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1648 q.in.level = lvl1; \
1649 TESTGETCALL(GetPrinter, q) \
1650 info_ctr.level = lvl1; \
1651 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1652 info_ctr.info.info ## lvl1->field1 = value; \
1653 TESTSETCALL(SetPrinter, s) \
1654 info_ctr.info.info ## lvl1->field1 = 0; \
1655 TESTGETCALL(GetPrinter, q) \
1656 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1657 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1658 q.in.level = lvl2; \
1659 TESTGETCALL(GetPrinter, q) \
1660 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1661 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1662 } while (0)
1664 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1665 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1666 } while (0)
1668 q0.in.level = 0;
1669 do { TESTGETCALL(GetPrinter, q0) } while (0);
1671 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1672 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1674 /* level 0 printername does not stick */
1675 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1676 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1677 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1678 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1679 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1680 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1681 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1682 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1683 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1684 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1685 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1686 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1687 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1688 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1689 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1691 /* servername can be set but does not stick
1692 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1693 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1694 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1697 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1698 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1699 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1700 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1701 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1703 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1704 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1705 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1706 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1707 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1708 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1709 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1710 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1711 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1712 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1714 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1715 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1716 attribute_list[i],
1717 (attribute_list[i] | default_attribute)
1718 ); */
1719 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1720 attribute_list[i],
1721 (attribute_list[i] | default_attribute)
1723 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1724 attribute_list[i],
1725 (attribute_list[i] | default_attribute)
1727 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1728 attribute_list[i],
1729 (attribute_list[i] | default_attribute)
1731 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1732 attribute_list[i],
1733 (attribute_list[i] | default_attribute)
1734 ); */
1735 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1736 attribute_list[i],
1737 (attribute_list[i] | default_attribute)
1739 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1740 attribute_list[i],
1741 (attribute_list[i] | default_attribute)
1743 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1744 attribute_list[i],
1745 (attribute_list[i] | default_attribute)
1747 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1748 attribute_list[i],
1749 (attribute_list[i] | default_attribute)
1750 ); */
1751 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1752 attribute_list[i],
1753 (attribute_list[i] | default_attribute)
1755 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1756 attribute_list[i],
1757 (attribute_list[i] | default_attribute)
1759 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1760 attribute_list[i],
1761 (attribute_list[i] | default_attribute)
1765 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1766 /* level 2 sets do not stick
1767 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1768 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1769 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1770 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1771 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1772 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1775 /* priorities need to be between 0 and 99
1776 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1777 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1778 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1779 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1780 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1781 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1782 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1783 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1784 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1786 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1787 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1789 /* does not stick
1790 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1791 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1793 /* does not stick
1794 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1795 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1797 /* FIXME: gd also test devmode and secdesc behavior */
1800 /* verify composition of level 1 description field */
1801 const char *description;
1802 const char *tmp;
1804 q0.in.level = 1;
1805 do { TESTGETCALL(GetPrinter, q0) } while (0);
1807 description = talloc_strdup(tctx, q0.out.info->info1.description);
1809 q0.in.level = 2;
1810 do { TESTGETCALL(GetPrinter, q0) } while (0);
1812 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1813 q0.out.info->info2.printername,
1814 q0.out.info->info2.drivername,
1815 q0.out.info->info2.location);
1817 do { STRING_EQUAL(description, tmp, "description")} while (0);
1820 return ret;
1823 static bool test_security_descriptor_equal(struct torture_context *tctx,
1824 const struct security_descriptor *sd1,
1825 const struct security_descriptor *sd2)
1827 if (sd1 == sd2) {
1828 return true;
1831 if (!sd1 || !sd2) {
1832 torture_comment(tctx, "%s\n", __location__);
1833 return false;
1836 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1837 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1839 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1840 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1842 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1843 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1844 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1845 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1846 return false;
1848 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1849 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1850 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1851 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1852 return false;
1855 return true;
1858 static bool test_sd_set_level(struct torture_context *tctx,
1859 struct dcerpc_binding_handle *b,
1860 struct policy_handle *handle,
1861 uint32_t level,
1862 struct security_descriptor *sd)
1864 struct spoolss_SetPrinterInfoCtr info_ctr;
1865 struct spoolss_DevmodeContainer devmode_ctr;
1866 struct sec_desc_buf secdesc_ctr;
1867 union spoolss_SetPrinterInfo sinfo;
1869 ZERO_STRUCT(devmode_ctr);
1870 ZERO_STRUCT(secdesc_ctr);
1872 switch (level) {
1873 case 2: {
1874 union spoolss_PrinterInfo info;
1875 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1876 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1878 info_ctr.level = 2;
1879 info_ctr.info = sinfo;
1881 break;
1883 case 3: {
1884 struct spoolss_SetPrinterInfo3 info3;
1886 info3.sec_desc_ptr = NULL;
1888 info_ctr.level = 3;
1889 info_ctr.info.info3 = &info3;
1891 break;
1893 default:
1894 return false;
1897 secdesc_ctr.sd = sd;
1899 torture_assert(tctx,
1900 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1902 return true;
1905 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1906 struct dcerpc_binding_handle *b,
1907 struct policy_handle *handle)
1909 union spoolss_PrinterInfo info;
1910 struct security_descriptor *sd1, *sd2;
1911 int i;
1913 /* just compare level 2 and level 3 */
1915 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1917 sd1 = info.info2.secdesc;
1919 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1921 sd2 = info.info3.secdesc;
1923 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1924 "SD level 2 != SD level 3");
1927 /* query level 2, set level 2, query level 2 */
1929 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1931 sd1 = info.info2.secdesc;
1933 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1935 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1937 sd2 = info.info2.secdesc;
1938 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1939 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1940 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1943 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1944 "SD level 2 != SD level 2 after SD has been set via level 2");
1947 /* query level 2, set level 3, query level 2 */
1949 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1951 sd1 = info.info2.secdesc;
1953 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1955 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1957 sd2 = info.info2.secdesc;
1959 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1960 "SD level 2 != SD level 2 after SD has been set via level 3");
1962 /* set modified sd level 3, query level 2 */
1964 for (i=0; i < 93; i++) {
1965 struct security_ace a;
1966 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1967 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1968 a.flags = 0;
1969 a.size = 0; /* autogenerated */
1970 a.access_mask = 0;
1971 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1972 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1975 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1977 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1978 sd2 = info.info2.secdesc;
1980 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1981 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1982 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1985 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1986 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1989 return true;
1993 * wrapper call that saves original sd, runs tests, and restores sd
1996 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1997 struct dcerpc_binding_handle *b,
1998 struct policy_handle *handle)
2000 union spoolss_PrinterInfo info;
2001 struct security_descriptor *sd;
2002 bool ret = true;
2004 torture_comment(tctx, "Testing Printer Security Descriptors\n");
2006 /* save original sd */
2008 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
2009 "failed to get initial security descriptor");
2011 sd = security_descriptor_copy(tctx, info.info2.secdesc);
2013 /* run tests */
2015 ret = test_PrinterInfo_SDs(tctx, b, handle);
2017 /* restore original sd */
2019 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
2020 "failed to restore initial security descriptor");
2022 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
2023 ret ? "succeeded" : "failed");
2026 return ret;
2029 static bool test_devmode_set_level(struct torture_context *tctx,
2030 struct dcerpc_binding_handle *b,
2031 struct policy_handle *handle,
2032 uint32_t level,
2033 struct spoolss_DeviceMode *devmode)
2035 struct spoolss_SetPrinterInfoCtr info_ctr;
2036 struct spoolss_DevmodeContainer devmode_ctr;
2037 struct sec_desc_buf secdesc_ctr;
2038 union spoolss_SetPrinterInfo sinfo;
2040 ZERO_STRUCT(devmode_ctr);
2041 ZERO_STRUCT(secdesc_ctr);
2043 switch (level) {
2044 case 2: {
2045 union spoolss_PrinterInfo info;
2046 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2047 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
2049 info_ctr.level = 2;
2050 info_ctr.info = sinfo;
2052 break;
2054 case 8: {
2055 struct spoolss_SetPrinterInfo8 info8;
2057 info8.devmode_ptr = NULL;
2059 info_ctr.level = 8;
2060 info_ctr.info.info8 = &info8;
2062 break;
2064 default:
2065 return false;
2068 devmode_ctr.devmode = devmode;
2070 torture_assert(tctx,
2071 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
2073 return true;
2077 static bool test_devicemode_equal(struct torture_context *tctx,
2078 const struct spoolss_DeviceMode *d1,
2079 const struct spoolss_DeviceMode *d2)
2081 if (d1 == d2) {
2082 return true;
2085 if (!d1 || !d2) {
2086 torture_comment(tctx, "%s\n", __location__);
2087 return false;
2089 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
2090 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
2091 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
2092 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
2093 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
2094 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
2095 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
2096 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
2097 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
2098 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
2099 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
2100 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
2101 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
2102 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2103 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2104 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2105 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2106 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2107 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2108 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2109 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2110 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2111 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2112 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2113 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2114 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2115 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2116 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2117 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2118 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2119 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2120 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2121 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2122 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2123 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2125 return true;
2128 static bool test_devicemode_full(struct torture_context *tctx,
2129 struct dcerpc_binding_handle *b,
2130 struct policy_handle *handle)
2132 struct spoolss_SetPrinter s;
2133 struct spoolss_GetPrinter q;
2134 struct spoolss_GetPrinter q0;
2135 struct spoolss_SetPrinterInfoCtr info_ctr;
2136 struct spoolss_SetPrinterInfo8 info8;
2137 union spoolss_PrinterInfo info;
2138 struct spoolss_DevmodeContainer devmode_ctr;
2139 struct sec_desc_buf secdesc_ctr;
2140 uint32_t needed;
2141 bool ret = true;
2142 NTSTATUS status;
2144 #define TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, exp_value, expected_result) do { \
2145 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2146 q.in.level = lvl1; \
2147 TESTGETCALL(GetPrinter, q) \
2148 info_ctr.level = lvl1; \
2149 if (lvl1 == 2) {\
2150 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
2151 } else if (lvl1 == 8) {\
2152 info_ctr.info.info ## lvl1 = &info8; \
2154 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2155 devmode_ctr.devmode->field1 = value; \
2156 TESTSETCALL_EXP(SetPrinter, s, expected_result) \
2157 if (W_ERROR_IS_OK(expected_result)) { \
2158 TESTGETCALL(GetPrinter, q) \
2159 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2160 q.in.level = lvl2; \
2161 TESTGETCALL(GetPrinter, q) \
2162 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2164 } while (0)
2166 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, expected_result) do { \
2167 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, expected_result); \
2168 } while (0)
2170 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2171 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, WERR_OK); \
2172 } while (0)
2174 ZERO_STRUCT(devmode_ctr);
2175 ZERO_STRUCT(secdesc_ctr);
2176 ZERO_STRUCT(info8);
2178 s.in.handle = handle;
2179 s.in.command = 0;
2180 s.in.info_ctr = &info_ctr;
2181 s.in.devmode_ctr = &devmode_ctr;
2182 s.in.secdesc_ctr = &secdesc_ctr;
2184 q.in.handle = handle;
2185 q.out.info = &info;
2186 q0 = q;
2188 #if 0
2189 const char *devicename;/* [charset(UTF16)] */
2190 enum spoolss_DeviceModeSpecVersion specversion;
2191 uint16_t driverversion;
2192 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2193 uint32_t fields;
2194 #endif
2195 TEST_DEVMODE_INT_EXP(8, size, 8, size, __LINE__, WERR_INVALID_PARAM);
2196 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0, WERR_INVALID_PARAM);
2197 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0xffff, WERR_INVALID_PARAM);
2198 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);
2199 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2201 devmode_ctr.devmode->driverextra_data = data_blob_string_const("foobar");
2202 torture_assert(tctx,
2203 test_devmode_set_level(tctx, b, handle, 8, devmode_ctr.devmode),
2204 "failed to set devmode");
2206 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);
2207 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2209 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
2210 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
2211 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
2212 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
2213 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
2214 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
2215 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
2216 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
2217 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
2218 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
2219 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
2220 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
2221 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
2222 #if 0
2223 const char *formname;/* [charset(UTF16)] */
2224 #endif
2225 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
2226 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
2227 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
2228 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
2229 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
2230 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
2231 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
2232 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
2233 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
2234 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
2235 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
2236 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
2237 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
2238 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
2240 return ret;
2243 static bool call_OpenPrinterEx(struct torture_context *tctx,
2244 struct dcerpc_pipe *p,
2245 const char *name,
2246 struct spoolss_DeviceMode *devmode,
2247 struct policy_handle *handle);
2249 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2250 struct dcerpc_pipe *p,
2251 struct policy_handle *handle,
2252 const char *name)
2254 union spoolss_PrinterInfo info;
2255 struct spoolss_DeviceMode *devmode;
2256 struct spoolss_DeviceMode *devmode2;
2257 struct policy_handle handle_devmode;
2258 struct dcerpc_binding_handle *b = p->binding_handle;
2260 /* simply compare level8 and level2 devmode */
2262 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2264 devmode = info.info8.devmode;
2266 if (devmode && devmode->size == 0) {
2267 torture_fail(tctx,
2268 "devmode of zero size!");
2271 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2273 devmode2 = info.info2.devmode;
2275 if (devmode2 && devmode2->size == 0) {
2276 torture_fail(tctx,
2277 "devmode of zero size!");
2280 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2281 "DM level 8 != DM level 2");
2284 /* set devicemode level 8 and see if it persists */
2286 devmode->copies = 93;
2287 devmode->formname = talloc_strdup(tctx, "Legal");
2289 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2291 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2293 devmode2 = info.info8.devmode;
2295 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2296 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2298 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2300 devmode2 = info.info2.devmode;
2302 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2303 "modified DM level 8 != DM level 2");
2306 /* set devicemode level 2 and see if it persists */
2308 devmode->copies = 39;
2309 devmode->formname = talloc_strdup(tctx, "Executive");
2311 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2313 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2315 devmode2 = info.info8.devmode;
2317 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2318 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2320 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2322 devmode2 = info.info2.devmode;
2324 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2325 "modified DM level 8 != DM level 2");
2328 /* check every single bit in public part of devicemode */
2330 torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2331 "failed to set every single devicemode component");
2334 /* change formname upon open and see if it persists in getprinter calls */
2336 devmode->formname = talloc_strdup(tctx, "A4");
2337 devmode->copies = 42;
2339 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2340 "failed to open printer handle");
2342 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2344 devmode2 = info.info8.devmode;
2346 if (strequal(devmode->devicename, devmode2->devicename)) {
2347 torture_warning(tctx, "devicenames are the same\n");
2348 } else {
2349 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2350 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2353 if (strequal(devmode->formname, devmode2->formname)) {
2354 torture_warning(tctx, "formname are the same\n");
2355 } else {
2356 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2357 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2360 if (devmode->copies == devmode2->copies) {
2361 torture_warning(tctx, "copies are the same\n");
2362 } else {
2363 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2364 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2367 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2369 devmode2 = info.info2.devmode;
2371 if (strequal(devmode->devicename, devmode2->devicename)) {
2372 torture_warning(tctx, "devicenames are the same\n");
2373 } else {
2374 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2375 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2378 if (strequal(devmode->formname, devmode2->formname)) {
2379 torture_warning(tctx, "formname is the same\n");
2380 } else {
2381 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2382 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2385 if (devmode->copies == devmode2->copies) {
2386 torture_warning(tctx, "copies are the same\n");
2387 } else {
2388 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2389 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2392 test_ClosePrinter(tctx, b, &handle_devmode);
2394 return true;
2398 * wrapper call that saves original devmode, runs tests, and restores devmode
2401 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2402 struct dcerpc_pipe *p,
2403 struct policy_handle *handle,
2404 const char *name,
2405 struct spoolss_DeviceMode *addprinter_devmode)
2407 union spoolss_PrinterInfo info;
2408 struct spoolss_DeviceMode *devmode;
2409 bool ret = true;
2410 struct dcerpc_binding_handle *b = p->binding_handle;
2412 torture_comment(tctx, "Testing Printer Devicemodes\n");
2414 /* save original devmode */
2416 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2417 "failed to get initial global devicemode");
2419 devmode = info.info8.devmode;
2421 if (devmode && devmode->size == 0) {
2422 torture_fail(tctx,
2423 "devmode of zero size!");
2426 if (addprinter_devmode) {
2427 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
2428 torture_warning(tctx, "current global DM is != DM provided in addprinter");
2432 /* run tests */
2434 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2436 /* restore original devmode */
2438 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2439 "failed to restore initial global device mode");
2441 torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2442 ret ? "succeeded" : "failed");
2445 return ret;
2448 bool test_ClosePrinter(struct torture_context *tctx,
2449 struct dcerpc_binding_handle *b,
2450 struct policy_handle *handle)
2452 NTSTATUS status;
2453 struct spoolss_ClosePrinter r;
2455 r.in.handle = handle;
2456 r.out.handle = handle;
2458 torture_comment(tctx, "Testing ClosePrinter\n");
2460 status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2461 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2462 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2464 return true;
2467 static bool test_GetForm_args(struct torture_context *tctx,
2468 struct dcerpc_binding_handle *b,
2469 struct policy_handle *handle,
2470 const char *form_name,
2471 uint32_t level,
2472 union spoolss_FormInfo *info_p)
2474 NTSTATUS status;
2475 struct spoolss_GetForm r;
2476 uint32_t needed;
2478 r.in.handle = handle;
2479 r.in.form_name = form_name;
2480 r.in.level = level;
2481 r.in.buffer = NULL;
2482 r.in.offered = 0;
2483 r.out.needed = &needed;
2485 torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2487 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2488 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2490 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2491 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2492 r.in.buffer = &blob;
2493 r.in.offered = needed;
2494 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2495 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2497 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2499 torture_assert(tctx, r.out.info, "No form info returned");
2502 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2504 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
2506 if (info_p) {
2507 *info_p = *r.out.info;
2510 return true;
2513 static bool test_GetForm(struct torture_context *tctx,
2514 struct dcerpc_binding_handle *b,
2515 struct policy_handle *handle,
2516 const char *form_name,
2517 uint32_t level)
2519 return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2522 static bool test_EnumForms(struct torture_context *tctx,
2523 struct dcerpc_binding_handle *b,
2524 struct policy_handle *handle,
2525 bool print_server,
2526 uint32_t level,
2527 uint32_t *count_p,
2528 union spoolss_FormInfo **info_p)
2530 struct spoolss_EnumForms r;
2531 uint32_t needed;
2532 uint32_t count;
2533 union spoolss_FormInfo *info;
2535 r.in.handle = handle;
2536 r.in.level = level;
2537 r.in.buffer = NULL;
2538 r.in.offered = 0;
2539 r.out.needed = &needed;
2540 r.out.count = &count;
2541 r.out.info = &info;
2543 torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2545 torture_assert_ntstatus_ok(tctx,
2546 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2547 "EnumForms failed");
2549 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2550 torture_skip(tctx, "EnumForms level 2 not supported");
2553 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2554 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2557 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2558 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2559 r.in.buffer = &blob;
2560 r.in.offered = needed;
2562 torture_assert_ntstatus_ok(tctx,
2563 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2564 "EnumForms failed");
2566 torture_assert(tctx, info, "No forms returned");
2569 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2571 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
2573 if (info_p) {
2574 *info_p = info;
2576 if (count_p) {
2577 *count_p = count;
2580 return true;
2583 static bool test_EnumForms_all(struct torture_context *tctx,
2584 struct dcerpc_binding_handle *b,
2585 struct policy_handle *handle,
2586 bool print_server)
2588 uint32_t levels[] = { 1, 2 };
2589 int i, j;
2591 for (i=0; i<ARRAY_SIZE(levels); i++) {
2593 uint32_t count = 0;
2594 union spoolss_FormInfo *info = NULL;
2596 torture_assert(tctx,
2597 test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2598 "failed to enum forms");
2600 for (j = 0; j < count; j++) {
2601 if (!print_server) {
2602 torture_assert(tctx,
2603 test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2604 "failed to get form");
2609 return true;
2612 static bool test_EnumForms_find_one(struct torture_context *tctx,
2613 struct dcerpc_binding_handle *b,
2614 struct policy_handle *handle,
2615 bool print_server,
2616 const char *form_name)
2618 union spoolss_FormInfo *info;
2619 uint32_t count;
2620 bool found = false;
2621 int i;
2623 torture_assert(tctx,
2624 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2625 "failed to enumerate forms");
2627 for (i=0; i<count; i++) {
2628 if (strequal(form_name, info[i].info1.form_name)) {
2629 found = true;
2630 break;
2634 return found;
2637 static bool test_DeleteForm(struct torture_context *tctx,
2638 struct dcerpc_binding_handle *b,
2639 struct policy_handle *handle,
2640 const char *form_name,
2641 WERROR expected_result)
2643 struct spoolss_DeleteForm r;
2645 r.in.handle = handle;
2646 r.in.form_name = form_name;
2648 torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2650 torture_assert_ntstatus_ok(tctx,
2651 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2652 "DeleteForm failed");
2653 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2654 "DeleteForm gave unexpected result");
2655 if (W_ERROR_IS_OK(r.out.result)) {
2656 torture_assert_ntstatus_ok(tctx,
2657 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2658 "2nd DeleteForm failed");
2659 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2660 "2nd DeleteForm failed");
2663 return true;
2666 static bool test_AddForm(struct torture_context *tctx,
2667 struct dcerpc_binding_handle *b,
2668 struct policy_handle *handle,
2669 uint32_t level,
2670 union spoolss_AddFormInfo *info,
2671 WERROR expected_result)
2673 struct spoolss_AddForm r;
2674 struct spoolss_AddFormInfoCtr info_ctr;
2676 info_ctr.level = level;
2677 info_ctr.info = *info;
2679 if (level != 1) {
2680 torture_skip(tctx, "only level 1 supported");
2683 r.in.handle = handle;
2684 r.in.info_ctr = &info_ctr;
2686 torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2687 r.in.info_ctr->info.info1->form_name, level,
2688 r.in.info_ctr->info.info1->flags);
2690 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2691 "AddForm failed");
2692 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2693 "AddForm gave unexpected result");
2695 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2696 "2nd AddForm failed");
2697 if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2698 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2699 "2nd AddForm gave unexpected result");
2700 } else {
2701 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2702 "2nd AddForm gave unexpected result");
2705 return true;
2708 static bool test_SetForm(struct torture_context *tctx,
2709 struct dcerpc_binding_handle *b,
2710 struct policy_handle *handle,
2711 const char *form_name,
2712 uint32_t level,
2713 union spoolss_AddFormInfo *info)
2715 struct spoolss_SetForm r;
2716 struct spoolss_AddFormInfoCtr info_ctr;
2718 info_ctr.level = level;
2719 info_ctr.info = *info;
2721 r.in.handle = handle;
2722 r.in.form_name = form_name;
2723 r.in.info_ctr = &info_ctr;
2725 torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2726 form_name, level);
2728 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2729 "SetForm failed");
2731 torture_assert_werr_ok(tctx, r.out.result,
2732 "SetForm failed");
2734 return true;
2737 static bool test_GetForm_winreg(struct torture_context *tctx,
2738 struct dcerpc_binding_handle *b,
2739 struct policy_handle *handle,
2740 const char *key_name,
2741 const char *form_name,
2742 enum winreg_Type *w_type,
2743 uint32_t *w_size,
2744 uint32_t *w_length,
2745 uint8_t **w_data);
2747 static bool test_Forms_args(struct torture_context *tctx,
2748 struct dcerpc_binding_handle *b,
2749 struct policy_handle *handle,
2750 bool print_server,
2751 const char *printer_name,
2752 struct dcerpc_binding_handle *winreg_handle,
2753 struct policy_handle *hive_handle,
2754 const char *form_name,
2755 struct spoolss_AddFormInfo1 *info1,
2756 WERROR expected_add_result,
2757 WERROR expected_delete_result)
2759 union spoolss_FormInfo info;
2760 union spoolss_AddFormInfo add_info;
2762 enum winreg_Type w_type;
2763 uint32_t w_size;
2764 uint32_t w_length;
2765 uint8_t *w_data;
2767 add_info.info1 = info1;
2769 torture_assert(tctx,
2770 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2771 "failed to add form");
2773 if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2775 struct spoolss_FormInfo1 i1;
2777 torture_assert(tctx,
2778 test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2779 "failed to get form via winreg");
2781 i1.size.width = IVAL(w_data, 0);
2782 i1.size.height = IVAL(w_data, 4);
2783 i1.area.left = IVAL(w_data, 8);
2784 i1.area.top = IVAL(w_data, 12);
2785 i1.area.right = IVAL(w_data, 16);
2786 i1.area.bottom = IVAL(w_data, 20);
2787 /* skip index here */
2788 i1.flags = IVAL(w_data, 28);
2790 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2791 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2792 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2793 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
2794 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
2795 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
2796 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
2797 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
2798 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2799 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
2802 if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2803 torture_assert(tctx,
2804 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2805 "failed to get added form");
2807 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2808 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2809 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2810 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2811 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2812 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2813 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2815 if (winreg_handle && hive_handle) {
2817 struct spoolss_FormInfo1 i1;
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, i1.size.width, info.info1.size.width, "width mismatch");
2829 torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
2830 torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
2831 torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
2832 torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
2833 torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
2834 torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
2837 add_info.info1->size.width = 1234;
2839 torture_assert(tctx,
2840 test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2841 "failed to set form");
2842 torture_assert(tctx,
2843 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2844 "failed to get setted form");
2846 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2849 if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2850 torture_assert(tctx,
2851 test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2852 "Newly added form not found in enum call");
2855 torture_assert(tctx,
2856 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2857 "failed to delete form");
2859 return true;
2862 static bool test_Forms(struct torture_context *tctx,
2863 struct dcerpc_binding_handle *b,
2864 struct policy_handle *handle,
2865 bool print_server,
2866 const char *printer_name,
2867 struct dcerpc_binding_handle *winreg_handle,
2868 struct policy_handle *hive_handle)
2870 const struct spoolss_FormSize size = {
2871 .width = 50,
2872 .height = 25
2874 const struct spoolss_FormArea area = {
2875 .left = 5,
2876 .top = 10,
2877 .right = 45,
2878 .bottom = 15
2880 int i;
2882 struct {
2883 struct spoolss_AddFormInfo1 info1;
2884 WERROR expected_add_result;
2885 WERROR expected_delete_result;
2886 } forms[] = {
2888 .info1 = {
2889 .flags = SPOOLSS_FORM_USER,
2890 .form_name = "testform_user",
2891 .size = size,
2892 .area = area,
2894 .expected_add_result = WERR_OK,
2895 .expected_delete_result = WERR_OK
2898 weird, we can add a builtin form but we can never remove it
2899 again - gd
2902 .info1 = {
2903 .flags = SPOOLSS_FORM_BUILTIN,
2904 .form_name = "testform_builtin",
2905 .size = size,
2906 .area = area,
2908 .expected_add_result = WERR_OK,
2909 .expected_delete_result = WERR_INVALID_PARAM,
2913 .info1 = {
2914 .flags = SPOOLSS_FORM_PRINTER,
2915 .form_name = "testform_printer",
2916 .size = size,
2917 .area = area,
2919 .expected_add_result = WERR_OK,
2920 .expected_delete_result = WERR_OK
2923 .info1 = {
2924 .flags = SPOOLSS_FORM_USER,
2925 .form_name = "Letter",
2926 .size = size,
2927 .area = area,
2929 .expected_add_result = WERR_FILE_EXISTS,
2930 .expected_delete_result = WERR_INVALID_PARAM
2933 .info1 = {
2934 .flags = SPOOLSS_FORM_BUILTIN,
2935 .form_name = "Letter",
2936 .size = size,
2937 .area = area,
2939 .expected_add_result = WERR_FILE_EXISTS,
2940 .expected_delete_result = WERR_INVALID_PARAM
2943 .info1 = {
2944 .flags = SPOOLSS_FORM_PRINTER,
2945 .form_name = "Letter",
2946 .size = size,
2947 .area = area,
2949 .expected_add_result = WERR_FILE_EXISTS,
2950 .expected_delete_result = WERR_INVALID_PARAM
2953 .info1 = {
2954 .flags = 12345,
2955 .form_name = "invalid_flags",
2956 .size = size,
2957 .area = area,
2959 .expected_add_result = WERR_INVALID_PARAM,
2960 .expected_delete_result = WERR_INVALID_FORM_NAME
2965 for (i=0; i < ARRAY_SIZE(forms); i++) {
2966 torture_assert(tctx,
2967 test_Forms_args(tctx, b, handle, print_server, printer_name,
2968 winreg_handle, hive_handle,
2969 forms[i].info1.form_name,
2970 &forms[i].info1,
2971 forms[i].expected_add_result,
2972 forms[i].expected_delete_result),
2973 talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2976 return true;
2979 static bool test_EnumPorts_old(struct torture_context *tctx,
2980 void *private_data)
2982 struct test_spoolss_context *ctx =
2983 talloc_get_type_abort(private_data, struct test_spoolss_context);
2985 NTSTATUS status;
2986 struct spoolss_EnumPorts r;
2987 uint32_t needed;
2988 uint32_t count;
2989 union spoolss_PortInfo *info;
2990 struct dcerpc_pipe *p = ctx->spoolss_pipe;
2991 struct dcerpc_binding_handle *b = p->binding_handle;
2993 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2994 dcerpc_server_name(p));
2995 r.in.level = 2;
2996 r.in.buffer = NULL;
2997 r.in.offered = 0;
2998 r.out.needed = &needed;
2999 r.out.count = &count;
3000 r.out.info = &info;
3002 torture_comment(tctx, "Testing EnumPorts\n");
3004 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3006 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3008 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3009 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3010 r.in.buffer = &blob;
3011 r.in.offered = needed;
3013 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3014 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3015 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3017 torture_assert(tctx, info, "No ports returned");
3020 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3022 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
3024 return true;
3027 static bool test_AddPort(struct torture_context *tctx,
3028 void *private_data)
3030 struct test_spoolss_context *ctx =
3031 talloc_get_type_abort(private_data, struct test_spoolss_context);
3033 NTSTATUS status;
3034 struct spoolss_AddPort r;
3035 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3036 struct dcerpc_binding_handle *b = p->binding_handle;
3038 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
3039 dcerpc_server_name(p));
3040 r.in.unknown = 0;
3041 r.in.monitor_name = "foo";
3043 torture_comment(tctx, "Testing AddPort\n");
3045 status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
3047 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
3049 /* win2k3 returns WERR_NOT_SUPPORTED */
3051 #if 0
3053 if (!W_ERROR_IS_OK(r.out.result)) {
3054 printf("AddPort failed - %s\n", win_errstr(r.out.result));
3055 return false;
3058 #endif
3060 return true;
3063 static bool test_GetJob_args(struct torture_context *tctx,
3064 struct dcerpc_binding_handle *b,
3065 struct policy_handle *handle,
3066 uint32_t job_id,
3067 uint32_t level,
3068 union spoolss_JobInfo *info_p)
3070 NTSTATUS status;
3071 struct spoolss_GetJob r;
3072 union spoolss_JobInfo info;
3073 uint32_t needed;
3075 r.in.handle = handle;
3076 r.in.job_id = job_id;
3077 r.in.level = level;
3078 r.in.buffer = NULL;
3079 r.in.offered = 0;
3080 r.out.needed = &needed;
3081 r.out.info = &info;
3083 torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
3085 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3086 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3087 if (level == 0) {
3088 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
3091 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3092 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3093 r.in.buffer = &blob;
3094 r.in.offered = needed;
3096 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3097 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3100 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
3101 torture_assert(tctx, r.out.info, "No job info returned");
3103 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
3105 if (info_p) {
3106 *info_p = *r.out.info;
3109 return true;
3112 static bool test_GetJob(struct torture_context *tctx,
3113 struct dcerpc_binding_handle *b,
3114 struct policy_handle *handle,
3115 uint32_t job_id)
3117 uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
3118 uint32_t i;
3120 for (i=0; i < ARRAY_SIZE(levels); i++) {
3121 torture_assert(tctx,
3122 test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
3123 "GetJob failed");
3126 return true;
3129 static bool test_SetJob(struct torture_context *tctx,
3130 struct dcerpc_binding_handle *b,
3131 struct policy_handle *handle,
3132 uint32_t job_id,
3133 struct spoolss_JobInfoContainer *ctr,
3134 enum spoolss_JobControl command)
3136 NTSTATUS status;
3137 struct spoolss_SetJob r;
3139 r.in.handle = handle;
3140 r.in.job_id = job_id;
3141 r.in.ctr = ctr;
3142 r.in.command = command;
3144 switch (command) {
3145 case SPOOLSS_JOB_CONTROL_PAUSE:
3146 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3147 break;
3148 case SPOOLSS_JOB_CONTROL_RESUME:
3149 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3150 break;
3151 case SPOOLSS_JOB_CONTROL_CANCEL:
3152 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3153 break;
3154 case SPOOLSS_JOB_CONTROL_RESTART:
3155 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3156 break;
3157 case SPOOLSS_JOB_CONTROL_DELETE:
3158 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3159 break;
3160 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3161 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3162 break;
3163 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3164 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3165 break;
3166 case SPOOLSS_JOB_CONTROL_RETAIN:
3167 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3168 break;
3169 case SPOOLSS_JOB_CONTROL_RELEASE:
3170 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3171 break;
3172 default:
3173 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3174 break;
3177 status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3178 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3179 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3181 return true;
3184 static bool test_AddJob(struct torture_context *tctx,
3185 struct dcerpc_binding_handle *b,
3186 struct policy_handle *handle)
3188 NTSTATUS status;
3189 struct spoolss_AddJob r;
3190 uint32_t needed;
3192 r.in.level = 0;
3193 r.in.handle = handle;
3194 r.in.offered = 0;
3195 r.out.needed = &needed;
3196 r.in.buffer = r.out.buffer = NULL;
3198 torture_comment(tctx, "Testing AddJob\n");
3200 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3201 torture_assert_ntstatus_ok(tctx, status, "AddJob failed");
3202 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3204 r.in.level = 1;
3206 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3207 torture_assert_ntstatus_ok(tctx, status, "AddJob failed");
3208 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3210 return true;
3214 static bool test_EnumJobs_args(struct torture_context *tctx,
3215 struct dcerpc_binding_handle *b,
3216 struct policy_handle *handle,
3217 uint32_t level,
3218 uint32_t *count_p,
3219 union spoolss_JobInfo **info_p)
3221 NTSTATUS status;
3222 struct spoolss_EnumJobs r;
3223 uint32_t needed;
3224 uint32_t count;
3225 union spoolss_JobInfo *info;
3227 r.in.handle = handle;
3228 r.in.firstjob = 0;
3229 r.in.numjobs = 0xffffffff;
3230 r.in.level = level;
3231 r.in.buffer = NULL;
3232 r.in.offered = 0;
3233 r.out.needed = &needed;
3234 r.out.count = &count;
3235 r.out.info = &info;
3237 torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3239 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3241 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3243 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3244 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3245 r.in.buffer = &blob;
3246 r.in.offered = needed;
3248 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3250 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3251 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3252 torture_assert(tctx, info, "No jobs returned");
3254 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3256 } else {
3257 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3260 if (count_p) {
3261 *count_p = count;
3263 if (info_p) {
3264 *info_p = info;
3267 return true;
3270 static bool test_JobPropertiesEnum(struct torture_context *tctx,
3271 struct dcerpc_binding_handle *b,
3272 struct policy_handle *handle,
3273 uint32_t job_id)
3275 struct spoolss_RpcEnumJobNamedProperties r;
3276 uint32_t pcProperties = 0;
3277 struct RPC_PrintNamedProperty *ppProperties = NULL;
3279 r.in.hPrinter = handle;
3280 r.in.JobId = job_id;
3281 r.out.pcProperties = &pcProperties;
3282 r.out.ppProperties = &ppProperties;
3284 torture_comment(tctx, "Testing RpcEnumJobNamedProperties(%d)\n", job_id);
3286 torture_assert_ntstatus_ok(tctx,
3287 dcerpc_spoolss_RpcEnumJobNamedProperties_r(b, tctx, &r),
3288 "spoolss_RpcEnumJobNamedProperties failed");
3289 torture_assert_werr_ok(tctx, r.out.result,
3290 "spoolss_RpcEnumJobNamedProperties failed");
3292 return true;
3295 static bool test_JobPropertySet(struct torture_context *tctx,
3296 struct dcerpc_binding_handle *b,
3297 struct policy_handle *handle,
3298 uint32_t job_id,
3299 struct RPC_PrintNamedProperty *property)
3301 struct spoolss_RpcSetJobNamedProperty r;
3303 r.in.hPrinter = handle;
3304 r.in.JobId = job_id;
3305 r.in.pProperty = property;
3307 torture_comment(tctx, "Testing RpcSetJobNamedProperty(%d) %s - %d\n",
3308 job_id, property->propertyName,
3309 property->propertyValue.ePropertyType);
3311 torture_assert_ntstatus_ok(tctx,
3312 dcerpc_spoolss_RpcSetJobNamedProperty_r(b, tctx, &r),
3313 "spoolss_RpcSetJobNamedProperty failed");
3314 torture_assert_werr_ok(tctx, r.out.result,
3315 "spoolss_RpcSetJobNamedProperty failed");
3317 return true;
3320 static bool test_JobPropertyGetValue(struct torture_context *tctx,
3321 struct dcerpc_binding_handle *b,
3322 struct policy_handle *handle,
3323 uint32_t job_id,
3324 const char *property_name,
3325 struct RPC_PrintPropertyValue *value)
3327 struct spoolss_RpcGetJobNamedPropertyValue r;
3329 r.in.hPrinter = handle;
3330 r.in.JobId = job_id;
3331 r.in.pszName = property_name;
3332 r.out.pValue = value;
3334 torture_comment(tctx, "Testing RpcGetJobNamedPropertyValue(%d) %s\n",
3335 job_id, property_name);
3337 torture_assert_ntstatus_ok(tctx,
3338 dcerpc_spoolss_RpcGetJobNamedPropertyValue_r(b, tctx, &r),
3339 "spoolss_RpcGetJobNamedPropertyValue failed");
3340 torture_assert_werr_ok(tctx, r.out.result,
3341 "spoolss_RpcGetJobNamedPropertyValue failed");
3343 return true;
3346 static bool test_JobPropertyDelete(struct torture_context *tctx,
3347 struct dcerpc_binding_handle *b,
3348 struct policy_handle *handle,
3349 uint32_t job_id,
3350 const char *property_name)
3352 struct spoolss_RpcDeleteJobNamedProperty r;
3354 r.in.hPrinter = handle;
3355 r.in.JobId = job_id;
3356 r.in.pszName = property_name;
3358 torture_comment(tctx, "Testing RpcDeleteJobNamedProperty(%d) %s\n",
3359 job_id, property_name);
3361 torture_assert_ntstatus_ok(tctx,
3362 dcerpc_spoolss_RpcDeleteJobNamedProperty_r(b, tctx, &r),
3363 "spoolss_RpcDeleteJobNamedProperty failed");
3364 torture_assert_werr_ok(tctx, r.out.result,
3365 "spoolss_RpcDeleteJobNamedProperty failed");
3367 return true;
3371 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3372 struct dcerpc_binding_handle *b,
3373 struct policy_handle *handle,
3374 const char *document_name,
3375 uint32_t *job_id)
3377 NTSTATUS status;
3378 struct spoolss_StartDocPrinter s;
3379 struct spoolss_DocumentInfoCtr info_ctr;
3380 struct spoolss_DocumentInfo1 info1;
3381 struct spoolss_StartPagePrinter sp;
3382 struct spoolss_WritePrinter w;
3383 struct spoolss_EndPagePrinter ep;
3384 struct spoolss_EndDocPrinter e;
3385 int i;
3386 uint32_t num_written;
3388 torture_comment(tctx, "Testing StartDocPrinter\n");
3390 s.in.handle = handle;
3391 s.in.info_ctr = &info_ctr;
3392 s.out.job_id = job_id;
3394 info1.document_name = document_name;
3395 info1.output_file = NULL;
3396 info1.datatype = "RAW";
3398 info_ctr.level = 1;
3399 info_ctr.info.info1 = &info1;
3401 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3402 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3403 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3405 for (i=1; i < 4; i++) {
3406 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3408 sp.in.handle = handle;
3410 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3411 torture_assert_ntstatus_ok(tctx, status,
3412 "dcerpc_spoolss_StartPagePrinter failed");
3413 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3415 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3417 w.in.handle = handle;
3418 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3419 w.out.num_written = &num_written;
3421 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3422 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3423 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3425 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3427 ep.in.handle = handle;
3429 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3430 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3431 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3434 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3436 e.in.handle = handle;
3438 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3439 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3440 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3442 return true;
3445 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3446 struct dcerpc_binding_handle *b,
3447 struct policy_handle *handle,
3448 uint32_t num_jobs,
3449 uint32_t *job_ids)
3451 uint32_t count;
3452 union spoolss_JobInfo *info = NULL;
3453 int i;
3455 torture_assert(tctx,
3456 test_AddJob(tctx, b, handle),
3457 "AddJob failed");
3459 torture_assert(tctx,
3460 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3461 "EnumJobs level 1 failed");
3463 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3465 for (i=0; i < num_jobs; i++) {
3466 union spoolss_JobInfo ginfo;
3467 const char *document_name;
3468 const char *new_document_name = "any_other_docname";
3469 struct spoolss_JobInfoContainer ctr;
3470 struct spoolss_SetJobInfo1 info1;
3472 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3474 torture_assert(tctx,
3475 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3476 "failed to call test_GetJob");
3478 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3480 document_name = ginfo.info1.document_name;
3482 info1.job_id = ginfo.info1.job_id;
3483 info1.printer_name = ginfo.info1.printer_name;
3484 info1.server_name = ginfo.info1.server_name;
3485 info1.user_name = ginfo.info1.user_name;
3486 info1.document_name = new_document_name;
3487 info1.data_type = ginfo.info1.data_type;
3488 info1.text_status = ginfo.info1.text_status;
3489 info1.status = ginfo.info1.status;
3490 info1.priority = ginfo.info1.priority;
3491 info1.position = ginfo.info1.position;
3492 info1.total_pages = ginfo.info1.total_pages;
3493 info1.pages_printed = ginfo.info1.pages_printed;
3494 info1.submitted = ginfo.info1.submitted;
3496 ctr.level = 1;
3497 ctr.info.info1 = &info1;
3499 torture_assert(tctx,
3500 test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3501 "failed to call test_SetJob level 1");
3503 torture_assert(tctx,
3504 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3505 "failed to call test_GetJob");
3507 if (strequal(ginfo.info1.document_name, document_name)) {
3508 torture_warning(tctx,
3509 "document_name did *NOT* change from '%s' to '%s'\n",
3510 document_name, new_document_name);
3514 for (i=0; i < num_jobs; i++) {
3515 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3516 torture_warning(tctx, "failed to pause printjob\n");
3518 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3519 torture_warning(tctx, "failed to resume printjob\n");
3523 return true;
3526 static bool test_DoPrintTest(struct torture_context *tctx,
3527 struct dcerpc_binding_handle *b,
3528 struct policy_handle *handle)
3530 bool ret = true;
3531 uint32_t num_jobs = 8;
3532 uint32_t *job_ids;
3533 int i;
3535 torture_comment(tctx, "Testing real print operations\n");
3537 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3539 for (i=0; i < num_jobs; i++) {
3540 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3543 for (i=0; i < num_jobs; i++) {
3544 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3547 if (ret == true) {
3548 torture_comment(tctx, "real print operations test succeeded\n\n");
3551 return ret;
3554 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3555 struct dcerpc_binding_handle *b,
3556 struct policy_handle *handle)
3558 bool ret = true;
3559 uint32_t num_jobs = 8;
3560 uint32_t *job_ids;
3561 int i;
3562 torture_comment(tctx, "Testing real print operations (extended)\n");
3564 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3566 for (i=0; i < num_jobs; i++) {
3567 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3570 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3572 for (i=0; i < num_jobs; i++) {
3573 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3576 if (ret == true) {
3577 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3580 return ret;
3583 static bool test_JobPrintProperties_equal(struct torture_context *tctx,
3584 struct RPC_PrintPropertyValue *got,
3585 struct RPC_PrintNamedProperty *exp)
3587 torture_assert_int_equal(tctx,
3588 got->ePropertyType,
3589 exp->propertyValue.ePropertyType,
3590 "ePropertyType");
3592 switch (exp->propertyValue.ePropertyType) {
3593 case kRpcPropertyTypeString:
3594 torture_assert_str_equal(tctx,
3595 got->value.propertyString,
3596 exp->propertyValue.value.propertyString,
3597 "propertyString");
3598 break;
3599 case kRpcPropertyTypeInt32:
3600 torture_assert_int_equal(tctx,
3601 got->value.propertyInt32,
3602 exp->propertyValue.value.propertyInt32,
3603 "propertyInt32");
3604 break;
3605 case kRpcPropertyTypeInt64:
3606 torture_assert_u64_equal(tctx,
3607 got->value.propertyInt64,
3608 exp->propertyValue.value.propertyInt64,
3609 "propertyInt64");
3610 break;
3611 case kRpcPropertyTypeByte:
3612 torture_assert_int_equal(tctx,
3613 got->value.propertyByte,
3614 exp->propertyValue.value.propertyByte,
3615 "propertyByte");
3616 break;
3617 case kRpcPropertyTypeBuffer:
3618 torture_assert_int_equal(tctx,
3619 got->value.propertyBlob.cbBuf,
3620 exp->propertyValue.value.propertyBlob.cbBuf,
3621 "propertyBlob.cbBuf");
3622 torture_assert_mem_equal(tctx,
3623 got->value.propertyBlob.pBuf,
3624 exp->propertyValue.value.propertyBlob.pBuf,
3625 exp->propertyValue.value.propertyBlob.cbBuf,
3626 "propertyBlob.pBuf");
3628 break;
3632 return true;
3635 static bool test_JobPrintProperties(struct torture_context *tctx,
3636 struct dcerpc_binding_handle *b,
3637 struct policy_handle *handle,
3638 uint32_t job_id)
3640 struct RPC_PrintNamedProperty in;
3641 struct RPC_PrintPropertyValue out;
3642 int i;
3643 DATA_BLOB blob = data_blob_string_const("blob");
3644 struct {
3645 const char *property_name;
3646 enum RPC_EPrintPropertyType type;
3647 union RPC_PrintPropertyValueUnion value;
3648 WERROR expected_result;
3649 } tests[] = {
3651 .property_name = "torture_property_string",
3652 .type = kRpcPropertyTypeString,
3653 .value.propertyString = "torture_property_value_string",
3655 .property_name = "torture_property_int32",
3656 .type = kRpcPropertyTypeInt32,
3657 .value.propertyInt32 = 42,
3659 .property_name = "torture_property_int64",
3660 .type = kRpcPropertyTypeInt64,
3661 .value.propertyInt64 = 0xaffe,
3663 .property_name = "torture_property_byte",
3664 .type = kRpcPropertyTypeByte,
3665 .value.propertyByte = 0xab,
3667 .property_name = "torture_property_buffer",
3668 .type = kRpcPropertyTypeBuffer,
3669 .value.propertyBlob.cbBuf = blob.length,
3670 .value.propertyBlob.pBuf = blob.data,
3674 torture_assert(tctx,
3675 test_JobPropertiesEnum(tctx, b, handle, job_id),
3676 "failed to enum properties");
3678 for (i=0; i <ARRAY_SIZE(tests); i++) {
3680 in.propertyName = tests[i].property_name;
3681 in.propertyValue.ePropertyType = tests[i].type;
3682 in.propertyValue.value = tests[i].value;
3684 torture_assert(tctx,
3685 test_JobPropertySet(tctx, b, handle, job_id, &in),
3686 "failed to set property");
3688 torture_assert(tctx,
3689 test_JobPropertyGetValue(tctx, b, handle, job_id, in.propertyName, &out),
3690 "failed to get property");
3692 torture_assert(tctx,
3693 test_JobPrintProperties_equal(tctx, &out, &in),
3694 "property unequal");
3696 torture_assert(tctx,
3697 test_JobPropertiesEnum(tctx, b, handle, job_id),
3698 "failed to enum properties");
3700 torture_assert(tctx,
3701 test_JobPropertyDelete(tctx, b, handle, job_id, in.propertyName),
3702 "failed to delete job property");
3705 torture_assert(tctx,
3706 test_JobPropertiesEnum(tctx, b, handle, job_id),
3707 "failed to enum properties");
3709 return true;
3712 static bool test_DoPrintTest_properties(struct torture_context *tctx,
3713 struct dcerpc_binding_handle *b,
3714 struct policy_handle *handle)
3716 uint32_t num_jobs = 8;
3717 uint32_t *job_ids;
3718 int i;
3719 torture_comment(tctx, "Testing real print operations (properties)\n");
3721 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3723 for (i=0; i < num_jobs; i++) {
3724 torture_assert(tctx,
3725 test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]),
3726 "failed to create print job");
3729 for (i=0; i < num_jobs; i++) {
3730 torture_assert(tctx,
3731 test_JobPrintProperties(tctx, b, handle, job_ids[i]),
3732 "failed to test job properties");
3736 for (i=0; i < num_jobs; i++) {
3737 torture_assert(tctx,
3738 test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE),
3739 "failed to delete printjob");
3742 torture_comment(tctx, "real print operations (properties) test succeeded\n\n");
3744 return true;
3747 static bool test_PausePrinter(struct torture_context *tctx,
3748 struct dcerpc_binding_handle *b,
3749 struct policy_handle *handle)
3751 NTSTATUS status;
3752 struct spoolss_SetPrinter r;
3753 struct spoolss_SetPrinterInfoCtr info_ctr;
3754 struct spoolss_DevmodeContainer devmode_ctr;
3755 struct sec_desc_buf secdesc_ctr;
3757 info_ctr.level = 0;
3758 info_ctr.info.info0 = NULL;
3760 ZERO_STRUCT(devmode_ctr);
3761 ZERO_STRUCT(secdesc_ctr);
3763 r.in.handle = handle;
3764 r.in.info_ctr = &info_ctr;
3765 r.in.devmode_ctr = &devmode_ctr;
3766 r.in.secdesc_ctr = &secdesc_ctr;
3767 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3769 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3771 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3773 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3775 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3777 return true;
3780 static bool test_ResumePrinter(struct torture_context *tctx,
3781 struct dcerpc_binding_handle *b,
3782 struct policy_handle *handle)
3784 NTSTATUS status;
3785 struct spoolss_SetPrinter r;
3786 struct spoolss_SetPrinterInfoCtr info_ctr;
3787 struct spoolss_DevmodeContainer devmode_ctr;
3788 struct sec_desc_buf secdesc_ctr;
3790 info_ctr.level = 0;
3791 info_ctr.info.info0 = NULL;
3793 ZERO_STRUCT(devmode_ctr);
3794 ZERO_STRUCT(secdesc_ctr);
3796 r.in.handle = handle;
3797 r.in.info_ctr = &info_ctr;
3798 r.in.devmode_ctr = &devmode_ctr;
3799 r.in.secdesc_ctr = &secdesc_ctr;
3800 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3802 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3804 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3806 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3808 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3810 return true;
3813 static bool test_GetPrinterData_checktype(struct torture_context *tctx,
3814 struct dcerpc_binding_handle *b,
3815 struct policy_handle *handle,
3816 const char *value_name,
3817 enum winreg_Type *expected_type,
3818 enum winreg_Type *type_p,
3819 uint8_t **data_p,
3820 uint32_t *needed_p)
3822 NTSTATUS status;
3823 struct spoolss_GetPrinterData r;
3824 uint32_t needed;
3825 enum winreg_Type type;
3826 union spoolss_PrinterData data;
3828 r.in.handle = handle;
3829 r.in.value_name = value_name;
3830 r.in.offered = 0;
3831 r.out.needed = &needed;
3832 r.out.type = &type;
3833 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3835 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3837 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3838 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3840 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3841 if (expected_type) {
3842 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3844 r.in.offered = needed;
3845 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3846 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3847 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3850 torture_assert_werr_ok(tctx, r.out.result,
3851 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3853 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3855 if (type_p) {
3856 *type_p = type;
3859 if (data_p) {
3860 *data_p = r.out.data;
3863 if (needed_p) {
3864 *needed_p = needed;
3867 return true;
3870 static bool test_GetPrinterData(struct torture_context *tctx,
3871 struct dcerpc_binding_handle *b,
3872 struct policy_handle *handle,
3873 const char *value_name,
3874 enum winreg_Type *type_p,
3875 uint8_t **data_p,
3876 uint32_t *needed_p)
3878 return test_GetPrinterData_checktype(tctx, b, handle, value_name,
3879 NULL, type_p, data_p, needed_p);
3882 static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
3883 struct dcerpc_pipe *p,
3884 struct policy_handle *handle,
3885 const char *key_name,
3886 const char *value_name,
3887 enum winreg_Type *expected_type,
3888 enum winreg_Type *type_p,
3889 uint8_t **data_p,
3890 uint32_t *needed_p)
3892 NTSTATUS status;
3893 struct spoolss_GetPrinterDataEx r;
3894 enum winreg_Type type;
3895 uint32_t needed;
3896 union spoolss_PrinterData data;
3897 struct dcerpc_binding_handle *b = p->binding_handle;
3899 r.in.handle = handle;
3900 r.in.key_name = key_name;
3901 r.in.value_name = value_name;
3902 r.in.offered = 0;
3903 r.out.type = &type;
3904 r.out.needed = &needed;
3905 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3907 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3908 r.in.key_name, r.in.value_name);
3910 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3911 if (!NT_STATUS_IS_OK(status)) {
3912 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3913 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3915 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3918 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3919 if (expected_type) {
3920 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3922 r.in.offered = needed;
3923 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3924 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3925 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3928 torture_assert_werr_ok(tctx, r.out.result,
3929 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3931 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3933 if (type_p) {
3934 *type_p = type;
3937 if (data_p) {
3938 *data_p = r.out.data;
3941 if (needed_p) {
3942 *needed_p = needed;
3945 return true;
3948 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3949 struct dcerpc_pipe *p,
3950 struct policy_handle *handle,
3951 const char *key_name,
3952 const char *value_name,
3953 enum winreg_Type *type_p,
3954 uint8_t **data_p,
3955 uint32_t *needed_p)
3957 return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
3958 NULL, type_p, data_p, needed_p);
3961 static bool test_get_environment(struct torture_context *tctx,
3962 struct dcerpc_binding_handle *b,
3963 struct policy_handle *handle,
3964 const char **architecture)
3966 DATA_BLOB blob;
3967 enum winreg_Type type;
3968 uint8_t *data;
3969 uint32_t needed;
3971 torture_assert(tctx,
3972 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3973 "failed to get Architecture");
3975 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3977 blob = data_blob_const(data, needed);
3978 *architecture = reg_val_data_string(tctx, REG_SZ, blob);
3980 return true;
3983 static bool test_GetPrinterData_list(struct torture_context *tctx,
3984 void *private_data)
3986 struct test_spoolss_context *ctx =
3987 talloc_get_type_abort(private_data, struct test_spoolss_context);
3988 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3989 struct dcerpc_binding_handle *b = p->binding_handle;
3990 const char *list[] = {
3991 "W3SvcInstalled",
3992 "BeepEnabled",
3993 "EventLog",
3994 /* "NetPopup", not on w2k8 */
3995 /* "NetPopupToComputer", not on w2k8 */
3996 "MajorVersion",
3997 "MinorVersion",
3998 "DefaultSpoolDirectory",
3999 "Architecture",
4000 "DsPresent",
4001 "OSVersion",
4002 /* "OSVersionEx", not on s3 */
4003 "DNSMachineName"
4005 int i;
4007 for (i=0; i < ARRAY_SIZE(list); i++) {
4008 enum winreg_Type type, type_ex;
4009 uint8_t *data, *data_ex;
4010 uint32_t needed, needed_ex;
4012 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
4013 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
4014 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
4015 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
4016 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
4017 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
4018 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
4021 return true;
4024 static bool test_EnumPrinterData(struct torture_context *tctx,
4025 struct dcerpc_pipe *p,
4026 struct policy_handle *handle,
4027 uint32_t enum_index,
4028 uint32_t value_offered,
4029 uint32_t data_offered,
4030 enum winreg_Type *type_p,
4031 uint32_t *value_needed_p,
4032 uint32_t *data_needed_p,
4033 const char **value_name_p,
4034 uint8_t **data_p,
4035 WERROR *result_p)
4037 struct spoolss_EnumPrinterData r;
4038 uint32_t data_needed;
4039 uint32_t value_needed;
4040 enum winreg_Type type;
4041 struct dcerpc_binding_handle *b = p->binding_handle;
4043 r.in.handle = handle;
4044 r.in.enum_index = enum_index;
4045 r.in.value_offered = value_offered;
4046 r.in.data_offered = data_offered;
4047 r.out.data_needed = &data_needed;
4048 r.out.value_needed = &value_needed;
4049 r.out.type = &type;
4050 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
4051 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
4053 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
4055 torture_assert_ntstatus_ok(tctx,
4056 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
4057 "EnumPrinterData failed");
4059 if (type_p) {
4060 *type_p = type;
4062 if (value_needed_p) {
4063 *value_needed_p = value_needed;
4065 if (data_needed_p) {
4066 *data_needed_p = data_needed;
4068 if (value_name_p) {
4069 *value_name_p = r.out.value_name;
4071 if (data_p) {
4072 *data_p = r.out.data;
4074 if (result_p) {
4075 *result_p = r.out.result;
4078 return true;
4082 static bool test_EnumPrinterData_all(struct torture_context *tctx,
4083 struct dcerpc_pipe *p,
4084 struct policy_handle *handle)
4086 uint32_t enum_index = 0;
4087 enum winreg_Type type;
4088 uint32_t value_needed;
4089 uint32_t data_needed;
4090 uint8_t *data;
4091 const char *value_name;
4092 WERROR result;
4094 torture_comment(tctx, "Testing EnumPrinterData\n");
4096 do {
4097 torture_assert(tctx,
4098 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
4099 &type, &value_needed, &data_needed,
4100 &value_name, &data, &result),
4101 "EnumPrinterData failed");
4103 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
4104 break;
4107 torture_assert(tctx,
4108 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
4109 &type, &value_needed, &data_needed,
4110 &value_name, &data, &result),
4111 "EnumPrinterData failed");
4113 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
4114 break;
4117 enum_index++;
4119 } while (W_ERROR_IS_OK(result));
4121 torture_comment(tctx, "EnumPrinterData test succeeded\n");
4123 return true;
4126 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
4127 struct dcerpc_binding_handle *b,
4128 struct policy_handle *handle,
4129 const char *key_name,
4130 uint32_t *count_p,
4131 struct spoolss_PrinterEnumValues **info_p)
4133 struct spoolss_EnumPrinterDataEx r;
4134 struct spoolss_PrinterEnumValues *info;
4135 uint32_t needed;
4136 uint32_t count;
4138 r.in.handle = handle;
4139 r.in.key_name = key_name;
4140 r.in.offered = 0;
4141 r.out.needed = &needed;
4142 r.out.count = &count;
4143 r.out.info = &info;
4145 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
4147 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
4148 "EnumPrinterDataEx failed");
4149 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4150 r.in.offered = needed;
4151 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
4152 "EnumPrinterDataEx failed");
4155 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
4157 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
4159 if (count_p) {
4160 *count_p = count;
4162 if (info_p) {
4163 *info_p = info;
4166 return true;
4169 static bool test_SetPrinterData(struct torture_context *tctx,
4170 struct dcerpc_binding_handle *b,
4171 struct policy_handle *handle,
4172 const char *value_name,
4173 enum winreg_Type type,
4174 uint8_t *data,
4175 uint32_t offered);
4176 static bool test_DeletePrinterData(struct torture_context *tctx,
4177 struct dcerpc_binding_handle *b,
4178 struct policy_handle *handle,
4179 const char *value_name);
4181 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
4182 struct dcerpc_pipe *p,
4183 struct policy_handle *handle)
4185 uint32_t count;
4186 struct spoolss_PrinterEnumValues *info;
4187 int i;
4188 uint32_t value_needed, data_needed;
4189 uint32_t value_offered, data_offered;
4190 WERROR result;
4191 struct dcerpc_binding_handle *b = p->binding_handle;
4193 enum winreg_Type type;
4194 DATA_BLOB blob;
4196 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
4198 torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
4199 type = REG_SZ;
4201 torture_assert(tctx,
4202 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
4203 "SetPrinterData failed");
4205 blob = data_blob_string_const("torture_data2");
4207 torture_assert(tctx,
4208 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
4209 "SetPrinterData failed");
4211 blob = data_blob_talloc(tctx, NULL, 4);
4212 SIVAL(blob.data, 0, 0x11223344);
4214 torture_assert(tctx,
4215 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
4216 "SetPrinterData failed");
4218 torture_assert(tctx,
4219 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
4220 "failed to call EnumPrinterDataEx");
4222 /* get the max sizes for value and data */
4224 torture_assert(tctx,
4225 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
4226 NULL, &value_needed, &data_needed,
4227 NULL, NULL, &result),
4228 "EnumPrinterData failed");
4229 torture_assert_werr_ok(tctx, result, "unexpected result");
4231 /* check if the reply from the EnumPrinterData really matches max values */
4233 for (i=0; i < count; i++) {
4234 if (info[i].value_name_len > value_needed) {
4235 torture_fail(tctx,
4236 talloc_asprintf(tctx,
4237 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
4238 info[i].value_name_len, value_needed));
4240 if (info[i].data_length > data_needed) {
4241 torture_fail(tctx,
4242 talloc_asprintf(tctx,
4243 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
4244 info[i].data_length, data_needed));
4248 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
4249 * sort or not sort the replies by value name, we should be able to do
4250 * the following entry comparison */
4252 data_offered = data_needed;
4253 value_offered = value_needed;
4255 for (i=0; i < count; i++) {
4257 const char *value_name;
4258 uint8_t *data;
4260 torture_assert(tctx,
4261 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
4262 &type, &value_needed, &data_needed,
4263 &value_name, &data, &result),
4264 "EnumPrinterData failed");
4266 if (i -1 == count) {
4267 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
4268 "unexpected result");
4269 break;
4270 } else {
4271 torture_assert_werr_ok(tctx, result, "unexpected result");
4274 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
4275 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
4276 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
4277 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
4278 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
4281 torture_assert(tctx,
4282 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
4283 "DeletePrinterData failed");
4284 torture_assert(tctx,
4285 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
4286 "DeletePrinterData failed");
4287 torture_assert(tctx,
4288 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
4289 "DeletePrinterData failed");
4291 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4293 return true;
4296 static bool test_DeletePrinterData(struct torture_context *tctx,
4297 struct dcerpc_binding_handle *b,
4298 struct policy_handle *handle,
4299 const char *value_name)
4301 NTSTATUS status;
4302 struct spoolss_DeletePrinterData r;
4304 r.in.handle = handle;
4305 r.in.value_name = value_name;
4307 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
4308 r.in.value_name);
4310 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
4312 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
4313 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
4315 return true;
4318 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
4319 struct dcerpc_binding_handle *b,
4320 struct policy_handle *handle,
4321 const char *key_name,
4322 const char *value_name)
4324 struct spoolss_DeletePrinterDataEx r;
4326 r.in.handle = handle;
4327 r.in.key_name = key_name;
4328 r.in.value_name = value_name;
4330 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
4331 r.in.key_name, r.in.value_name);
4333 torture_assert_ntstatus_ok(tctx,
4334 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
4335 "DeletePrinterDataEx failed");
4336 torture_assert_werr_ok(tctx, r.out.result,
4337 "DeletePrinterDataEx failed");
4339 return true;
4342 static bool test_DeletePrinterKey(struct torture_context *tctx,
4343 struct dcerpc_binding_handle *b,
4344 struct policy_handle *handle,
4345 const char *key_name)
4347 struct spoolss_DeletePrinterKey r;
4349 r.in.handle = handle;
4350 r.in.key_name = key_name;
4352 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
4354 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
4355 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
4356 return true;
4359 torture_assert_ntstatus_ok(tctx,
4360 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
4361 "DeletePrinterKey failed");
4362 torture_assert_werr_ok(tctx, r.out.result,
4363 "DeletePrinterKey failed");
4365 return true;
4368 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4369 struct dcerpc_binding_handle *b,
4370 struct policy_handle *handle)
4372 struct winreg_OpenHKLM r;
4374 r.in.system_name = NULL;
4375 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4376 r.out.handle = handle;
4378 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4380 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4381 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4383 return true;
4386 static void init_winreg_String(struct winreg_String *name, const char *s)
4388 name->name = s;
4389 if (s) {
4390 name->name_len = 2 * (strlen_m(s) + 1);
4391 name->name_size = name->name_len;
4392 } else {
4393 name->name_len = 0;
4394 name->name_size = 0;
4398 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4399 struct dcerpc_binding_handle *b,
4400 struct policy_handle *hive_handle,
4401 const char *keyname,
4402 uint32_t options,
4403 struct policy_handle *key_handle)
4405 struct winreg_OpenKey r;
4407 r.in.parent_handle = hive_handle;
4408 init_winreg_String(&r.in.keyname, keyname);
4409 r.in.options = options;
4410 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4411 r.out.handle = key_handle;
4413 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4415 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4416 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4418 return true;
4421 static bool test_winreg_OpenKey(struct torture_context *tctx,
4422 struct dcerpc_binding_handle *b,
4423 struct policy_handle *hive_handle,
4424 const char *keyname,
4425 struct policy_handle *key_handle)
4427 return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4428 REG_OPTION_NON_VOLATILE, key_handle);
4431 static bool test_winreg_CloseKey(struct torture_context *tctx,
4432 struct dcerpc_binding_handle *b,
4433 struct policy_handle *handle)
4435 struct winreg_CloseKey r;
4437 r.in.handle = handle;
4438 r.out.handle = handle;
4440 torture_comment(tctx, "Testing winreg_CloseKey\n");
4442 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4443 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4445 return true;
4448 bool test_winreg_QueryValue(struct torture_context *tctx,
4449 struct dcerpc_binding_handle *b,
4450 struct policy_handle *handle,
4451 const char *value_name,
4452 enum winreg_Type *type_p,
4453 uint32_t *data_size_p,
4454 uint32_t *data_length_p,
4455 uint8_t **data_p)
4457 struct winreg_QueryValue r;
4458 enum winreg_Type type = REG_NONE;
4459 uint32_t data_size = 0;
4460 uint32_t data_length = 0;
4461 struct winreg_String valuename;
4462 uint8_t *data = NULL;
4464 init_winreg_String(&valuename, value_name);
4466 data = talloc_zero_array(tctx, uint8_t, 0);
4468 r.in.handle = handle;
4469 r.in.value_name = &valuename;
4470 r.in.type = &type;
4471 r.in.data_size = &data_size;
4472 r.in.data_length = &data_length;
4473 r.in.data = data;
4474 r.out.type = &type;
4475 r.out.data = data;
4476 r.out.data_size = &data_size;
4477 r.out.data_length = &data_length;
4479 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4481 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4482 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4483 *r.in.data_size = *r.out.data_size;
4484 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4485 r.in.data = data;
4486 r.out.data = data;
4487 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4489 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4491 if (type_p) {
4492 *type_p = *r.out.type;
4494 if (data_size_p) {
4495 *data_size_p = *r.out.data_size;
4497 if (data_length_p) {
4498 *data_length_p = *r.out.data_length;
4500 if (data_p) {
4501 *data_p = r.out.data;
4504 return true;
4507 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4508 struct dcerpc_binding_handle *b,
4509 struct policy_handle *handle,
4510 const char *printer_name,
4511 const char *key_name,
4512 const char *value_name,
4513 enum winreg_Type *w_type,
4514 uint32_t *w_size,
4515 uint32_t *w_length,
4516 uint8_t **w_data)
4518 const char *printer_key;
4519 struct policy_handle key_handle;
4521 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4522 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4524 torture_assert(tctx,
4525 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4527 torture_assert(tctx,
4528 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4530 torture_assert(tctx,
4531 test_winreg_CloseKey(tctx, b, &key_handle), "");
4533 return true;
4536 static bool test_GetForm_winreg(struct torture_context *tctx,
4537 struct dcerpc_binding_handle *b,
4538 struct policy_handle *handle,
4539 const char *key_name,
4540 const char *form_name,
4541 enum winreg_Type *w_type,
4542 uint32_t *w_size,
4543 uint32_t *w_length,
4544 uint8_t **w_data)
4546 struct policy_handle key_handle;
4548 torture_assert(tctx,
4549 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4551 torture_assert(tctx,
4552 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4554 torture_assert(tctx,
4555 test_winreg_CloseKey(tctx, b, &key_handle), "");
4557 return true;
4560 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4561 struct dcerpc_binding_handle *b,
4562 struct policy_handle *handle,
4563 const char *symlink_keyname,
4564 const char *symlink_destination)
4566 /* check if the first key is a symlink to the second key */
4568 enum winreg_Type w_type;
4569 uint32_t w_size;
4570 uint32_t w_length;
4571 uint8_t *w_data;
4572 struct policy_handle key_handle;
4573 DATA_BLOB blob;
4574 const char *str;
4576 if (torture_setting_bool(tctx, "samba3", false)) {
4577 torture_skip(tctx, "skip winreg symlink test against samba");
4580 torture_assert(tctx,
4581 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4582 "failed to open key link");
4584 torture_assert(tctx,
4585 test_winreg_QueryValue(tctx, b, &key_handle,
4586 "SymbolicLinkValue",
4587 &w_type, &w_size, &w_length, &w_data),
4588 "failed to query for 'SymbolicLinkValue' attribute");
4590 torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4592 blob = data_blob(w_data, w_size);
4593 str = reg_val_data_string(tctx, REG_SZ, blob);
4595 torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4597 torture_assert(tctx,
4598 test_winreg_CloseKey(tctx, b, &key_handle),
4599 "failed to close key link");
4601 return true;
4604 static const char *strip_unc(const char *unc)
4606 char *name;
4608 if (!unc) {
4609 return NULL;
4612 if (unc[0] == '\\' && unc[1] == '\\') {
4613 unc +=2;
4616 name = strchr(unc, '\\');
4617 if (name) {
4618 return name+1;
4621 return unc;
4624 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4625 struct dcerpc_binding_handle *b,
4626 struct policy_handle *handle,
4627 const char *printer_name,
4628 struct dcerpc_binding_handle *winreg_handle,
4629 struct policy_handle *hive_handle)
4631 union spoolss_PrinterInfo info;
4632 const char *keys[] = {
4633 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4634 TOP_LEVEL_PRINT_PRINTERS_KEY
4636 int i;
4637 const char *printername, *sharename;
4639 torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4641 torture_assert(tctx,
4642 test_GetPrinter_level(tctx, b, handle, 2, &info),
4643 "failed to get printer info level 2");
4645 printername = strip_unc(info.info2.printername);
4646 sharename = strip_unc(info.info2.sharename);
4648 #define test_sz(wname, iname) \
4649 do {\
4650 DATA_BLOB blob;\
4651 const char *str;\
4652 enum winreg_Type w_type;\
4653 uint32_t w_size;\
4654 uint32_t w_length;\
4655 uint8_t *w_data;\
4656 torture_assert(tctx,\
4657 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4658 &w_type, &w_size, &w_length, &w_data),\
4659 "failed to query winreg");\
4660 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4661 blob = data_blob(w_data, w_size);\
4662 str = reg_val_data_string(tctx, REG_SZ, blob);\
4663 if (w_size == 2 && iname == NULL) {\
4664 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4665 } else {\
4666 torture_assert_str_equal(tctx, str, iname,\
4667 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4669 } while(0);
4671 #define test_dword(wname, iname) \
4672 do {\
4673 uint32_t value;\
4674 enum winreg_Type w_type;\
4675 uint32_t w_size;\
4676 uint32_t w_length;\
4677 uint8_t *w_data;\
4678 torture_assert(tctx,\
4679 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4680 &w_type, &w_size, &w_length, &w_data),\
4681 "failed to query winreg");\
4682 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4683 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4684 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4685 value = IVAL(w_data, 0);\
4686 torture_assert_int_equal(tctx, value, iname,\
4687 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4688 } while(0);
4690 #define test_binary(wname, iname) \
4691 do {\
4692 enum winreg_Type w_type;\
4693 uint32_t w_size;\
4694 uint32_t w_length;\
4695 uint8_t *w_data;\
4696 torture_assert(tctx,\
4697 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4698 &w_type, &w_size, &w_length, &w_data),\
4699 "failed to query winreg");\
4700 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4701 torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4702 torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4703 "binary unequal");\
4704 } while(0);
4707 #define test_dm(wname, iname) \
4708 do {\
4709 DATA_BLOB blob;\
4710 struct spoolss_DeviceMode dm;\
4711 enum ndr_err_code ndr_err;\
4712 enum winreg_Type w_type;\
4713 uint32_t w_size;\
4714 uint32_t w_length;\
4715 uint8_t *w_data;\
4716 torture_assert(tctx,\
4717 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4718 &w_type, &w_size, &w_length, &w_data),\
4719 "failed to query winreg");\
4720 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4721 blob = data_blob(w_data, w_size);\
4722 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4723 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4724 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4725 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4726 "dm unequal");\
4727 } while(0);
4729 #define test_sd(wname, iname) \
4730 do {\
4731 DATA_BLOB blob;\
4732 struct security_descriptor sd;\
4733 enum ndr_err_code ndr_err;\
4734 enum winreg_Type w_type;\
4735 uint32_t w_size;\
4736 uint32_t w_length;\
4737 uint8_t *w_data;\
4738 torture_assert(tctx,\
4739 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4740 &w_type, &w_size, &w_length, &w_data),\
4741 "failed to query winreg");\
4742 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4743 blob = data_blob(w_data, w_size);\
4744 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4745 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4746 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4747 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4748 "sd unequal");\
4749 } while(0);
4751 #define test_multi_sz(wname, iname) \
4752 do {\
4753 DATA_BLOB blob;\
4754 const char **array;\
4755 enum winreg_Type w_type;\
4756 uint32_t w_size;\
4757 uint32_t w_length;\
4758 uint8_t *w_data;\
4759 int i;\
4760 torture_assert(tctx,\
4761 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4762 &w_type, &w_size, &w_length, &w_data),\
4763 "failed to query winreg");\
4764 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4765 blob = data_blob(w_data, w_size);\
4766 torture_assert(tctx, \
4767 pull_reg_multi_sz(tctx, &blob, &array),\
4768 "failed to pull multi sz");\
4769 for (i=0; array[i] != NULL; i++) {\
4770 torture_assert_str_equal(tctx, array[i], iname[i],\
4771 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4773 } while(0);
4775 if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4776 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4777 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4779 torture_warning(tctx, "failed to check for winreg symlink");
4782 for (i=0; i < ARRAY_SIZE(keys); i++) {
4784 const char *printer_key;
4785 struct policy_handle key_handle;
4787 printer_key = talloc_asprintf(tctx, "%s\\%s",
4788 keys[i], printer_name);
4790 torture_assert(tctx,
4791 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4793 test_sz("Name", printername);
4794 test_sz("Share Name", sharename);
4795 test_sz("Port", info.info2.portname);
4796 test_sz("Printer Driver", info.info2.drivername);
4797 test_sz("Description", info.info2.comment);
4798 test_sz("Location", info.info2.location);
4799 test_sz("Separator File", info.info2.sepfile);
4800 test_sz("Print Processor", info.info2.printprocessor);
4801 test_sz("Datatype", info.info2.datatype);
4802 test_sz("Parameters", info.info2.parameters);
4803 /* winreg: 0, spoolss not */
4804 /* test_dword("Attributes", info.info2.attributes); */
4805 test_dword("Priority", info.info2.priority);
4806 test_dword("Default Priority", info.info2.defaultpriority);
4807 /* winreg: 60, spoolss: 0 */
4808 /* test_dword("StartTime", info.info2.starttime); */
4809 /* test_dword("UntilTime", info.info2.untiltime); */
4810 /* winreg != spoolss */
4811 /* test_dword("Status", info.info2.status); */
4812 test_dm("Default DevMode", info.info2.devmode);
4813 test_sd("Security", info.info2.secdesc);
4815 torture_assert(tctx,
4816 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4819 #undef test_dm
4820 #undef test_sd
4822 torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4824 return true;
4827 static bool test_PrintProcessors(struct torture_context *tctx,
4828 struct dcerpc_binding_handle *b,
4829 const char *environment,
4830 struct dcerpc_binding_handle *winreg_handle,
4831 struct policy_handle *hive_handle)
4833 union spoolss_PrintProcessorInfo *info;
4834 uint32_t count;
4835 int i;
4837 torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4839 torture_assert(tctx,
4840 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
4841 "failed to enum print processors level 1");
4843 for (i=0; i < count; i++) {
4845 const char *processor_key;
4846 struct policy_handle key_handle;
4848 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4849 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4850 environment,
4851 info[i].info1.print_processor_name);
4853 torture_assert(tctx,
4854 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4856 /* nothing to check in there so far */
4858 torture_assert(tctx,
4859 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4862 torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4864 return true;
4867 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4868 struct dcerpc_binding_handle *b,
4869 struct policy_handle *handle,
4870 const char *driver_name,
4871 const char *architecture,
4872 uint32_t level,
4873 uint32_t client_major_version,
4874 uint32_t client_minor_version,
4875 union spoolss_DriverInfo *info_p,
4876 WERROR *result);
4878 static const char *strip_path(const char *path)
4880 char *p;
4882 if (path == NULL) {
4883 return NULL;
4886 p = strrchr(path, '\\');
4887 if (p) {
4888 return p+1;
4891 return path;
4894 static const char **strip_paths(const char **path_array)
4896 int i;
4898 if (path_array == NULL) {
4899 return NULL;
4902 for (i=0; path_array[i] != NULL; i++) {
4903 path_array[i] = strip_path(path_array[i]);
4906 return path_array;
4909 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4911 time_t t;
4912 struct tm *tm;
4914 if (nt == 0) {
4915 return talloc_strdup(mem_ctx, "01/01/1601");
4918 t = nt_time_to_unix(nt);
4919 tm = localtime(&t);
4921 return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4922 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4925 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4927 return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4928 (unsigned)((v >> 48) & 0xFFFF),
4929 (unsigned)((v >> 32) & 0xFFFF),
4930 (unsigned)((v >> 16) & 0xFFFF),
4931 (unsigned)(v & 0xFFFF));
4934 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4935 struct dcerpc_binding_handle *b,
4936 struct policy_handle *handle,
4937 const char *printer_name,
4938 const char *driver_name,
4939 const char *environment,
4940 enum spoolss_DriverOSVersion version,
4941 struct dcerpc_binding_handle *winreg_handle,
4942 struct policy_handle *hive_handle,
4943 const char *server_name_slash)
4945 WERROR result;
4946 union spoolss_DriverInfo info;
4947 const char *driver_key;
4948 struct policy_handle key_handle;
4950 const char *driver_path;
4951 const char *data_file;
4952 const char *config_file;
4953 const char *help_file;
4954 const char **dependent_files;
4956 const char *driver_date;
4957 const char *inbox_driver_date;
4959 const char *driver_version;
4960 const char *inbox_driver_version;
4962 torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4964 driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4965 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4966 environment,
4967 version,
4968 driver_name);
4970 torture_assert(tctx,
4971 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4972 "failed to open driver key");
4974 if (torture_setting_bool(tctx, "samba3", false) ||
4975 torture_setting_bool(tctx, "w2k3", false)) {
4976 goto try_level6;
4979 if (handle) {
4980 torture_assert(tctx,
4981 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
4982 "failed to get driver info level 8");
4983 } else {
4984 torture_assert(tctx,
4985 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
4986 "failed to get driver info level 8");
4989 if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4990 goto try_level6;
4993 driver_path = strip_path(info.info8.driver_path);
4994 data_file = strip_path(info.info8.data_file);
4995 config_file = strip_path(info.info8.config_file);
4996 help_file = strip_path(info.info8.help_file);
4997 dependent_files = strip_paths(info.info8.dependent_files);
4999 driver_date = driver_winreg_date(tctx, info.info8.driver_date);
5000 inbox_driver_date = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
5002 driver_version = driver_winreg_version(tctx, info.info8.driver_version);
5003 inbox_driver_version = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
5005 test_sz("Configuration File", config_file);
5006 test_sz("Data File", data_file);
5007 test_sz("Datatype", info.info8.default_datatype);
5008 test_sz("Driver", driver_path);
5009 test_sz("DriverDate", driver_date);
5010 test_sz("DriverVersion", driver_version);
5011 test_sz("HardwareID", info.info8.hardware_id);
5012 test_sz("Help File", help_file);
5013 test_sz("InfPath", info.info8.inf_path);
5014 test_sz("Manufacturer", info.info8.manufacturer_name);
5015 test_sz("MinInboxDriverVerDate", inbox_driver_date);
5016 test_sz("MinInboxDriverVerVersion", inbox_driver_version);
5017 test_sz("Monitor", info.info8.monitor_name);
5018 test_sz("OEM URL", info.info8.manufacturer_url);
5019 test_sz("Print Processor", info.info8.print_processor);
5020 test_sz("Provider", info.info8.provider);
5021 test_sz("VendorSetup", info.info8.vendor_setup);
5022 test_multi_sz("ColorProfiles", info.info8.color_profiles);
5023 test_multi_sz("Dependent Files", dependent_files);
5024 test_multi_sz("CoreDependencies", info.info8.core_driver_dependencies);
5025 test_multi_sz("Previous Names", info.info8.previous_names);
5026 /* test_dword("Attributes", ?); */
5027 test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
5028 test_dword("Version", info.info8.version);
5029 /* test_dword("TempDir", ?); */
5031 try_level6:
5033 if (handle) {
5034 torture_assert(tctx,
5035 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
5036 "failed to get driver info level 6");
5037 } else {
5038 torture_assert(tctx,
5039 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
5040 "failed to get driver info level 6");
5043 driver_path = strip_path(info.info6.driver_path);
5044 data_file = strip_path(info.info6.data_file);
5045 config_file = strip_path(info.info6.config_file);
5046 help_file = strip_path(info.info6.help_file);
5047 dependent_files = strip_paths(info.info6.dependent_files);
5049 driver_date = driver_winreg_date(tctx, info.info6.driver_date);
5051 driver_version = driver_winreg_version(tctx, info.info6.driver_version);
5053 test_sz("Configuration File", config_file);
5054 test_sz("Data File", data_file);
5055 test_sz("Datatype", info.info6.default_datatype);
5056 test_sz("Driver", driver_path);
5057 if (torture_setting_bool(tctx, "w2k3", false)) {
5058 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
5059 push_nttime(blob.data, 0, info.info6.driver_date);
5060 test_binary("DriverDate", blob);
5061 SBVAL(blob.data, 0, info.info6.driver_version);
5062 test_binary("DriverVersion", blob);
5063 } else {
5064 test_sz("DriverDate", driver_date);
5065 test_sz("DriverVersion", driver_version);
5067 test_sz("HardwareID", info.info6.hardware_id);
5068 test_sz("Help File", help_file);
5069 test_sz("Manufacturer", info.info6.manufacturer_name);
5070 test_sz("Monitor", info.info6.monitor_name);
5071 test_sz("OEM URL", info.info6.manufacturer_url);
5072 test_sz("Provider", info.info6.provider);
5073 test_multi_sz("Dependent Files", dependent_files);
5074 test_multi_sz("Previous Names", info.info6.previous_names);
5075 /* test_dword("Attributes", ?); */
5076 test_dword("Version", info.info6.version);
5077 /* test_dword("TempDir", ?); */
5079 if (handle) {
5080 torture_assert(tctx,
5081 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
5082 "failed to get driver info level 3");
5083 } else {
5084 torture_assert(tctx,
5085 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
5086 "failed to get driver info level 3");
5089 driver_path = strip_path(info.info3.driver_path);
5090 data_file = strip_path(info.info3.data_file);
5091 config_file = strip_path(info.info3.config_file);
5092 help_file = strip_path(info.info3.help_file);
5093 dependent_files = strip_paths(info.info3.dependent_files);
5095 test_sz("Configuration File", config_file);
5096 test_sz("Data File", data_file);
5097 test_sz("Datatype", info.info3.default_datatype);
5098 test_sz("Driver", driver_path);
5099 test_sz("Help File", help_file);
5100 test_sz("Monitor", info.info3.monitor_name);
5101 test_multi_sz("Dependent Files", dependent_files);
5102 /* test_dword("Attributes", ?); */
5103 test_dword("Version", info.info3.version);
5104 /* test_dword("TempDir", ?); */
5107 torture_assert(tctx,
5108 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
5110 torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
5112 return true;
5115 #undef test_sz
5116 #undef test_dword
5118 static bool test_SetPrinterData(struct torture_context *tctx,
5119 struct dcerpc_binding_handle *b,
5120 struct policy_handle *handle,
5121 const char *value_name,
5122 enum winreg_Type type,
5123 uint8_t *data,
5124 uint32_t offered)
5126 struct spoolss_SetPrinterData r;
5128 r.in.handle = handle;
5129 r.in.value_name = value_name;
5130 r.in.type = type;
5131 r.in.data = data;
5132 r.in.offered = offered;
5134 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
5135 r.in.value_name);
5137 torture_assert_ntstatus_ok(tctx,
5138 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
5139 "SetPrinterData failed");
5140 torture_assert_werr_ok(tctx, r.out.result,
5141 "SetPrinterData failed");
5143 return true;
5146 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
5147 struct dcerpc_binding_handle *b,
5148 struct policy_handle *handle,
5149 const char *printer_name,
5150 struct dcerpc_binding_handle *winreg_handle,
5151 struct policy_handle *hive_handle)
5153 const char *values[] = {
5154 "spootyfoot",
5155 "spooty\\foot",
5156 #if 0
5157 /* FIXME: not working with s3 atm. */
5158 "spooty,foot",
5159 "spooty,fo,ot",
5160 #endif
5161 "spooty foot",
5162 #if 0
5163 /* FIXME: not working with s3 atm. */
5164 "spooty\\fo,ot",
5165 "spooty,fo\\ot"
5166 #endif
5168 int i;
5170 for (i=0; i < ARRAY_SIZE(values); i++) {
5172 enum winreg_Type type, expected_type = REG_SZ;
5173 DATA_BLOB blob;
5174 uint8_t *data;
5175 uint32_t needed;
5177 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
5178 type = REG_SZ;
5180 torture_assert(tctx,
5181 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
5182 "SetPrinterData failed");
5184 torture_assert(tctx,
5185 test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
5186 "GetPrinterData failed");
5188 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
5189 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
5190 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
5192 if (winreg_handle && hive_handle) {
5194 enum winreg_Type w_type;
5195 uint32_t w_size;
5196 uint32_t w_length;
5197 uint8_t *w_data;
5199 torture_assert(tctx,
5200 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5201 printer_name, "PrinterDriverData", values[i],
5202 &w_type, &w_size, &w_length, &w_data), "");
5204 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
5205 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
5206 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
5207 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
5210 torture_assert(tctx,
5211 test_DeletePrinterData(tctx, b, handle, values[i]),
5212 "DeletePrinterData failed");
5215 return true;
5219 static bool test_EnumPrinterKey(struct torture_context *tctx,
5220 struct dcerpc_binding_handle *b,
5221 struct policy_handle *handle,
5222 const char *key_name,
5223 const char ***array);
5225 static bool test_SetPrinterDataEx(struct torture_context *tctx,
5226 struct dcerpc_binding_handle *b,
5227 struct policy_handle *handle,
5228 const char *key_name,
5229 const char *value_name,
5230 enum winreg_Type type,
5231 uint8_t *data,
5232 uint32_t offered)
5234 NTSTATUS status;
5235 struct spoolss_SetPrinterDataEx r;
5237 r.in.handle = handle;
5238 r.in.key_name = key_name;
5239 r.in.value_name = value_name;
5240 r.in.type = type;
5241 r.in.data = data;
5242 r.in.offered = offered;
5244 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
5245 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
5247 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
5249 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
5250 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
5252 return true;
5255 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
5256 struct dcerpc_pipe *p,
5257 struct policy_handle *handle)
5259 struct dcerpc_binding_handle *b = p->binding_handle;
5260 const char *value_name = "dog";
5261 const char *keys[] = {
5262 "torturedataex",
5263 "torture data ex",
5264 "torturedataex_with_subkey\\subkey",
5265 "torturedataex_with_subkey\\subkey:0",
5266 "torturedataex_with_subkey\\subkey:1",
5267 "torturedataex_with_subkey\\subkey\\subsubkey",
5268 "torturedataex_with_subkey\\subkey\\subsubkey:0",
5269 "torturedataex_with_subkey\\subkey\\subsubkey:1",
5270 "torture,data",
5271 "torture,data,ex",
5272 "torture,data\\ex",
5273 "torture\\data,ex",
5274 "torture/data",
5275 "torture/data ex",
5276 "torture/data ex/sub",
5277 "torture//data",
5278 "torture//data ex",
5279 "torture//data ex/sub",
5280 "torture//data ex//sub",
5282 int i;
5284 for (i=0; i < ARRAY_SIZE(keys); i++) {
5286 char *c;
5287 const char *key;
5288 enum winreg_Type type;
5289 DATA_BLOB blob_in, blob_out;
5290 const char **subkeys;
5291 uint32_t ecount;
5292 struct spoolss_PrinterEnumValues *einfo;
5293 uint32_t needed;
5295 blob_in = data_blob_talloc(tctx, NULL, 42);
5297 generate_random_buffer(blob_in.data, blob_in.length);
5299 torture_assert(tctx,
5300 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
5301 "failed to call SetPrinterDataEx");
5303 torture_assert(tctx,
5304 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
5305 "failed to call GetPrinterDataEx");
5307 blob_out.length = needed;
5308 torture_assert(tctx,
5309 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
5310 "failed to call EnumPrinterDataEx");
5312 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5313 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5314 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5316 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5317 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5318 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5319 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5320 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5321 if (einfo[0].data_length > 0) {
5322 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5325 key = talloc_strdup(tctx, keys[i]);
5327 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
5328 return false;
5331 c = strchr(key, '\\');
5332 if (c) {
5333 int k;
5335 /* we have subkeys */
5337 *c = 0;
5339 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
5340 return false;
5343 for (k=0; subkeys && subkeys[k]; k++) {
5345 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
5347 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
5348 return false;
5352 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5353 return false;
5356 } else {
5357 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5358 return false;
5363 return true;
5366 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
5367 struct dcerpc_pipe *p,
5368 struct policy_handle *handle)
5370 struct dcerpc_binding_handle *b = p->binding_handle;
5371 const char *key = "torturedataex";
5372 const char *values[] = {
5373 "torture_value",
5374 "torture value",
5375 "torture,value",
5376 "torture/value",
5377 "torture\\value",
5378 "torture\\\\value"
5380 int i;
5382 for (i=0; i < ARRAY_SIZE(values); i++) {
5384 enum winreg_Type type;
5385 DATA_BLOB blob_in, blob_out;
5386 uint32_t ecount;
5387 struct spoolss_PrinterEnumValues *einfo;
5388 uint32_t needed;
5390 if (torture_setting_bool(tctx, "samba3", false)) {
5391 char *q;
5392 q = strrchr(values[i], ',');
5393 if (q) {
5394 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
5395 values[i]);
5396 continue;
5400 blob_in = data_blob_talloc(tctx, NULL, 42);
5402 generate_random_buffer(blob_in.data, blob_in.length);
5404 torture_assert(tctx,
5405 test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
5406 "failed to call SetPrinterDataEx");
5408 torture_assert(tctx,
5409 test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
5410 "failed to call GetPrinterDataEx");
5412 blob_out.length = needed;
5413 torture_assert(tctx,
5414 test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
5415 "failed to call EnumPrinterDataEx");
5417 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5418 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5419 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5421 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5422 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5423 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5424 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5425 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5426 if (einfo[0].data_length > 0) {
5427 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5430 torture_assert(tctx,
5431 test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5432 "failed to call DeletePrinterDataEx");
5435 return true;
5439 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5440 struct dcerpc_pipe *p,
5441 struct policy_handle *handle,
5442 const char *printername,
5443 struct dcerpc_binding_handle *winreg_handle,
5444 struct policy_handle *hive_handle)
5446 struct dcerpc_binding_handle *b = p->binding_handle;
5447 const char *value_name = "dog";
5448 const char *key_name = "torturedataex";
5449 enum winreg_Type types[] = {
5450 REG_SZ,
5451 REG_MULTI_SZ,
5452 REG_DWORD,
5453 REG_BINARY
5455 const char *str = "abcdefghi";
5456 int t, s;
5458 for (t=0; t < ARRAY_SIZE(types); t++) {
5459 for (s=0; s < strlen(str); s++) {
5461 enum winreg_Type type;
5462 const char *string = talloc_strndup(tctx, str, s);
5463 const char *array[2];
5464 DATA_BLOB blob = data_blob_string_const(string);
5465 DATA_BLOB data;
5466 uint8_t *data_out;
5467 uint32_t needed, offered = 0;
5468 uint32_t ecount;
5469 struct spoolss_PrinterEnumValues *einfo;
5471 array[0] = talloc_strdup(tctx, string);
5472 array[1] = NULL;
5474 if (types[t] == REG_DWORD) {
5475 s = 0xffff;
5478 switch (types[t]) {
5479 case REG_BINARY:
5480 data = blob;
5481 offered = blob.length;
5482 break;
5483 case REG_DWORD:
5484 data = data_blob_talloc(tctx, NULL, 4);
5485 SIVAL(data.data, 0, 0x12345678);
5486 offered = 4;
5487 break;
5488 case REG_SZ:
5489 torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5490 type = REG_SZ;
5491 offered = data.length;
5492 /*strlen_m_term(data.string)*2;*/
5493 break;
5494 case REG_MULTI_SZ:
5495 torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5496 type = REG_MULTI_SZ;
5497 offered = data.length;
5498 break;
5499 default:
5500 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5503 torture_assert(tctx,
5504 test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5505 "failed to call SetPrinterDataEx");
5507 torture_assert(tctx,
5508 test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
5509 "failed to call GetPrinterDataEx");
5511 torture_assert(tctx,
5512 test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5513 "failed to call EnumPrinterDataEx");
5515 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5516 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5517 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5519 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5520 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5521 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5522 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5523 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5524 if (einfo[0].data_length > 0) {
5525 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5528 if (winreg_handle && hive_handle) {
5529 enum winreg_Type w_type;
5530 uint32_t w_size;
5531 uint32_t w_length;
5532 uint8_t *w_data;
5534 torture_assert(tctx,
5535 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5536 printername, key_name, value_name,
5537 &w_type, &w_size, &w_length, &w_data), "");
5539 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5540 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5541 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5542 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5545 torture_assert(tctx,
5546 test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5547 "failed to call DeletePrinterDataEx");
5551 return true;
5554 static bool test_PrinterData_winreg(struct torture_context *tctx,
5555 struct dcerpc_pipe *p,
5556 struct policy_handle *handle,
5557 const char *printer_name)
5559 struct dcerpc_binding_handle *b = p->binding_handle;
5560 struct dcerpc_pipe *p2;
5561 bool ret = true;
5562 struct policy_handle hive_handle;
5563 struct dcerpc_binding_handle *b2;
5565 torture_assert_ntstatus_ok(tctx,
5566 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5567 "could not open winreg pipe");
5568 b2 = p2->binding_handle;
5570 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5572 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5573 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5575 test_winreg_CloseKey(tctx, b2, &hive_handle);
5577 talloc_free(p2);
5579 return ret;
5582 static bool test_Forms_winreg(struct torture_context *tctx,
5583 struct dcerpc_binding_handle *b,
5584 struct policy_handle *handle,
5585 bool print_server,
5586 const char *printer_name)
5588 struct dcerpc_pipe *p2;
5589 bool ret = true;
5590 struct policy_handle hive_handle;
5591 struct dcerpc_binding_handle *b2;
5593 torture_assert_ntstatus_ok(tctx,
5594 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5595 "could not open winreg pipe");
5596 b2 = p2->binding_handle;
5598 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5600 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5602 test_winreg_CloseKey(tctx, b2, &hive_handle);
5604 talloc_free(p2);
5606 return ret;
5609 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5610 struct dcerpc_pipe *p,
5611 struct policy_handle *handle,
5612 const char *printer_name)
5614 struct dcerpc_binding_handle *b = p->binding_handle;
5615 struct dcerpc_pipe *p2;
5616 bool ret = true;
5617 struct policy_handle hive_handle;
5618 struct dcerpc_binding_handle *b2;
5620 torture_assert_ntstatus_ok(tctx,
5621 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5622 "could not open winreg pipe");
5623 b2 = p2->binding_handle;
5625 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5627 ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5629 test_winreg_CloseKey(tctx, b2, &hive_handle);
5631 talloc_free(p2);
5633 return ret;
5636 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5637 struct dcerpc_pipe *p,
5638 struct policy_handle *handle,
5639 const char *printer_name,
5640 const char *driver_name,
5641 const char *environment,
5642 enum spoolss_DriverOSVersion version)
5644 struct dcerpc_binding_handle *b = p->binding_handle;
5645 struct dcerpc_pipe *p2;
5646 bool ret = true;
5647 struct policy_handle hive_handle;
5648 struct dcerpc_binding_handle *b2;
5650 torture_assert_ntstatus_ok(tctx,
5651 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5652 "could not open winreg pipe");
5653 b2 = p2->binding_handle;
5655 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5657 ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
5659 test_winreg_CloseKey(tctx, b2, &hive_handle);
5661 talloc_free(p2);
5663 return ret;
5666 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5667 struct dcerpc_binding_handle *b,
5668 const char *environment)
5670 struct dcerpc_pipe *p2;
5671 bool ret = true;
5672 struct policy_handle hive_handle;
5673 struct dcerpc_binding_handle *b2;
5675 torture_assert_ntstatus_ok(tctx,
5676 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5677 "could not open winreg pipe");
5678 b2 = p2->binding_handle;
5680 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5682 ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5684 test_winreg_CloseKey(tctx, b2, &hive_handle);
5686 talloc_free(p2);
5688 return ret;
5691 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5692 struct dcerpc_pipe *p,
5693 struct policy_handle *handle,
5694 const char *printer_name)
5696 struct spoolss_SetPrinterInfoCtr info_ctr;
5697 struct spoolss_DevmodeContainer devmode_ctr;
5698 struct sec_desc_buf secdesc_ctr;
5699 union spoolss_SetPrinterInfo sinfo;
5700 union spoolss_PrinterInfo info;
5701 struct dcerpc_binding_handle *b = p->binding_handle;
5702 const char *pname;
5704 ZERO_STRUCT(info_ctr);
5705 ZERO_STRUCT(devmode_ctr);
5706 ZERO_STRUCT(secdesc_ctr);
5708 torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5710 torture_assert(tctx,
5711 test_GetPrinter_level(tctx, b, handle, 2, &info),
5712 "failed to query Printer level 2");
5714 torture_assert(tctx,
5715 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5716 "failed to convert");
5718 info_ctr.level = 2;
5719 info_ctr.info = sinfo;
5721 #define TEST_SZ(wname, iname) \
5722 do {\
5723 enum winreg_Type type;\
5724 uint8_t *data;\
5725 uint32_t needed;\
5726 DATA_BLOB blob;\
5727 const char *str;\
5728 torture_assert(tctx,\
5729 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5730 "failed to query");\
5731 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5732 blob = data_blob_const(data, needed);\
5733 torture_assert(tctx,\
5734 pull_reg_sz(tctx, &blob, &str),\
5735 "failed to pull REG_SZ");\
5736 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5737 } while(0);
5740 #define TEST_SET_SZ(wname, iname, val) \
5741 do {\
5742 enum winreg_Type type;\
5743 uint8_t *data;\
5744 uint32_t needed;\
5745 DATA_BLOB blob;\
5746 const char *str;\
5747 sinfo.info2->iname = val;\
5748 torture_assert(tctx,\
5749 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5750 "failed to call SetPrinter");\
5751 torture_assert(tctx,\
5752 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5753 "failed to query");\
5754 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5755 blob = data_blob_const(data, needed);\
5756 torture_assert(tctx,\
5757 pull_reg_sz(tctx, &blob, &str),\
5758 "failed to pull REG_SZ");\
5759 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5760 } while(0);
5762 #define TEST_SET_DWORD(wname, iname, val) \
5763 do {\
5764 enum winreg_Type type;\
5765 uint8_t *data;\
5766 uint32_t needed;\
5767 uint32_t value;\
5768 sinfo.info2->iname = val;\
5769 torture_assert(tctx,\
5770 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5771 "failed to call SetPrinter");\
5772 torture_assert(tctx,\
5773 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5774 "failed to query");\
5775 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5776 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5777 value = IVAL(data, 0); \
5778 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5779 } while(0);
5781 TEST_SET_SZ("description", comment, "newval");
5782 TEST_SET_SZ("location", location, "newval");
5783 TEST_SET_SZ("driverName", drivername, "newval");
5784 /* TEST_SET_DWORD("priority", priority, 25); */
5786 torture_assert(tctx,
5787 test_GetPrinter_level(tctx, b, handle, 2, &info),
5788 "failed to query Printer level 2");
5790 TEST_SZ("description", info.info2.comment);
5791 TEST_SZ("driverName", info.info2.drivername);
5792 TEST_SZ("location", info.info2.location);
5794 pname = strrchr(info.info2.printername, '\\');
5795 if (pname == NULL) {
5796 pname = info.info2.printername;
5797 } else {
5798 pname++;
5800 TEST_SZ("printerName", pname);
5801 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5802 /* TEST_SZ("printShareName", info.info2.sharename); */
5804 /* FIXME gd: complete the list */
5806 #undef TEST_SZ
5807 #undef TEST_SET_SZ
5808 #undef TEST_DWORD
5810 torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5812 return true;
5815 static bool test_print_processors_winreg(struct torture_context *tctx,
5816 void *private_data)
5818 struct test_spoolss_context *ctx =
5819 talloc_get_type_abort(private_data, struct test_spoolss_context);
5820 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5821 struct dcerpc_binding_handle *b = p->binding_handle;
5823 return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5826 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5827 struct dcerpc_binding_handle *b,
5828 struct policy_handle *handle,
5829 uint32_t *change_id)
5831 enum winreg_Type type;
5832 uint8_t *data;
5833 uint32_t needed;
5835 torture_assert(tctx,
5836 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5837 "failed to call GetPrinterData");
5839 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5840 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5842 *change_id = IVAL(data, 0);
5844 return true;
5847 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5848 struct dcerpc_pipe *p,
5849 struct policy_handle *handle,
5850 uint32_t *change_id)
5852 enum winreg_Type type;
5853 uint8_t *data;
5854 uint32_t needed;
5856 torture_assert(tctx,
5857 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5858 "failed to call GetPrinterData");
5860 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5861 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5863 *change_id = IVAL(data, 0);
5865 return true;
5868 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5869 struct dcerpc_binding_handle *b,
5870 struct policy_handle *handle,
5871 uint32_t *change_id)
5873 union spoolss_PrinterInfo info;
5875 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5876 "failed to query Printer level 0");
5878 *change_id = info.info0.change_id;
5880 return true;
5883 static bool test_ChangeID(struct torture_context *tctx,
5884 struct dcerpc_pipe *p,
5885 struct policy_handle *handle)
5887 uint32_t change_id, change_id_ex, change_id_info;
5888 uint32_t change_id2, change_id_ex2, change_id_info2;
5889 union spoolss_PrinterInfo info;
5890 const char *comment;
5891 struct dcerpc_binding_handle *b = p->binding_handle;
5893 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5895 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5896 "failed to query for ChangeID");
5897 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5898 "failed to query for ChangeID");
5899 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5900 "failed to query for ChangeID");
5902 torture_assert_int_equal(tctx, change_id, change_id_ex,
5903 "change_ids should all be equal");
5904 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5905 "change_ids should all be equal");
5908 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
5910 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5911 "failed to query for ChangeID");
5912 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5913 "failed to query Printer level 2");
5914 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5915 "failed to query for ChangeID");
5916 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5917 "failed to query for ChangeID");
5918 torture_assert_int_equal(tctx, change_id, change_id_ex,
5919 "change_id should not have changed");
5920 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5921 "change_id should not have changed");
5924 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
5926 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5927 "failed to query for ChangeID");
5928 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5929 "failed to query for ChangeID");
5930 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5931 "failed to query for ChangeID");
5932 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5933 "failed to query Printer level 2");
5934 comment = talloc_strdup(tctx, info.info2.comment);
5937 struct spoolss_SetPrinterInfoCtr info_ctr;
5938 struct spoolss_DevmodeContainer devmode_ctr;
5939 struct sec_desc_buf secdesc_ctr;
5940 union spoolss_SetPrinterInfo sinfo;
5942 ZERO_STRUCT(info_ctr);
5943 ZERO_STRUCT(devmode_ctr);
5944 ZERO_STRUCT(secdesc_ctr);
5947 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5948 sinfo.info2->comment = "torture_comment";
5950 info_ctr.level = 2;
5951 info_ctr.info = sinfo;
5953 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5954 "failed to call SetPrinter");
5956 sinfo.info2->comment = comment;
5958 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5959 "failed to call SetPrinter");
5963 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5964 "failed to query for ChangeID");
5965 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5966 "failed to query for ChangeID");
5967 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5968 "failed to query for ChangeID");
5970 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5971 "change_ids should all be equal");
5972 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5973 "change_ids should all be equal");
5975 torture_assert(tctx, (change_id < change_id2),
5976 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5977 change_id2, change_id));
5978 torture_assert(tctx, (change_id_ex < change_id_ex2),
5979 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5980 change_id_ex2, change_id_ex));
5981 torture_assert(tctx, (change_id_info < change_id_info2),
5982 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5983 change_id_info2, change_id_info));
5985 torture_comment(tctx, "ChangeID tests succeeded\n\n");
5987 return true;
5990 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5991 struct dcerpc_pipe *p,
5992 struct policy_handle *handle)
5994 NTSTATUS status;
5995 struct dcerpc_binding *b;
5996 struct dcerpc_pipe *p2;
5997 struct spoolss_ClosePrinter cp;
5999 /* only makes sense on SMB */
6000 if (p->conn->transport.transport != NCACN_NP) {
6001 return true;
6004 torture_comment(tctx, "Testing close on secondary pipe\n");
6006 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
6007 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
6009 status = dcerpc_secondary_connection(p, &p2, b);
6010 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
6012 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
6013 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
6015 cp.in.handle = handle;
6016 cp.out.handle = handle;
6018 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
6019 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
6020 "ERROR: Allowed close on secondary connection");
6022 talloc_free(p2);
6024 return true;
6027 static bool test_OpenPrinter_badname(struct torture_context *tctx,
6028 struct dcerpc_binding_handle *b, const char *name)
6030 NTSTATUS status;
6031 struct spoolss_OpenPrinter op;
6032 struct spoolss_OpenPrinterEx opEx;
6033 struct policy_handle handle;
6034 bool ret = true;
6036 op.in.printername = name;
6037 op.in.datatype = NULL;
6038 op.in.devmode_ctr.devmode= NULL;
6039 op.in.access_mask = 0;
6040 op.out.handle = &handle;
6042 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
6044 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
6045 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
6046 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
6047 "unexpected result");
6049 if (W_ERROR_IS_OK(op.out.result)) {
6050 ret &=test_ClosePrinter(tctx, b, &handle);
6053 opEx.in.printername = name;
6054 opEx.in.datatype = NULL;
6055 opEx.in.devmode_ctr.devmode = NULL;
6056 opEx.in.access_mask = 0;
6057 opEx.in.userlevel_ctr.level = 1;
6058 opEx.in.userlevel_ctr.user_info.level1 = NULL;
6059 opEx.out.handle = &handle;
6061 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
6063 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
6064 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
6065 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
6066 "unexpected result");
6068 if (W_ERROR_IS_OK(opEx.out.result)) {
6069 ret &=test_ClosePrinter(tctx, b, &handle);
6072 return ret;
6075 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
6076 void *private_data)
6078 struct test_spoolss_context *ctx =
6079 talloc_get_type_abort(private_data, struct test_spoolss_context);
6081 const char *badnames[] = {
6082 "__INVALID_PRINTER__",
6083 "\\\\__INVALID_HOST__",
6085 "\\\\\\",
6086 "\\\\\\__INVALID_PRINTER__"
6088 const char *badname;
6089 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6090 const char *server_name = dcerpc_server_name(p);
6091 struct dcerpc_binding_handle *b = p->binding_handle;
6092 int i;
6094 for (i=0; i < ARRAY_SIZE(badnames); i++) {
6095 torture_assert(tctx,
6096 test_OpenPrinter_badname(tctx, b, badnames[i]),
6097 "");
6100 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
6101 torture_assert(tctx,
6102 test_OpenPrinter_badname(tctx, b, badname),
6103 "");
6105 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
6106 torture_assert(tctx,
6107 test_OpenPrinter_badname(tctx, b, badname),
6108 "");
6110 return true;
6113 static bool test_OpenPrinter(struct torture_context *tctx,
6114 struct dcerpc_pipe *p,
6115 const char *name,
6116 const char *environment,
6117 bool open_only)
6119 NTSTATUS status;
6120 struct spoolss_OpenPrinter r;
6121 struct policy_handle handle;
6122 bool ret = true;
6123 struct dcerpc_binding_handle *b = p->binding_handle;
6125 r.in.printername = name;
6126 r.in.datatype = NULL;
6127 r.in.devmode_ctr.devmode= NULL;
6128 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6129 r.out.handle = &handle;
6131 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
6133 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
6135 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
6137 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
6139 if (open_only) {
6140 goto close_printer;
6143 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6144 ret = false;
6147 if (!torture_setting_bool(tctx, "samba3", false)) {
6148 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6149 ret = false;
6153 close_printer:
6154 if (!test_ClosePrinter(tctx, b, &handle)) {
6155 ret = false;
6158 return ret;
6161 static bool test_OpenPrinterEx(struct torture_context *tctx,
6162 struct dcerpc_binding_handle *b,
6163 const char *printername,
6164 const char *datatype,
6165 struct spoolss_DeviceMode *devmode,
6166 uint32_t access_mask,
6167 struct spoolss_UserLevelCtr *userlevel_ctr,
6168 struct policy_handle *handle,
6169 WERROR expected_result)
6171 struct spoolss_OpenPrinterEx r;
6173 r.in.printername = printername;
6174 r.in.datatype = datatype;
6175 r.in.devmode_ctr.devmode= devmode;
6176 r.in.access_mask = access_mask;
6177 r.in.userlevel_ctr = *userlevel_ctr;
6178 r.out.handle = handle;
6180 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
6182 torture_assert_ntstatus_ok(tctx,
6183 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
6184 "OpenPrinterEx failed");
6186 torture_assert_werr_equal(tctx, r.out.result, expected_result,
6187 "OpenPrinterEx failed");
6189 return true;
6192 static bool call_OpenPrinterEx(struct torture_context *tctx,
6193 struct dcerpc_pipe *p,
6194 const char *name,
6195 struct spoolss_DeviceMode *devmode,
6196 struct policy_handle *handle)
6198 struct spoolss_UserLevelCtr userlevel_ctr;
6199 struct spoolss_UserLevel1 userlevel1;
6200 struct dcerpc_binding_handle *b = p->binding_handle;
6202 userlevel1.size = 1234;
6203 userlevel1.client = "hello";
6204 userlevel1.user = "spottyfoot!";
6205 userlevel1.build = 1;
6206 userlevel1.major = 2;
6207 userlevel1.minor = 3;
6208 userlevel1.processor = 4;
6210 userlevel_ctr.level = 1;
6211 userlevel_ctr.user_info.level1 = &userlevel1;
6213 return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
6214 SEC_FLAG_MAXIMUM_ALLOWED,
6215 &userlevel_ctr,
6216 handle,
6217 WERR_OK);
6220 static bool test_printer_rename(struct torture_context *tctx,
6221 void *private_data)
6223 struct torture_printer_context *t =
6224 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6225 struct dcerpc_pipe *p = t->spoolss_pipe;
6227 bool ret = true;
6228 union spoolss_PrinterInfo info;
6229 union spoolss_SetPrinterInfo sinfo;
6230 struct spoolss_SetPrinterInfoCtr info_ctr;
6231 struct spoolss_DevmodeContainer devmode_ctr;
6232 struct sec_desc_buf secdesc_ctr;
6233 const char *printer_name;
6234 const char *printer_name_orig;
6235 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
6236 struct policy_handle new_handle;
6237 const char *q;
6238 struct dcerpc_binding_handle *b = p->binding_handle;
6240 ZERO_STRUCT(devmode_ctr);
6241 ZERO_STRUCT(secdesc_ctr);
6243 torture_comment(tctx, "Testing Printer rename operations\n");
6245 torture_assert(tctx,
6246 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
6247 "failed to call GetPrinter level 2");
6249 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
6251 q = strrchr(info.info2.printername, '\\');
6252 if (q) {
6253 torture_warning(tctx,
6254 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6257 torture_assert(tctx,
6258 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
6260 sinfo.info2->printername = printer_name_new;
6262 info_ctr.level = 2;
6263 info_ctr.info = sinfo;
6265 torture_assert(tctx,
6266 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6267 "failed to call SetPrinter level 2");
6269 torture_assert(tctx,
6270 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
6271 "failed to call GetPrinter level 2");
6273 printer_name = talloc_strdup(tctx, info.info2.printername);
6275 q = strrchr(info.info2.printername, '\\');
6276 if (q) {
6277 torture_warning(tctx,
6278 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6279 q++;
6280 printer_name = q;
6283 torture_assert_str_equal(tctx, printer_name, printer_name_new,
6284 "new printer name was not set");
6286 /* samba currently cannot fully rename printers */
6287 if (!torture_setting_bool(tctx, "samba3", false)) {
6288 torture_assert(tctx,
6289 test_OpenPrinter_badname(tctx, b, printer_name_orig),
6290 "still can open printer with oldname after rename");
6291 } else {
6292 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
6295 torture_assert(tctx,
6296 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
6297 "failed to open printer with new name");
6299 torture_assert(tctx,
6300 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
6301 "failed to call GetPrinter level 2");
6303 torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
6304 "new printer name was not set");
6306 torture_assert(tctx,
6307 test_ClosePrinter(tctx, b, &new_handle),
6308 "failed to close printer");
6310 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
6312 return ret;
6315 static bool test_openprinter(struct torture_context *tctx,
6316 struct dcerpc_binding_handle *b,
6317 const char *real_printername)
6319 struct spoolss_UserLevelCtr userlevel_ctr;
6320 struct policy_handle handle;
6321 struct spoolss_UserLevel1 userlevel1;
6322 const char *printername = NULL;
6323 int i;
6325 struct {
6326 const char *suffix;
6327 WERROR expected_result;
6328 } tests[] = {
6330 .suffix = "rubbish",
6331 .expected_result = WERR_INVALID_PRINTER_NAME
6333 .suffix = ", LocalOnl",
6334 .expected_result = WERR_INVALID_PRINTER_NAME
6336 .suffix = ", localOnly",
6337 .expected_result = WERR_INVALID_PRINTER_NAME
6339 .suffix = ", localonl",
6340 .expected_result = WERR_INVALID_PRINTER_NAME
6342 .suffix = ",LocalOnl",
6343 .expected_result = WERR_INVALID_PRINTER_NAME
6345 .suffix = ",localOnl2",
6346 .expected_result = WERR_INVALID_PRINTER_NAME
6348 .suffix = ", DrvConver2t",
6349 .expected_result = WERR_INVALID_PRINTER_NAME
6351 .suffix = ", drvconvert",
6352 .expected_result = WERR_INVALID_PRINTER_NAME
6354 .suffix = ",drvconvert",
6355 .expected_result = WERR_INVALID_PRINTER_NAME
6357 .suffix = ", DrvConvert",
6358 .expected_result = WERR_OK
6360 .suffix = " , DrvConvert",
6361 .expected_result = WERR_INVALID_PRINTER_NAME
6363 .suffix = ",DrvConvert",
6364 .expected_result = WERR_OK
6366 .suffix = ", DrvConvertsadfasdf",
6367 .expected_result = WERR_OK
6369 .suffix = ",DrvConvertasdfasd",
6370 .expected_result = WERR_OK
6372 .suffix = ", LocalOnly",
6373 .expected_result = WERR_OK
6375 .suffix = " , LocalOnly",
6376 .expected_result = WERR_INVALID_PRINTER_NAME
6378 .suffix = ",LocalOnly",
6379 .expected_result = WERR_OK
6381 .suffix = ", LocalOnlysagi4gjfkd",
6382 .expected_result = WERR_OK
6384 .suffix = ",LocalOnlysagi4gjfkd",
6385 .expected_result = WERR_OK
6389 userlevel1.size = 1234;
6390 userlevel1.client = "hello";
6391 userlevel1.user = "spottyfoot!";
6392 userlevel1.build = 1;
6393 userlevel1.major = 2;
6394 userlevel1.minor = 3;
6395 userlevel1.processor = 4;
6397 userlevel_ctr.level = 1;
6398 userlevel_ctr.user_info.level1 = &userlevel1;
6400 torture_comment(tctx, "Testing openprinterex printername pattern\n");
6402 torture_assert(tctx,
6403 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0,
6404 &userlevel_ctr, &handle,
6405 WERR_OK),
6406 "OpenPrinterEx failed");
6407 test_ClosePrinter(tctx, b, &handle);
6409 for (i=0; i < ARRAY_SIZE(tests); i++) {
6411 printername = talloc_asprintf(tctx, "%s%s",
6412 real_printername,
6413 tests[i].suffix);
6415 torture_assert(tctx,
6416 test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0,
6417 &userlevel_ctr, &handle,
6418 tests[i].expected_result),
6419 "OpenPrinterEx failed");
6420 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6421 test_ClosePrinter(tctx, b, &handle);
6425 return true;
6429 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6430 struct dcerpc_pipe *p,
6431 const char *name,
6432 const char *environment)
6434 struct policy_handle handle;
6435 bool ret = true;
6436 struct dcerpc_binding_handle *b = p->binding_handle;
6438 if (!test_openprinter(tctx, b, name)) {
6439 return false;
6442 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6443 return false;
6446 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6447 ret = false;
6450 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6451 ret = false;
6454 if (!test_EnumForms_all(tctx, b, &handle, false)) {
6455 ret = false;
6458 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6459 ret = false;
6462 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6463 ret = false;
6466 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6467 ret = false;
6470 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6471 ret = false;
6474 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6475 ret = false;
6478 if (!test_printer_all_keys(tctx, b, &handle)) {
6479 ret = false;
6482 if (!test_PausePrinter(tctx, b, &handle)) {
6483 ret = false;
6486 if (!test_DoPrintTest(tctx, b, &handle)) {
6487 ret = false;
6490 if (!test_ResumePrinter(tctx, b, &handle)) {
6491 ret = false;
6494 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
6495 ret = false;
6498 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
6499 ret = false;
6502 if (!torture_setting_bool(tctx, "samba3", false)) {
6503 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6504 ret = false;
6508 if (!test_ClosePrinter(tctx, b, &handle)) {
6509 ret = false;
6512 return ret;
6515 static bool test_EnumPrinters_old(struct torture_context *tctx,
6516 void *private_data)
6518 struct test_spoolss_context *ctx =
6519 talloc_get_type_abort(private_data, struct test_spoolss_context);
6520 struct spoolss_EnumPrinters r;
6521 NTSTATUS status;
6522 uint16_t levels[] = {1, 2, 4, 5};
6523 int i;
6524 bool ret = true;
6525 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6526 struct dcerpc_binding_handle *b = p->binding_handle;
6528 for (i=0;i<ARRAY_SIZE(levels);i++) {
6529 union spoolss_PrinterInfo *info;
6530 int j;
6531 uint32_t needed;
6532 uint32_t count;
6534 r.in.flags = PRINTER_ENUM_LOCAL;
6535 r.in.server = "";
6536 r.in.level = levels[i];
6537 r.in.buffer = NULL;
6538 r.in.offered = 0;
6539 r.out.needed = &needed;
6540 r.out.count = &count;
6541 r.out.info = &info;
6543 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6545 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6546 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6548 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6549 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6550 r.in.buffer = &blob;
6551 r.in.offered = needed;
6552 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6555 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6557 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6559 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6561 if (!info) {
6562 torture_comment(tctx, "No printers returned\n");
6563 return true;
6566 for (j=0;j<count;j++) {
6567 if (r.in.level == 1) {
6568 char *unc = talloc_strdup(tctx, info[j].info1.name);
6569 char *slash, *name, *full_name;
6570 name = unc;
6571 if (unc[0] == '\\' && unc[1] == '\\') {
6572 unc +=2;
6574 slash = strchr(unc, '\\');
6575 if (slash) {
6576 slash++;
6577 name = slash;
6579 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6580 dcerpc_server_name(p), name);
6581 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6582 ret = false;
6584 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6585 ret = false;
6587 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6588 ret = false;
6590 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6591 ret = false;
6597 return ret;
6600 static bool test_EnumPrinters_level(struct torture_context *tctx,
6601 struct dcerpc_binding_handle *b,
6602 uint32_t flags,
6603 const char *servername,
6604 uint32_t level,
6605 uint32_t *count_p,
6606 union spoolss_PrinterInfo **info_p)
6608 struct spoolss_EnumPrinters r;
6609 union spoolss_PrinterInfo *info;
6610 uint32_t needed;
6611 uint32_t count;
6613 r.in.flags = flags;
6614 r.in.server = servername;
6615 r.in.level = level;
6616 r.in.buffer = NULL;
6617 r.in.offered = 0;
6618 r.out.needed = &needed;
6619 r.out.count = &count;
6620 r.out.info = &info;
6622 torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6623 r.in.server, r.in.level);
6625 torture_assert_ntstatus_ok(tctx,
6626 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6627 "EnumPrinters failed");
6628 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6629 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6630 r.in.buffer = &blob;
6631 r.in.offered = needed;
6632 torture_assert_ntstatus_ok(tctx,
6633 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6634 "EnumPrinters failed");
6637 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6639 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6641 if (count_p) {
6642 *count_p = count;
6644 if (info_p) {
6645 *info_p = info;
6648 return true;
6651 static const char *get_short_printername(struct torture_context *tctx,
6652 const char *name)
6654 const char *short_name;
6656 if (name[0] == '\\' && name[1] == '\\') {
6657 name += 2;
6658 short_name = strchr(name, '\\');
6659 if (short_name) {
6660 return talloc_strdup(tctx, short_name+1);
6664 return name;
6667 static const char *get_full_printername(struct torture_context *tctx,
6668 const char *name)
6670 const char *full_name = talloc_strdup(tctx, name);
6671 char *p;
6673 if (name && name[0] == '\\' && name[1] == '\\') {
6674 name += 2;
6675 p = strchr(name, '\\');
6676 if (p) {
6677 return full_name;
6681 return NULL;
6684 static bool test_OnePrinter_servername(struct torture_context *tctx,
6685 struct dcerpc_pipe *p,
6686 struct dcerpc_binding_handle *b,
6687 const char *servername,
6688 const char *printername)
6690 union spoolss_PrinterInfo info;
6691 const char *short_name = get_short_printername(tctx, printername);
6692 const char *full_name = get_full_printername(tctx, printername);
6694 if (short_name) {
6695 struct policy_handle handle;
6696 torture_assert(tctx,
6697 call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
6698 "failed to open printer");
6700 torture_assert(tctx,
6701 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6702 "failed to get printer info");
6704 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
6705 "unexpected servername");
6706 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
6707 "unexpected printername");
6709 if (info.info2.devmode) {
6710 const char *expected_devicename;
6711 expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
6712 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6713 "unexpected devicemode devicename");
6716 torture_assert(tctx,
6717 test_ClosePrinter(tctx, b, &handle),
6718 "failed to close printer");
6721 if (full_name) {
6722 struct policy_handle handle;
6724 torture_assert(tctx,
6725 call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
6726 "failed to open printer");
6728 torture_assert(tctx,
6729 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6730 "failed to get printer info");
6732 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
6733 "unexpected servername");
6734 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
6735 "unexpected printername");
6737 if (info.info2.devmode) {
6738 const char *expected_devicename;
6739 expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
6740 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6741 "unexpected devicemode devicename");
6744 torture_assert(tctx,
6745 test_ClosePrinter(tctx, b, &handle),
6746 "failed to close printer");
6749 return true;
6752 static bool test_EnumPrinters_servername(struct torture_context *tctx,
6753 void *private_data)
6755 struct test_spoolss_context *ctx =
6756 talloc_get_type_abort(private_data, struct test_spoolss_context);
6757 int i;
6758 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6759 struct dcerpc_binding_handle *b = p->binding_handle;
6760 uint32_t count;
6761 union spoolss_PrinterInfo *info;
6762 const char *servername;
6763 uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
6765 torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6767 servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6769 torture_assert(tctx,
6770 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6771 "failed to enumerate printers");
6773 for (i=0; i < count; i++) {
6775 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
6776 "unexpected servername");
6778 torture_assert(tctx,
6779 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6780 "failed to check printer");
6783 servername = "";
6785 torture_assert(tctx,
6786 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6787 "failed to enumerate printers");
6789 for (i=0; i < count; i++) {
6791 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
6792 "unexpected servername");
6794 torture_assert(tctx,
6795 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6796 "failed to check printer");
6800 return true;
6804 static bool test_GetPrinterDriver(struct torture_context *tctx,
6805 struct dcerpc_binding_handle *b,
6806 struct policy_handle *handle,
6807 const char *driver_name)
6809 struct spoolss_GetPrinterDriver r;
6810 uint32_t needed;
6812 r.in.handle = handle;
6813 r.in.architecture = "W32X86";
6814 r.in.level = 1;
6815 r.in.buffer = NULL;
6816 r.in.offered = 0;
6817 r.out.needed = &needed;
6819 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
6821 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6822 "failed to call GetPrinterDriver");
6823 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6824 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6825 r.in.buffer = &blob;
6826 r.in.offered = needed;
6827 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6828 "failed to call GetPrinterDriver");
6831 torture_assert_werr_ok(tctx, r.out.result,
6832 "failed to call GetPrinterDriver");
6834 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6836 return true;
6839 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
6840 struct dcerpc_binding_handle *b,
6841 struct policy_handle *handle,
6842 const char *driver_name,
6843 const char *architecture,
6844 uint32_t level,
6845 uint32_t client_major_version,
6846 uint32_t client_minor_version,
6847 union spoolss_DriverInfo *info_p,
6848 WERROR *result_p)
6851 struct spoolss_GetPrinterDriver2 r;
6852 uint32_t needed;
6853 uint32_t server_major_version;
6854 uint32_t server_minor_version;
6856 r.in.handle = handle;
6857 r.in.architecture = architecture;
6858 r.in.client_major_version = client_major_version;
6859 r.in.client_minor_version = client_minor_version;
6860 r.in.buffer = NULL;
6861 r.in.offered = 0;
6862 r.in.level = level;
6863 r.out.needed = &needed;
6864 r.out.server_major_version = &server_major_version;
6865 r.out.server_minor_version = &server_minor_version;
6867 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
6868 driver_name, r.in.level);
6870 torture_assert_ntstatus_ok(tctx,
6871 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6872 "failed to call GetPrinterDriver2");
6873 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6874 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6875 r.in.buffer = &blob;
6876 r.in.offered = needed;
6877 torture_assert_ntstatus_ok(tctx,
6878 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6879 "failed to call GetPrinterDriver2");
6882 if (result_p) {
6883 *result_p = r.out.result;
6886 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
6887 switch (r.in.level) {
6888 case 101:
6889 case 8:
6890 torture_comment(tctx,
6891 "level %d not implemented, not considering as an error\n",
6892 r.in.level);
6893 return true;
6894 default:
6895 break;
6899 torture_assert_werr_ok(tctx, r.out.result,
6900 "failed to call GetPrinterDriver2");
6902 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6904 if (info_p) {
6905 *info_p = *r.out.info;
6908 return true;
6911 static bool test_GetPrinterDriver2(struct torture_context *tctx,
6912 struct dcerpc_binding_handle *b,
6913 struct policy_handle *handle,
6914 const char *driver_name,
6915 const char *architecture)
6917 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
6918 int i;
6921 for (i=0;i<ARRAY_SIZE(levels);i++) {
6923 torture_assert(tctx,
6924 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
6925 "");
6928 return true;
6931 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
6932 void *private_data)
6934 struct test_spoolss_context *ctx =
6935 talloc_get_type_abort(private_data, struct test_spoolss_context);
6936 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
6937 int i;
6938 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6939 struct dcerpc_binding_handle *b = p->binding_handle;
6940 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6942 for (i=0;i<ARRAY_SIZE(levels);i++) {
6944 uint32_t count;
6945 union spoolss_DriverInfo *info;
6947 torture_assert(tctx,
6948 test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
6949 "failed to enumerate drivers");
6951 if (!info) {
6952 torture_comment(tctx, "No printer drivers returned\n");
6953 break;
6957 return true;
6960 static bool test_DeletePrinter(struct torture_context *tctx,
6961 struct dcerpc_binding_handle *b,
6962 struct policy_handle *handle)
6964 struct spoolss_DeletePrinter r;
6966 torture_comment(tctx, "Testing DeletePrinter\n");
6968 r.in.handle = handle;
6970 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
6971 "failed to delete printer");
6972 torture_assert_werr_ok(tctx, r.out.result,
6973 "failed to delete printer");
6975 return true;
6978 static bool test_EnumPrinters_findname(struct torture_context *tctx,
6979 struct dcerpc_binding_handle *b,
6980 uint32_t flags,
6981 uint32_t level,
6982 const char *name,
6983 bool *found)
6985 struct spoolss_EnumPrinters e;
6986 uint32_t count;
6987 union spoolss_PrinterInfo *info;
6988 uint32_t needed;
6989 int i;
6991 *found = false;
6993 e.in.flags = flags;
6994 e.in.server = NULL;
6995 e.in.level = level;
6996 e.in.buffer = NULL;
6997 e.in.offered = 0;
6998 e.out.count = &count;
6999 e.out.info = &info;
7000 e.out.needed = &needed;
7002 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
7003 "failed to enum printers");
7005 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
7006 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7007 e.in.buffer = &blob;
7008 e.in.offered = needed;
7010 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
7011 "failed to enum printers");
7014 torture_assert_werr_ok(tctx, e.out.result,
7015 "failed to enum printers");
7017 for (i=0; i < count; i++) {
7019 const char *current = NULL;
7020 const char *q;
7022 switch (level) {
7023 case 1:
7024 current = info[i].info1.name;
7025 break;
7028 if (strequal(current, name)) {
7029 *found = true;
7030 break;
7033 q = strrchr(current, '\\');
7034 if (q) {
7035 if (!e.in.server) {
7036 torture_warning(tctx,
7037 "server returns printername %s incl. servername although we did not set servername", current);
7039 q++;
7040 if (strequal(q, name)) {
7041 *found = true;
7042 break;
7047 return true;
7050 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
7051 struct dcerpc_pipe *p,
7052 const char *printername,
7053 bool ex)
7055 WERROR result;
7056 struct spoolss_AddPrinter r;
7057 struct spoolss_AddPrinterEx rex;
7058 struct spoolss_SetPrinterInfoCtr info_ctr;
7059 struct spoolss_SetPrinterInfo1 info1;
7060 struct spoolss_DevmodeContainer devmode_ctr;
7061 struct sec_desc_buf secdesc_ctr;
7062 struct spoolss_UserLevelCtr userlevel_ctr;
7063 struct policy_handle handle;
7064 bool found = false;
7065 struct dcerpc_binding_handle *b = p->binding_handle;
7067 ZERO_STRUCT(devmode_ctr);
7068 ZERO_STRUCT(secdesc_ctr);
7069 ZERO_STRUCT(userlevel_ctr);
7070 ZERO_STRUCT(info1);
7072 torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
7073 ex ? "Ex":"", printername);
7075 /* try to add printer to wellknown printer list (level 1) */
7077 userlevel_ctr.level = 1;
7079 info_ctr.info.info1 = &info1;
7080 info_ctr.level = 1;
7082 rex.in.server = NULL;
7083 rex.in.info_ctr = &info_ctr;
7084 rex.in.devmode_ctr = &devmode_ctr;
7085 rex.in.secdesc_ctr = &secdesc_ctr;
7086 rex.in.userlevel_ctr = &userlevel_ctr;
7087 rex.out.handle = &handle;
7089 r.in.server = NULL;
7090 r.in.info_ctr = &info_ctr;
7091 r.in.devmode_ctr = &devmode_ctr;
7092 r.in.secdesc_ctr = &secdesc_ctr;
7093 r.out.handle = &handle;
7095 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7096 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7097 "failed to add printer");
7098 result = ex ? rex.out.result : r.out.result;
7099 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
7100 "unexpected result code");
7102 info1.name = printername;
7103 info1.flags = PRINTER_ATTRIBUTE_SHARED;
7105 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7106 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7107 "failed to add printer");
7108 result = ex ? rex.out.result : r.out.result;
7109 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7110 "unexpected result code");
7112 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7113 better do a real check to see the printer is really there */
7115 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7116 PRINTER_ENUM_NETWORK, 1,
7117 printername,
7118 &found),
7119 "failed to enum printers");
7121 torture_assert(tctx, found, "failed to find newly added printer");
7123 info1.flags = 0;
7125 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7126 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7127 "failed to add printer");
7128 result = ex ? rex.out.result : r.out.result;
7129 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7130 "unexpected result code");
7132 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7133 better do a real check to see the printer has really been removed
7134 from the well known printer list */
7136 found = false;
7138 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7139 PRINTER_ENUM_NETWORK, 1,
7140 printername,
7141 &found),
7142 "failed to enum printers");
7143 #if 0
7144 torture_assert(tctx, !found, "printer still in well known printer list");
7145 #endif
7146 return true;
7149 static bool test_AddPrinter_normal(struct torture_context *tctx,
7150 struct dcerpc_pipe *p,
7151 struct policy_handle *handle_p,
7152 const char *printername,
7153 const char *drivername,
7154 const char *portname,
7155 struct spoolss_DeviceMode *devmode,
7156 bool ex)
7158 WERROR result;
7159 struct spoolss_AddPrinter r;
7160 struct spoolss_AddPrinterEx rex;
7161 struct spoolss_SetPrinterInfoCtr info_ctr;
7162 struct spoolss_SetPrinterInfo2 info2;
7163 struct spoolss_DevmodeContainer devmode_ctr;
7164 struct sec_desc_buf secdesc_ctr;
7165 struct spoolss_UserLevelCtr userlevel_ctr;
7166 struct policy_handle handle;
7167 bool found = false;
7168 bool existing_printer_deleted = false;
7169 struct dcerpc_binding_handle *b = p->binding_handle;
7171 ZERO_STRUCT(devmode_ctr);
7172 ZERO_STRUCT(secdesc_ctr);
7173 ZERO_STRUCT(userlevel_ctr);
7175 torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
7176 ex ? "Ex":"", printername);
7178 devmode_ctr.devmode = devmode;
7180 userlevel_ctr.level = 1;
7182 rex.in.server = NULL;
7183 rex.in.info_ctr = &info_ctr;
7184 rex.in.devmode_ctr = &devmode_ctr;
7185 rex.in.secdesc_ctr = &secdesc_ctr;
7186 rex.in.userlevel_ctr = &userlevel_ctr;
7187 rex.out.handle = &handle;
7189 r.in.server = NULL;
7190 r.in.info_ctr = &info_ctr;
7191 r.in.devmode_ctr = &devmode_ctr;
7192 r.in.secdesc_ctr = &secdesc_ctr;
7193 r.out.handle = &handle;
7195 again:
7197 /* try to add printer to printer list (level 2) */
7199 ZERO_STRUCT(info2);
7201 info_ctr.info.info2 = &info2;
7202 info_ctr.level = 2;
7204 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7205 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7206 "failed to add printer");
7207 result = ex ? rex.out.result : r.out.result;
7208 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
7209 "unexpected result code");
7211 info2.printername = printername;
7213 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7214 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7215 "failed to add printer");
7216 result = ex ? rex.out.result : r.out.result;
7218 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
7219 struct policy_handle printer_handle;
7221 if (existing_printer_deleted) {
7222 torture_fail(tctx, "already deleted printer still existing?");
7225 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
7226 "failed to open printer handle");
7228 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
7229 "failed to delete printer");
7231 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
7232 "failed to close server handle");
7234 existing_printer_deleted = true;
7236 goto again;
7239 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
7240 "unexpected result code");
7242 info2.portname = portname;
7244 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7245 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7246 "failed to add printer");
7247 result = ex ? rex.out.result : r.out.result;
7248 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
7249 "unexpected result code");
7251 info2.drivername = drivername;
7253 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7254 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7255 "failed to add printer");
7256 result = ex ? rex.out.result : r.out.result;
7258 /* w2k8r2 allows to add printer w/o defining printprocessor */
7260 if (!W_ERROR_IS_OK(result)) {
7261 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
7262 "unexpected result code");
7264 info2.printprocessor = "winprint";
7266 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7267 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7268 "failed to add printer");
7269 result = ex ? rex.out.result : r.out.result;
7270 torture_assert_werr_ok(tctx, result,
7271 "failed to add printer");
7274 *handle_p = handle;
7276 /* we are paranoid, really check if the printer is there now */
7278 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7279 PRINTER_ENUM_LOCAL, 1,
7280 printername,
7281 &found),
7282 "failed to enum printers");
7283 torture_assert(tctx, found, "failed to find newly added printer");
7285 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7286 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7287 "failed to add printer");
7288 result = ex ? rex.out.result : r.out.result;
7289 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7290 "unexpected result code");
7292 return true;
7295 static bool test_printer_info(struct torture_context *tctx,
7296 void *private_data)
7298 struct torture_printer_context *t =
7299 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7300 struct dcerpc_pipe *p = t->spoolss_pipe;
7301 struct dcerpc_binding_handle *b = p->binding_handle;
7303 bool ret = true;
7305 if (torture_setting_bool(tctx, "samba3", false)) {
7306 torture_skip(tctx, "skipping printer info cross tests against samba 3");
7309 if (!test_PrinterInfo(tctx, b, &t->handle)) {
7310 ret = false;
7313 if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
7314 ret = false;
7317 return ret;
7320 static bool test_EnumPrinterKey(struct torture_context *tctx,
7321 struct dcerpc_binding_handle *b,
7322 struct policy_handle *handle,
7323 const char *key_name,
7324 const char ***array)
7326 struct spoolss_EnumPrinterKey r;
7327 uint32_t needed = 0;
7328 union spoolss_KeyNames key_buffer;
7329 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7330 uint32_t _ndr_size;
7331 int i;
7333 r.in.handle = handle;
7334 r.in.key_name = key_name;
7335 r.out.key_buffer = &key_buffer;
7336 r.out.needed = &needed;
7337 r.out._ndr_size = &_ndr_size;
7339 for (i=0; i < ARRAY_SIZE(offered); i++) {
7341 if (offered[i] < 0 && needed) {
7342 if (needed <= 4) {
7343 continue;
7345 r.in.offered = needed + offered[i];
7346 } else {
7347 r.in.offered = offered[i];
7350 ZERO_STRUCT(key_buffer);
7352 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
7354 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7355 "failed to call EnumPrinterKey");
7356 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
7358 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7359 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7360 _ndr_size, r.in.offered/2));
7362 r.in.offered = needed;
7363 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7364 "failed to call EnumPrinterKey");
7367 if (offered[i] > 0) {
7368 torture_assert_werr_ok(tctx, r.out.result,
7369 "failed to call EnumPrinterKey");
7372 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7373 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7374 _ndr_size, r.in.offered/2));
7376 torture_assert(tctx, (*r.out.needed <= r.in.offered),
7377 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
7379 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
7380 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
7382 if (key_buffer.string_array) {
7383 uint32_t calc_needed = 0;
7384 int s;
7385 for (s=0; key_buffer.string_array[s]; s++) {
7386 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7388 if (!key_buffer.string_array[0]) {
7389 calc_needed += 2;
7391 calc_needed += 2;
7393 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7394 "EnumPrinterKey unexpected size");
7398 if (array) {
7399 *array = key_buffer.string_array;
7402 return true;
7405 bool test_printer_all_keys(struct torture_context *tctx,
7406 struct dcerpc_binding_handle *b,
7407 struct policy_handle *handle)
7409 const char **key_array = NULL;
7410 int i;
7412 torture_comment(tctx, "Testing Printer Keys\n");
7414 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7415 "failed to call test_EnumPrinterKey");
7417 for (i=0; key_array && key_array[i]; i++) {
7418 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7419 "failed to call test_EnumPrinterKey");
7421 for (i=0; key_array && key_array[i]; i++) {
7422 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7423 "failed to call test_EnumPrinterDataEx");
7426 torture_comment(tctx, "Printer Keys test succeeded\n\n");
7428 return true;
7431 static bool test_openprinter_wrap(struct torture_context *tctx,
7432 void *private_data)
7434 struct torture_printer_context *t =
7435 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7436 struct dcerpc_pipe *p = t->spoolss_pipe;
7437 struct dcerpc_binding_handle *b = p->binding_handle;
7438 const char *printername = t->info2.printername;
7440 return test_openprinter(tctx, b, printername);
7443 static bool test_csetprinter(struct torture_context *tctx,
7444 void *private_data)
7446 struct torture_printer_context *t =
7447 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7448 struct dcerpc_pipe *p = t->spoolss_pipe;
7450 const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7451 const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7452 const char *portname = t->info2.portname;
7454 union spoolss_PrinterInfo info;
7455 struct policy_handle new_handle, new_handle2;
7456 struct dcerpc_binding_handle *b = p->binding_handle;
7458 torture_comment(tctx, "Testing c_setprinter\n");
7460 torture_assert(tctx,
7461 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7462 "failed to get level 0 printer info");
7463 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7464 info.info0.c_setprinter);
7466 /* check if c_setprinter on 1st handle increases after a printer has
7467 * been added */
7469 torture_assert(tctx,
7470 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7471 "failed to add new printer");
7472 torture_assert(tctx,
7473 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7474 "failed to get level 0 printer info");
7475 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7476 info.info0.c_setprinter);
7478 /* check if c_setprinter on new handle increases after a printer has
7479 * been added */
7481 torture_assert(tctx,
7482 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7483 "failed to get level 0 printer info");
7484 torture_comment(tctx, "csetprinter on created handle: %d\n",
7485 info.info0.c_setprinter);
7487 /* open the new printer and check if c_setprinter increases */
7489 torture_assert(tctx,
7490 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7491 "failed to open created printer");
7492 torture_assert(tctx,
7493 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
7494 "failed to get level 0 printer info");
7495 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
7496 info.info0.c_setprinter);
7498 /* cleanup */
7500 torture_assert(tctx,
7501 test_ClosePrinter(tctx, b, &new_handle2),
7502 "failed to close printer");
7503 torture_assert(tctx,
7504 test_DeletePrinter(tctx, b, &new_handle),
7505 "failed to delete new printer");
7507 return true;
7510 static bool compose_local_driver_directory(struct torture_context *tctx,
7511 const char *environment,
7512 const char *local_dir,
7513 const char **path)
7515 char *p;
7517 p = strrchr(local_dir, '/');
7518 if (!p) {
7519 return NULL;
7521 p++;
7523 if (strequal(environment, "Windows x64")) {
7524 if (!strequal(p, "x64")) {
7525 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
7527 } else if (strequal(environment, "Windows NT x86")) {
7528 if (!strequal(p, "i386")) {
7529 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
7531 } else {
7532 torture_assert(tctx, "unknown environment: '%s'\n", environment);
7535 return true;
7538 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
7539 const char *devicename)
7541 struct spoolss_DeviceMode *r;
7543 r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
7544 if (r == NULL) {
7545 return NULL;
7548 r->devicename = talloc_strdup(r, devicename);
7549 r->specversion = DMSPEC_NT4_AND_ABOVE;
7550 r->driverversion = 0x0600;
7551 r->size = 0x00dc;
7552 r->__driverextra_length = 0;
7553 r->fields = DEVMODE_FORMNAME |
7554 DEVMODE_TTOPTION |
7555 DEVMODE_PRINTQUALITY |
7556 DEVMODE_DEFAULTSOURCE |
7557 DEVMODE_COPIES |
7558 DEVMODE_SCALE |
7559 DEVMODE_PAPERSIZE |
7560 DEVMODE_ORIENTATION;
7561 r->orientation = DMORIENT_PORTRAIT;
7562 r->papersize = DMPAPER_LETTER;
7563 r->paperlength = 0;
7564 r->paperwidth = 0;
7565 r->scale = 100;
7566 r->copies = 55;
7567 r->defaultsource = DMBIN_FORMSOURCE;
7568 r->printquality = DMRES_HIGH;
7569 r->color = DMRES_MONOCHROME;
7570 r->duplex = DMDUP_SIMPLEX;
7571 r->yresolution = 0;
7572 r->ttoption = DMTT_SUBDEV;
7573 r->collate = DMCOLLATE_FALSE;
7574 r->formname = talloc_strdup(r, "Letter");
7576 return r;
7579 static bool test_architecture_buffer(struct torture_context *tctx,
7580 void *private_data)
7582 struct test_spoolss_context *ctx =
7583 talloc_get_type_abort(private_data, struct test_spoolss_context);
7585 struct spoolss_OpenPrinterEx r;
7586 struct spoolss_UserLevel1 u1;
7587 struct policy_handle handle;
7588 uint32_t architectures[] = {
7589 PROCESSOR_ARCHITECTURE_INTEL,
7590 PROCESSOR_ARCHITECTURE_IA64,
7591 PROCESSOR_ARCHITECTURE_AMD64
7593 uint32_t needed[3];
7594 int i;
7595 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7596 struct dcerpc_binding_handle *b = p->binding_handle;
7598 for (i=0; i < ARRAY_SIZE(architectures); i++) {
7600 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7602 u1.size = 0;
7603 u1.client = NULL;
7604 u1.user = NULL;
7605 u1.build = 0;
7606 u1.major = 3;
7607 u1.minor = 0;
7608 u1.processor = architectures[i];
7610 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7611 r.in.datatype = NULL;
7612 r.in.devmode_ctr.devmode= NULL;
7613 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7614 r.in.userlevel_ctr.level = 1;
7615 r.in.userlevel_ctr.user_info.level1 = &u1;
7616 r.out.handle = &handle;
7618 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7619 torture_assert_werr_ok(tctx, r.out.result, "");
7622 struct spoolss_EnumPrinters e;
7623 uint32_t count;
7624 union spoolss_PrinterInfo *info;
7626 e.in.flags = PRINTER_ENUM_LOCAL;
7627 e.in.server = NULL;
7628 e.in.level = 2;
7629 e.in.buffer = NULL;
7630 e.in.offered = 0;
7631 e.out.count = &count;
7632 e.out.info = &info;
7633 e.out.needed = &needed[i];
7635 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7636 #if 0
7637 torture_comment(tctx, "needed was %d\n", needed[i]);
7638 #endif
7641 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7644 for (i=1; i < ARRAY_SIZE(architectures); i++) {
7645 if (needed[i-1] != needed[i]) {
7646 torture_fail(tctx,
7647 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7648 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7652 return true;
7655 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
7656 void *private_data)
7658 struct test_spoolss_context *ctx =
7659 talloc_get_type_abort(private_data, struct test_spoolss_context);
7660 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7661 struct dcerpc_binding_handle *b = p->binding_handle;
7663 return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
7666 static bool test_PrintServer_Forms(struct torture_context *tctx,
7667 void *private_data)
7669 struct test_spoolss_context *ctx =
7670 talloc_get_type_abort(private_data, struct test_spoolss_context);
7671 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7672 struct dcerpc_binding_handle *b = p->binding_handle;
7674 return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
7677 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
7678 void *private_data)
7680 struct test_spoolss_context *ctx =
7681 talloc_get_type_abort(private_data, struct test_spoolss_context);
7682 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7683 struct dcerpc_binding_handle *b = p->binding_handle;
7685 return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
7688 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
7690 NTSTATUS status;
7692 status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
7694 torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
7696 torture_assert(tctx,
7697 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
7698 "failed to open printserver");
7699 torture_assert(tctx,
7700 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
7701 "failed to get environment");
7703 return true;
7706 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
7708 struct test_spoolss_context *t;
7710 *data = t = talloc_zero(tctx, struct test_spoolss_context);
7712 return torture_rpc_spoolss_setup_common(tctx, t);
7715 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
7717 test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
7719 return true;
7722 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
7724 struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
7725 bool ret;
7727 ret = torture_rpc_spoolss_teardown_common(tctx, t);
7728 talloc_free(t);
7730 return ret;
7733 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
7735 struct dcerpc_pipe *p;
7736 struct dcerpc_binding_handle *b;
7737 const char *server_name_slash;
7738 const char *driver_name;
7739 const char *printer_name;
7740 const char *port_name;
7742 torture_assert_ntstatus_ok(tctx,
7743 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
7744 "Error connecting to server");
7746 p = t->spoolss_pipe;
7747 b = p->binding_handle;
7748 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7750 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
7751 t->driver.info8.driver_name = TORTURE_DRIVER;
7752 t->driver.info8.driver_path = "pscript5.dll";
7753 t->driver.info8.data_file = "cups6.ppd";
7754 t->driver.info8.config_file = "ps5ui.dll";
7755 t->driver.info8.help_file = "pscript.hlp";
7756 t->driver.info8.default_datatype = "RAW";
7757 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
7758 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
7759 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
7760 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
7761 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
7762 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
7763 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
7764 t->driver.info8.dependent_files->string[5] = "cups6.ini";
7765 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
7766 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
7768 t->driver.local.driver_directory= "/usr/share/cups/drivers";
7770 t->info2.drivername = "Microsoft XPS Document Writer";
7771 t->info2.portname = "LPT1:";
7773 printer_name = t->info2.printername;
7774 port_name = t->info2.portname;
7776 torture_assert(tctx,
7777 fillup_printserver_info(tctx, p, &t->driver),
7778 "failed to fillup printserver info");
7780 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
7782 torture_assert(tctx,
7783 compose_local_driver_directory(tctx, t->driver.remote.environment,
7784 t->driver.local.driver_directory,
7785 &t->driver.local.driver_directory),
7786 "failed to compose local driver directory");
7788 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7789 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7790 t->info2.drivername, t->driver.remote.environment);
7791 t->have_driver = true;
7792 goto try_add;
7795 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
7796 t->info2.drivername, t->driver.remote.environment);
7797 torture_comment(tctx, "trying to upload own driver\n");
7799 if (!directory_exist(t->driver.local.driver_directory)) {
7800 torture_warning(tctx, "no local driver is available!");
7801 t->have_driver = false;
7802 goto try_add;
7805 torture_assert(tctx,
7806 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
7807 "failed to upload printer driver");
7809 torture_assert(tctx,
7810 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
7811 "failed to add driver");
7813 t->added_driver = true;
7814 t->have_driver = true;
7816 try_add:
7817 driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7819 if (t->wellknown) {
7820 torture_assert(tctx,
7821 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
7822 "failed to add wellknown printer");
7823 } else {
7824 torture_assert(tctx,
7825 test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
7826 "failed to add printer");
7829 return true;
7832 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
7834 struct torture_printer_context *t;
7836 *data = t = talloc_zero(tctx, struct torture_printer_context);
7838 t->ex = false;
7839 t->wellknown = false;
7840 t->info2.printername = TORTURE_PRINTER;
7841 t->devmode = NULL;
7843 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7846 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
7848 struct torture_printer_context *t;
7850 *data = t = talloc_zero(tctx, struct torture_printer_context);
7852 t->ex = true;
7853 t->wellknown = false;
7854 t->info2.printername = TORTURE_PRINTER_EX;
7855 t->devmode = NULL;
7857 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7860 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
7862 struct torture_printer_context *t;
7864 *data = t = talloc_zero(tctx, struct torture_printer_context);
7866 t->ex = false;
7867 t->wellknown = true;
7868 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
7869 t->devmode = NULL;
7871 /* FIXME */
7872 if (t->wellknown) {
7873 torture_skip(tctx, "skipping AddPrinter level 1");
7876 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7879 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
7881 struct torture_printer_context *t;
7883 *data = t = talloc_zero(tctx, struct torture_printer_context);
7885 t->ex = true;
7886 t->wellknown = true;
7887 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
7888 t->devmode = NULL;
7890 /* FIXME */
7891 if (t->wellknown) {
7892 torture_skip(tctx, "skipping AddPrinterEx level 1");
7895 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7898 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
7900 struct torture_printer_context *t;
7902 *data = t = talloc_zero(tctx, struct torture_printer_context);
7904 t->ex = true;
7905 t->wellknown = false;
7906 t->info2.printername = TORTURE_PRINTER_EX;
7907 t->devmode = torture_devicemode(t, TORTURE_PRINTER_EX);
7909 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7912 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
7914 bool found = false;
7915 struct dcerpc_pipe *p = t->spoolss_pipe;
7916 struct dcerpc_binding_handle *b;
7917 const char *printer_name = t->info2.printername;
7919 if (t->added_driver) {
7920 torture_assert(tctx,
7921 remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
7922 "failed to remove printer driver");
7925 if (p && !t->wellknown) {
7926 b = p->binding_handle;
7928 torture_assert(tctx,
7929 test_DeletePrinter(tctx, b, &t->handle),
7930 "failed to delete printer");
7932 torture_assert(tctx,
7933 test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
7934 printer_name, &found),
7935 "failed to enumerate printers");
7937 torture_assert(tctx, !found, "deleted printer still there");
7940 return true;
7943 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
7945 struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
7946 bool ret;
7948 ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
7949 talloc_free(t);
7951 return ret;
7954 static bool test_print_test(struct torture_context *tctx,
7955 void *private_data)
7957 struct torture_printer_context *t =
7958 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7959 struct dcerpc_pipe *p = t->spoolss_pipe;
7960 struct dcerpc_binding_handle *b = p->binding_handle;
7962 torture_assert(tctx,
7963 test_PausePrinter(tctx, b, &t->handle),
7964 "failed to pause printer");
7966 torture_assert(tctx,
7967 test_DoPrintTest(tctx, b, &t->handle),
7968 "failed to do print test");
7970 torture_assert(tctx,
7971 test_ResumePrinter(tctx, b, &t->handle),
7972 "failed to resume printer");
7974 return true;
7977 static bool test_print_test_extended(struct torture_context *tctx,
7978 void *private_data)
7980 struct torture_printer_context *t =
7981 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7982 struct dcerpc_pipe *p = t->spoolss_pipe;
7983 struct dcerpc_binding_handle *b = p->binding_handle;
7984 bool ret = true;
7986 torture_assert(tctx,
7987 test_PausePrinter(tctx, b, &t->handle),
7988 "failed to pause printer");
7990 ret = test_DoPrintTest_extended(tctx, b, &t->handle);
7991 if (ret == false) {
7992 torture_comment(tctx, "WARNING! failed to do extended print test\n");
7993 if (torture_setting_bool(tctx, "samba3", false)) {
7994 torture_comment(tctx, "non-critical for samba3\n");
7995 ret = true;
7996 tctx->last_result = TORTURE_SKIP;
8000 torture_assert(tctx,
8001 test_ResumePrinter(tctx, b, &t->handle),
8002 "failed to resume printer");
8004 return ret;
8007 static bool test_print_test_properties(struct torture_context *tctx,
8008 void *private_data)
8010 struct torture_printer_context *t =
8011 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8012 struct dcerpc_pipe *p = t->spoolss_pipe;
8013 struct dcerpc_binding_handle *b = p->binding_handle;
8015 if (torture_setting_bool(tctx, "samba3", false)) {
8016 torture_skip(tctx, "skip printer job property tests against samba");
8019 torture_assert(tctx,
8020 test_PausePrinter(tctx, b, &t->handle),
8021 "failed to pause printer");
8023 torture_assert(tctx,
8024 test_DoPrintTest_properties(tctx, b, &t->handle),
8025 "failed to test print job properties");
8027 torture_assert(tctx,
8028 test_ResumePrinter(tctx, b, &t->handle),
8029 "failed to resume printer");
8031 return true;
8034 /* use smbd file IO to spool a print job */
8035 static bool test_print_test_smbd(struct torture_context *tctx,
8036 void *private_data)
8038 struct torture_printer_context *t =
8039 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8040 struct dcerpc_pipe *p = t->spoolss_pipe;
8041 struct dcerpc_binding_handle *b = p->binding_handle;
8042 NTSTATUS status;
8043 uint32_t count;
8044 union spoolss_JobInfo *info = NULL;
8045 int i;
8047 struct smb2_tree *tree;
8048 struct smb2_handle job_h;
8049 struct cli_credentials *credentials = cmdline_credentials;
8050 struct smbcli_options options;
8051 TALLOC_CTX *mem_ctx = talloc_new(tctx);
8053 * Do not test against the dynamically added printers, printing via
8054 * smbd means that a different spoolss process may handle the
8055 * OpenPrinter request to the one that handled the AddPrinter request.
8056 * This currently leads to an ugly race condition where one process
8057 * sees the new printer and one doesn't.
8059 const char *share = TORTURE_PRINTER_STATIC1;
8061 torture_comment(tctx, "Testing smbd job spooling\n");
8062 lpcfg_smbcli_options(tctx->lp_ctx, &options);
8064 status = smb2_connect_ext(mem_ctx,
8065 torture_setting_string(tctx, "host", NULL),
8066 lpcfg_smb_ports(tctx->lp_ctx),
8067 share,
8068 lpcfg_resolve_context(tctx->lp_ctx),
8069 credentials,
8071 &tree,
8072 tctx->ev,
8073 &options,
8074 lpcfg_socket_options(tctx->lp_ctx),
8075 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
8076 if (!NT_STATUS_IS_OK(status)) {
8077 printf("Failed to connect to SMB2 printer %s - %s\n",
8078 share, nt_errstr(status));
8079 return false;
8082 status = torture_smb2_testfile(tree, "smbd_spooler_job", &job_h);
8083 torture_assert_ntstatus_ok(tctx, status, "smbd spool job create");
8085 status = smb2_util_write(tree, job_h, "exciting print job data", 0,
8086 sizeof("exciting print job data"));
8087 torture_assert_ntstatus_ok(tctx, status, "smbd spool job write");
8089 /* check back end spoolss job was created */
8090 torture_assert(tctx,
8091 test_EnumJobs_args(tctx, b, &t->handle, 1, &count, &info),
8092 "EnumJobs level 1 failed");
8094 for (i = 0; i < count; i++) {
8095 if (!strcmp(info[i].info1.document_name, "smbd_spooler_job")) {
8096 break;
8099 torture_assert(tctx, (i != count), "smbd_spooler_job not found");
8101 status = smb2_util_close(tree, job_h);
8102 torture_assert_ntstatus_ok(tctx, status, "smbd spool job close");
8104 /* disconnect from printer share */
8105 talloc_free(mem_ctx);
8107 return true;
8110 static bool test_printer_sd(struct torture_context *tctx,
8111 void *private_data)
8113 struct torture_printer_context *t =
8114 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8115 struct dcerpc_pipe *p = t->spoolss_pipe;
8116 struct dcerpc_binding_handle *b = p->binding_handle;
8118 torture_assert(tctx,
8119 test_PrinterInfo_SD(tctx, b, &t->handle),
8120 "failed to test security descriptors");
8122 return true;
8125 static bool test_printer_dm(struct torture_context *tctx,
8126 void *private_data)
8128 struct torture_printer_context *t =
8129 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8130 struct dcerpc_pipe *p = t->spoolss_pipe;
8132 torture_assert(tctx,
8133 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
8134 "failed to test devicemodes");
8136 return true;
8139 static bool test_printer_info_winreg(struct torture_context *tctx,
8140 void *private_data)
8142 struct torture_printer_context *t =
8143 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8144 struct dcerpc_pipe *p = t->spoolss_pipe;
8146 torture_assert(tctx,
8147 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
8148 "failed to test printer info winreg");
8150 return true;
8153 static bool test_printer_change_id(struct torture_context *tctx,
8154 void *private_data)
8156 struct torture_printer_context *t =
8157 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8158 struct dcerpc_pipe *p = t->spoolss_pipe;
8160 torture_assert(tctx,
8161 test_ChangeID(tctx, p, &t->handle),
8162 "failed to test change id");
8164 return true;
8167 static bool test_printer_keys(struct torture_context *tctx,
8168 void *private_data)
8170 struct torture_printer_context *t =
8171 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8172 struct dcerpc_pipe *p = t->spoolss_pipe;
8173 struct dcerpc_binding_handle *b = p->binding_handle;
8175 torture_assert(tctx,
8176 test_printer_all_keys(tctx, b, &t->handle),
8177 "failed to test printer keys");
8179 return true;
8182 static bool test_printer_data_consistency(struct torture_context *tctx,
8183 void *private_data)
8185 struct torture_printer_context *t =
8186 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8187 struct dcerpc_pipe *p = t->spoolss_pipe;
8189 torture_assert(tctx,
8190 test_EnumPrinterData_consistency(tctx, p, &t->handle),
8191 "failed to test printer data consistency");
8193 return true;
8196 static bool test_printer_data_keys(struct torture_context *tctx,
8197 void *private_data)
8199 struct torture_printer_context *t =
8200 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8201 struct dcerpc_pipe *p = t->spoolss_pipe;
8203 torture_assert(tctx,
8204 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
8205 "failed to test printer data keys");
8207 return true;
8210 static bool test_printer_data_values(struct torture_context *tctx,
8211 void *private_data)
8213 struct torture_printer_context *t =
8214 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8215 struct dcerpc_pipe *p = t->spoolss_pipe;
8217 torture_assert(tctx,
8218 test_SetPrinterDataEx_values(tctx, p, &t->handle),
8219 "failed to test printer data values");
8221 return true;
8224 static bool test_printer_data_set(struct torture_context *tctx,
8225 void *private_data)
8227 struct torture_printer_context *t =
8228 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8229 struct dcerpc_pipe *p = t->spoolss_pipe;
8231 torture_assert(tctx,
8232 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
8233 "failed to test printer data set");
8235 return true;
8238 static bool test_printer_data_winreg(struct torture_context *tctx,
8239 void *private_data)
8241 struct torture_printer_context *t =
8242 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8243 struct dcerpc_pipe *p = t->spoolss_pipe;
8245 torture_assert(tctx,
8246 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
8247 "failed to test printer data winreg");
8249 return true;
8252 static bool test_printer_data_dsspooler(struct torture_context *tctx,
8253 void *private_data)
8255 struct torture_printer_context *t =
8256 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8257 struct dcerpc_pipe *p = t->spoolss_pipe;
8259 torture_assert(tctx,
8260 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
8261 "failed to test printer data winreg dsspooler");
8263 return true;
8266 static bool test_printer_ic(struct torture_context *tctx,
8267 void *private_data)
8269 struct torture_printer_context *t =
8270 talloc_get_type_abort(private_data,
8271 struct torture_printer_context);
8272 struct dcerpc_pipe *p = t->spoolss_pipe;
8273 struct dcerpc_binding_handle *b = p->binding_handle;
8274 struct policy_handle gdi_handle;
8276 if (torture_setting_bool(tctx, "samba3", false)) {
8277 torture_skip(tctx, "skip printer information context tests against samba");
8281 struct spoolss_CreatePrinterIC r;
8282 struct spoolss_DevmodeContainer devmode_ctr;
8284 ZERO_STRUCT(devmode_ctr);
8286 r.in.handle = &t->handle;
8287 r.in.devmode_ctr = &devmode_ctr;
8288 r.out.gdi_handle = &gdi_handle;
8290 torture_assert_ntstatus_ok(tctx,
8291 dcerpc_spoolss_CreatePrinterIC_r(b, tctx, &r),
8292 "CreatePrinterIC failed");
8293 torture_assert_werr_ok(tctx, r.out.result,
8294 "CreatePrinterIC failed");
8298 struct spoolss_PlayGDIScriptOnPrinterIC r;
8299 DATA_BLOB in,out;
8300 int i;
8301 uint32_t num_fonts = 0;
8303 in = data_blob_string_const("");
8305 r.in.gdi_handle = &gdi_handle;
8306 r.in.pIn = in.data;
8307 r.in.cIn = in.length;
8308 r.in.ul = 0;
8310 for (i = 0; i < 4; i++) {
8312 out = data_blob_talloc_zero(tctx, i);
8314 r.in.cOut = out.length;
8315 r.out.pOut = out.data;
8317 torture_assert_ntstatus_ok(tctx,
8318 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8319 "PlayGDIScriptOnPrinterIC failed");
8320 torture_assert_werr_equal(tctx, r.out.result, WERR_NOMEM,
8321 "PlayGDIScriptOnPrinterIC failed");
8324 out = data_blob_talloc_zero(tctx, 4);
8326 r.in.cOut = out.length;
8327 r.out.pOut = out.data;
8329 torture_assert_ntstatus_ok(tctx,
8330 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8331 "PlayGDIScriptOnPrinterIC failed");
8332 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
8333 "PlayGDIScriptOnPrinterIC failed");
8335 /* now we should have the required length, so retry with a
8336 * buffer which is large enough to carry all font ids */
8338 num_fonts = IVAL(r.out.pOut, 0);
8340 torture_comment(tctx, "PlayGDIScriptOnPrinterIC gave font count of %d\n", num_fonts);
8342 out = data_blob_talloc_zero(tctx,
8343 num_fonts * sizeof(struct UNIVERSAL_FONT_ID) + 4);
8345 r.in.cOut = out.length;
8346 r.out.pOut = out.data;
8348 torture_assert_ntstatus_ok(tctx,
8349 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8350 "PlayGDIScriptOnPrinterIC failed");
8351 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
8352 "PlayGDIScriptOnPrinterIC failed");
8357 struct spoolss_DeletePrinterIC r;
8359 r.in.gdi_handle = &gdi_handle;
8360 r.out.gdi_handle = &gdi_handle;
8362 torture_assert_ntstatus_ok(tctx,
8363 dcerpc_spoolss_DeletePrinterIC_r(b, tctx, &r),
8364 "DeletePrinterIC failed");
8365 torture_assert_werr_ok(tctx, r.out.result,
8366 "DeletePrinterIC failed");
8370 return true;
8374 static bool test_driver_info_winreg(struct torture_context *tctx,
8375 void *private_data)
8377 struct torture_printer_context *t =
8378 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8379 struct dcerpc_pipe *p = t->spoolss_pipe;
8380 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
8382 if (!t->have_driver) {
8383 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
8386 torture_assert(tctx,
8387 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
8388 "failed to test driver info winreg");
8390 return true;
8393 void torture_tcase_printer(struct torture_tcase *tcase)
8395 torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
8396 torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
8397 torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
8398 torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
8399 torture_tcase_add_simple_test(tcase, "print_test_smbd", test_print_test_smbd);
8400 torture_tcase_add_simple_test(tcase, "print_test_properties", test_print_test_properties);
8401 torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
8402 torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
8403 torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
8404 torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
8405 torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
8406 torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
8407 torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
8408 torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
8409 torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
8410 torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
8411 torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
8412 torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
8413 torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
8414 torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
8415 torture_tcase_add_simple_test(tcase, "printer_ic", test_printer_ic);
8418 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
8420 struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
8421 struct torture_tcase *tcase;
8423 tcase = torture_suite_add_tcase(suite, "addprinter");
8425 torture_tcase_set_fixture(tcase,
8426 torture_rpc_spoolss_printer_setup,
8427 torture_rpc_spoolss_printer_teardown);
8429 torture_tcase_printer(tcase);
8431 tcase = torture_suite_add_tcase(suite, "addprinterex");
8433 torture_tcase_set_fixture(tcase,
8434 torture_rpc_spoolss_printerex_setup,
8435 torture_rpc_spoolss_printer_teardown);
8437 torture_tcase_printer(tcase);
8439 tcase = torture_suite_add_tcase(suite, "addprinterwkn");
8441 torture_tcase_set_fixture(tcase,
8442 torture_rpc_spoolss_printerwkn_setup,
8443 torture_rpc_spoolss_printer_teardown);
8445 tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
8447 torture_tcase_set_fixture(tcase,
8448 torture_rpc_spoolss_printerexwkn_setup,
8449 torture_rpc_spoolss_printer_teardown);
8451 #if 0
8452 /* test is not correct */
8453 tcase = torture_suite_add_tcase(suite, "addprinterdm");
8455 torture_tcase_set_fixture(tcase,
8456 torture_rpc_spoolss_printerdm_setup,
8457 torture_rpc_spoolss_printer_teardown);
8459 torture_tcase_printer(tcase);
8460 #endif
8461 return suite;
8464 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
8466 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
8467 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
8469 torture_tcase_set_fixture(tcase,
8470 torture_rpc_spoolss_setup,
8471 torture_rpc_spoolss_teardown);
8473 torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
8474 torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
8475 torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
8476 torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
8477 torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
8478 torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
8479 torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
8480 torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
8481 torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
8482 torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
8483 torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
8484 torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
8485 torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
8486 torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
8487 torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
8488 torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
8489 torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
8490 torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
8491 torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
8492 torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
8494 torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
8496 return suite;
8499 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
8500 struct dcerpc_binding_handle *b,
8501 const char *server,
8502 const char *environment,
8503 const char **dir_p)
8505 struct spoolss_GetPrinterDriverDirectory r;
8506 uint32_t needed;
8508 r.in.server = server;
8509 r.in.environment = environment;
8510 r.in.level = 1;
8511 r.in.buffer = NULL;
8512 r.in.offered = 0;
8513 r.out.needed = &needed;
8515 torture_assert_ntstatus_ok(tctx,
8516 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8517 "failed to query driver directory");
8519 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
8520 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
8521 r.in.buffer = &blob;
8522 r.in.offered = needed;
8524 torture_assert_ntstatus_ok(tctx,
8525 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8526 "failed to query driver directory");
8529 torture_assert_werr_ok(tctx, r.out.result,
8530 "failed to query driver directory");
8532 if (dir_p) {
8533 *dir_p = r.out.info->info1.directory_name;
8536 return true;
8539 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8541 if (info_ctr == NULL) {
8542 return NULL;
8545 switch (info_ctr->level) {
8546 case 1:
8547 return info_ctr->info.info1->driver_name;
8548 case 2:
8549 return info_ctr->info.info2->driver_name;
8550 case 3:
8551 return info_ctr->info.info3->driver_name;
8552 case 4:
8553 return info_ctr->info.info4->driver_name;
8554 case 6:
8555 return info_ctr->info.info6->driver_name;
8556 case 8:
8557 return info_ctr->info.info8->driver_name;
8558 default:
8559 return NULL;
8563 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8565 if (info_ctr == NULL) {
8566 return NULL;
8569 switch (info_ctr->level) {
8570 case 2:
8571 return info_ctr->info.info2->architecture;
8572 case 3:
8573 return info_ctr->info.info3->architecture;
8574 case 4:
8575 return info_ctr->info.info4->architecture;
8576 case 6:
8577 return info_ctr->info.info6->architecture;
8578 case 8:
8579 return info_ctr->info.info8->architecture;
8580 default:
8581 return NULL;
8586 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
8587 struct dcerpc_binding_handle *b,
8588 const char *servername,
8589 struct spoolss_AddDriverInfoCtr *info_ctr,
8590 WERROR expected_result)
8592 struct spoolss_AddPrinterDriver r;
8593 const char *drivername = get_driver_from_info(info_ctr);
8594 const char *environment = get_environment_from_info(info_ctr);
8596 r.in.servername = servername;
8597 r.in.info_ctr = info_ctr;
8599 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
8600 drivername, info_ctr->level, environment);
8602 torture_assert_ntstatus_ok(tctx,
8603 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
8604 "spoolss_AddPrinterDriver failed");
8605 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8606 "spoolss_AddPrinterDriver failed with unexpected result");
8608 return true;
8612 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
8613 struct dcerpc_binding_handle *b,
8614 const char *servername,
8615 struct spoolss_AddDriverInfoCtr *info_ctr,
8616 uint32_t flags,
8617 WERROR expected_result)
8619 struct spoolss_AddPrinterDriverEx r;
8620 const char *drivername = get_driver_from_info(info_ctr);
8621 const char *environment = get_environment_from_info(info_ctr);
8623 r.in.servername = servername;
8624 r.in.info_ctr = info_ctr;
8625 r.in.flags = flags;
8627 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
8628 drivername, info_ctr->level, environment);
8630 torture_assert_ntstatus_ok(tctx,
8631 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
8632 "AddPrinterDriverEx failed");
8633 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8634 "AddPrinterDriverEx failed with unexpected result");
8636 return true;
8639 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
8640 if (path && strlen(path)) {\
8641 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
8644 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
8645 struct dcerpc_binding_handle *b,
8646 const char *server_name,
8647 struct spoolss_AddDriverInfo8 *r,
8648 uint32_t flags,
8649 bool ex,
8650 const char *remote_driver_dir)
8652 struct spoolss_AddDriverInfoCtr info_ctr;
8653 struct spoolss_AddDriverInfo1 info1;
8655 ZERO_STRUCT(info1);
8657 info_ctr.level = 1;
8658 info_ctr.info.info1 = &info1;
8660 if (ex) {
8661 torture_assert(tctx,
8662 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8663 "failed to test AddPrinterDriverEx level 1");
8664 } else {
8665 torture_assert(tctx,
8666 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8667 "failed to test AddPrinterDriver level 1");
8670 info1.driver_name = r->driver_name;
8672 if (ex) {
8673 torture_assert(tctx,
8674 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8675 "failed to test AddPrinterDriverEx level 1");
8676 } else {
8677 torture_assert(tctx,
8678 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8679 "failed to test AddPrinterDriver level 1");
8682 return true;
8685 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
8686 struct dcerpc_binding_handle *b,
8687 const char *server_name,
8688 struct spoolss_AddDriverInfo8 *r,
8689 uint32_t flags,
8690 bool ex,
8691 const char *remote_driver_dir)
8693 struct spoolss_AddDriverInfoCtr info_ctr;
8694 struct spoolss_AddDriverInfo2 info2;
8695 union spoolss_DriverInfo info;
8697 ZERO_STRUCT(info2);
8699 info_ctr.level = 2;
8700 info_ctr.info.info2 = &info2;
8702 if (ex) {
8703 torture_assert(tctx,
8704 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8705 "failed to test AddPrinterDriverEx level 2");
8706 } else {
8707 torture_assert(tctx,
8708 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8709 "failed to test AddPrinterDriver level 2");
8712 info2.driver_name = r->driver_name;
8714 if (ex) {
8715 torture_assert(tctx,
8716 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8717 "failed to test AddPrinterDriverEx level 2");
8718 } else {
8719 torture_assert(tctx,
8720 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8721 "failed to test AddPrinterDriver level 2");
8724 info2.version = r->version;
8726 if (ex) {
8727 torture_assert(tctx,
8728 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8729 "failed to test AddPrinterDriverEx level 2");
8730 } else {
8731 torture_assert(tctx,
8732 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8733 "failed to test AddPrinterDriver level 2");
8736 info2.architecture = r->architecture;
8738 if (ex) {
8739 torture_assert(tctx,
8740 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8741 "failed to test AddPrinterDriverEx level 2");
8742 } else {
8743 torture_assert(tctx,
8744 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8745 "failed to test AddPrinterDriver level 2");
8748 info2.driver_path = r->driver_path;
8750 if (ex) {
8751 torture_assert(tctx,
8752 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8753 "failed to test AddPrinterDriverEx level 2");
8754 } else {
8755 torture_assert(tctx,
8756 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8757 "failed to test AddPrinterDriver level 2");
8760 info2.data_file = r->data_file;
8762 if (ex) {
8763 torture_assert(tctx,
8764 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8765 "failed to test AddPrinterDriverEx level 2");
8766 } else {
8767 torture_assert(tctx,
8768 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8769 "failed to test AddPrinterDriver level 2");
8772 info2.config_file = r->config_file;
8774 if (ex) {
8775 torture_assert(tctx,
8776 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
8777 "failed to test AddPrinterDriverEx");
8780 if (ex) {
8781 torture_assert(tctx,
8782 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8783 "failed to test AddPrinterDriverEx level 2");
8784 } else {
8785 torture_assert(tctx,
8786 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8787 "failed to test AddPrinterDriver level 2");
8790 torture_assert(tctx,
8791 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
8792 "failed to find added printer driver");
8794 if (remote_driver_dir) {
8795 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
8796 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
8797 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
8800 return true;
8803 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
8804 struct dcerpc_binding_handle *b,
8805 const char *server_name,
8806 struct spoolss_AddDriverInfo8 *r,
8807 uint32_t flags,
8808 bool ex,
8809 const char *remote_driver_dir)
8811 struct spoolss_AddDriverInfoCtr info_ctr;
8812 struct spoolss_AddDriverInfo3 info3;
8813 union spoolss_DriverInfo info;
8815 info3.driver_name = r->driver_name;
8816 info3.version = r->version;
8817 info3.architecture = r->architecture;
8818 info3.driver_path = r->driver_path;
8819 info3.data_file = r->data_file;
8820 info3.config_file = r->config_file;
8821 info3.help_file = r->help_file;
8822 info3.monitor_name = r->monitor_name;
8823 info3.default_datatype = r->default_datatype;
8824 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8825 info3.dependent_files = r->dependent_files;
8827 info_ctr.level = 3;
8828 info_ctr.info.info3 = &info3;
8830 if (ex) {
8831 torture_assert(tctx,
8832 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8833 "failed to test AddPrinterDriverEx level 3");
8834 } else {
8835 torture_assert(tctx,
8836 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8837 "failed to test AddPrinterDriver level 3");
8840 torture_assert(tctx,
8841 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
8842 "failed to find added printer driver");
8844 if (remote_driver_dir) {
8845 int i;
8846 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
8847 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
8848 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
8849 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
8850 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
8851 ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
8855 return true;
8858 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
8859 struct dcerpc_binding_handle *b,
8860 const char *server_name,
8861 struct spoolss_AddDriverInfo8 *r,
8862 uint32_t flags,
8863 bool ex,
8864 const char *remote_driver_dir)
8866 struct spoolss_AddDriverInfoCtr info_ctr;
8867 struct spoolss_AddDriverInfo4 info4;
8868 union spoolss_DriverInfo info;
8870 info4.version = r->version;
8871 info4.driver_name = r->driver_name;
8872 info4.architecture = r->architecture;
8873 info4.driver_path = r->driver_path;
8874 info4.data_file = r->data_file;
8875 info4.config_file = r->config_file;
8876 info4.help_file = r->help_file;
8877 info4.monitor_name = r->monitor_name;
8878 info4.default_datatype = r->default_datatype;
8879 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8880 info4.dependent_files = r->dependent_files;
8881 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
8882 info4.previous_names = r->previous_names;
8884 info_ctr.level = 4;
8885 info_ctr.info.info4 = &info4;
8887 if (ex) {
8888 torture_assert(tctx,
8889 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8890 "failed to test AddPrinterDriverEx level 4");
8891 } else {
8892 torture_assert(tctx,
8893 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8894 "failed to test AddPrinterDriver level 4");
8897 torture_assert(tctx,
8898 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
8899 "failed to find added printer driver");
8901 if (remote_driver_dir) {
8902 int i;
8903 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
8904 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
8905 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
8906 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
8907 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
8908 ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
8912 return true;
8915 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
8916 struct dcerpc_binding_handle *b,
8917 const char *server_name,
8918 struct spoolss_AddDriverInfo8 *r,
8919 uint32_t flags,
8920 bool ex,
8921 const char *remote_driver_dir)
8923 struct spoolss_AddDriverInfoCtr info_ctr;
8924 struct spoolss_AddDriverInfo6 info6;
8925 union spoolss_DriverInfo info;
8927 info6.version = r->version;
8928 info6.driver_name = r->driver_name;
8929 info6.architecture = r->architecture;
8930 info6.driver_path = r->driver_path;
8931 info6.data_file = r->data_file;
8932 info6.config_file = r->config_file;
8933 info6.help_file = r->help_file;
8934 info6.monitor_name = r->monitor_name;
8935 info6.default_datatype = r->default_datatype;
8936 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8937 info6.dependent_files = r->dependent_files;
8938 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
8939 info6.previous_names = r->previous_names;
8940 info6.driver_date = r->driver_date;
8941 info6.driver_version = r->driver_version;
8942 info6.manufacturer_name = r->manufacturer_name;
8943 info6.manufacturer_url = r->manufacturer_url;
8944 info6.hardware_id = r->hardware_id;
8945 info6.provider = r->provider;
8947 info_ctr.level = 6;
8948 info_ctr.info.info6 = &info6;
8950 if (ex) {
8951 torture_assert(tctx,
8952 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8953 "failed to test AddPrinterDriverEx level 6");
8954 } else {
8955 torture_assert(tctx,
8956 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8957 "failed to test AddPrinterDriver level 6");
8960 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8962 if (!ex) {
8963 return true;
8966 torture_assert(tctx,
8967 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
8968 "failed to find added printer driver");
8970 if (remote_driver_dir) {
8971 int i;
8972 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
8973 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
8974 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
8975 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
8976 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
8977 ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
8981 torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
8982 torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
8984 return true;
8987 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
8988 struct dcerpc_binding_handle *b,
8989 const char *server_name,
8990 struct spoolss_AddDriverInfo8 *r,
8991 uint32_t flags,
8992 bool ex,
8993 const char *remote_driver_dir)
8995 struct spoolss_AddDriverInfoCtr info_ctr;
8996 union spoolss_DriverInfo info;
8998 info_ctr.level = 8;
8999 info_ctr.info.info8 = r;
9001 if (ex) {
9002 torture_assert(tctx,
9003 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9004 "failed to test AddPrinterDriverEx level 8");
9005 } else {
9006 torture_assert(tctx,
9007 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9008 "failed to test AddPrinterDriver level 8");
9011 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9013 if (!ex) {
9014 return true;
9017 torture_assert(tctx,
9018 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
9019 "failed to find added printer driver");
9021 if (remote_driver_dir) {
9022 int i;
9023 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
9024 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
9025 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
9026 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
9027 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
9028 ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
9032 torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
9033 torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
9035 return true;
9038 #undef ASSERT_DRIVER_PATH
9040 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
9041 struct dcerpc_binding_handle *b,
9042 const char *server,
9043 const char *driver,
9044 const char *environment,
9045 WERROR expected_result)
9047 struct spoolss_DeletePrinterDriver r;
9049 r.in.server = server;
9050 r.in.architecture = environment;
9051 r.in.driver = driver;
9053 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
9055 torture_assert_ntstatus_ok(tctx,
9056 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
9057 "DeletePrinterDriver failed");
9058 torture_assert_werr_equal(tctx, r.out.result, expected_result,
9059 "DeletePrinterDriver failed with unexpected result");
9061 return true;
9064 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
9065 struct dcerpc_binding_handle *b,
9066 const char *server,
9067 const char *driver,
9068 const char *environment,
9069 uint32_t delete_flags,
9070 uint32_t version,
9071 WERROR expected_result)
9073 struct spoolss_DeletePrinterDriverEx r;
9075 r.in.server = server;
9076 r.in.architecture = environment;
9077 r.in.driver = driver;
9078 r.in.delete_flags = delete_flags;
9079 r.in.version = version;
9081 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
9083 torture_assert_ntstatus_ok(tctx,
9084 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
9085 "DeletePrinterDriverEx failed");
9086 torture_assert_werr_equal(tctx, r.out.result, expected_result,
9087 "DeletePrinterDriverEx failed with unexpected result");
9089 return true;
9092 static bool test_DeletePrinterDriver(struct torture_context *tctx,
9093 struct dcerpc_binding_handle *b,
9094 const char *server_name,
9095 const char *driver,
9096 const char *environment)
9098 torture_assert(tctx,
9099 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
9100 "failed to delete driver");
9102 torture_assert(tctx,
9103 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
9104 "failed to delete driver");
9106 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
9107 torture_fail(tctx, "deleted driver still enumerated");
9110 torture_assert(tctx,
9111 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
9112 "2nd delete failed");
9114 return true;
9117 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
9118 struct dcerpc_binding_handle *b,
9119 const char *server_name,
9120 const char *driver,
9121 const char *environment,
9122 uint32_t delete_flags,
9123 uint32_t version)
9125 torture_assert(tctx,
9126 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
9127 "failed to delete driver");
9129 torture_assert(tctx,
9130 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
9131 "failed to delete driver");
9133 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
9134 torture_fail(tctx, "deleted driver still enumerated");
9137 torture_assert(tctx,
9138 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
9139 "2nd delete failed");
9141 return true;
9144 static bool test_PrinterDriver_args(struct torture_context *tctx,
9145 struct dcerpc_binding_handle *b,
9146 const char *server_name,
9147 uint32_t level,
9148 struct spoolss_AddDriverInfo8 *r,
9149 uint32_t add_flags,
9150 uint32_t delete_flags,
9151 uint32_t delete_version,
9152 bool ex,
9153 const char *remote_driver_dir)
9155 bool ret = true;
9157 switch (level) {
9158 case 1:
9159 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9160 break;
9161 case 2:
9162 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9163 break;
9164 case 3:
9165 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9166 break;
9167 case 4:
9168 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9169 break;
9170 case 6:
9171 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9172 break;
9173 case 8:
9174 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9175 break;
9176 default:
9177 return false;
9180 if (ret == false) {
9181 return ret;
9184 if (level == 1) {
9185 return ret;
9188 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9190 if (!ex && (level == 6 || level == 8)) {
9191 return ret;
9195 struct dcerpc_pipe *p2;
9196 struct policy_handle hive_handle;
9197 struct dcerpc_binding_handle *b2;
9199 torture_assert_ntstatus_ok(tctx,
9200 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
9201 "could not open winreg pipe");
9202 b2 = p2->binding_handle;
9204 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
9206 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
9208 test_winreg_CloseKey(tctx, b2, &hive_handle);
9210 talloc_free(p2);
9213 if (ex) {
9214 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
9215 } else {
9216 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
9220 static bool fillup_printserver_info(struct torture_context *tctx,
9221 struct dcerpc_pipe *p,
9222 struct torture_driver_context *d)
9224 struct policy_handle server_handle;
9225 struct dcerpc_binding_handle *b = p->binding_handle;
9226 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9228 torture_assert(tctx,
9229 test_OpenPrinter_server(tctx, p, &server_handle),
9230 "failed to open printserver");
9231 torture_assert(tctx,
9232 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
9233 "failed to get environment");
9234 torture_assert(tctx,
9235 test_ClosePrinter(tctx, b, &server_handle),
9236 "failed to close printserver");
9238 torture_assert(tctx,
9239 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
9240 d->local.environment ? d->local.environment : d->remote.environment,
9241 &d->remote.driver_directory),
9242 "failed to get driver directory");
9244 return true;
9247 static const char *driver_directory_dir(const char *driver_directory)
9249 char *p;
9251 p = strrchr(driver_directory, '\\');
9252 if (p) {
9253 return p+1;
9256 return NULL;
9259 static const char *driver_directory_share(struct torture_context *tctx,
9260 const char *driver_directory)
9262 const char *p;
9263 char *tok;
9265 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
9266 driver_directory += 2;
9269 p = talloc_strdup(tctx, driver_directory);
9271 torture_assert(tctx,
9272 next_token_talloc(tctx, &p, &tok, "\\"),
9273 "cannot explode uri");
9274 torture_assert(tctx,
9275 next_token_talloc(tctx, &p, &tok, "\\"),
9276 "cannot explode uri");
9278 return tok;
9281 static bool upload_printer_driver_file(struct torture_context *tctx,
9282 struct smbcli_state *cli,
9283 struct torture_driver_context *d,
9284 const char *file_name)
9286 XFILE *f;
9287 int fnum;
9288 uint8_t *buf;
9289 int maxwrite = 64512;
9290 off_t nread = 0;
9291 size_t start = 0;
9292 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
9293 const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
9294 const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
9296 if (!file_name || strlen(file_name) == 0) {
9297 return true;
9300 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
9302 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
9303 if (fnum == -1) {
9304 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
9307 f = x_fopen(local_name, O_RDONLY, 0);
9308 if (f == NULL) {
9309 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
9312 buf = talloc_array(tctx, uint8_t, maxwrite);
9313 if (!buf) {
9314 x_fclose(f);
9315 return false;
9318 while (!x_feof(f)) {
9319 int n = maxwrite;
9320 int ret;
9322 if ((n = x_fread(buf, 1, n, f)) < 1) {
9323 if((n == 0) && x_feof(f))
9324 break; /* Empty local file. */
9326 torture_warning(tctx,
9327 "failed to read file: %s\n", strerror(errno));
9328 break;
9331 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
9333 if (n != ret) {
9334 torture_warning(tctx,
9335 "failed to write file: %s\n", smbcli_errstr(cli->tree));
9336 break;
9339 nread += n;
9342 x_fclose(f);
9344 torture_assert_ntstatus_ok(tctx,
9345 smbcli_close(cli->tree, fnum),
9346 "failed to close file");
9348 return true;
9351 static bool connect_printer_driver_share(struct torture_context *tctx,
9352 const char *server_name,
9353 const char *share_name,
9354 struct smbcli_state **cli)
9356 struct smbcli_options smb_options;
9357 struct smbcli_session_options smb_session_options;
9359 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
9360 share_name, server_name);
9362 lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
9363 lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
9365 torture_assert_ntstatus_ok(tctx,
9366 smbcli_full_connection(tctx, cli, server_name,
9367 lpcfg_smb_ports(tctx->lp_ctx),
9368 share_name, NULL,
9369 lpcfg_socket_options(tctx->lp_ctx),
9370 cmdline_credentials,
9371 lpcfg_resolve_context(tctx->lp_ctx),
9372 tctx->ev,
9373 &smb_options,
9374 &smb_session_options,
9375 lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
9376 "failed to open driver share");
9378 return true;
9381 static bool upload_printer_driver(struct torture_context *tctx,
9382 const char *server_name,
9383 struct torture_driver_context *d)
9385 struct smbcli_state *cli;
9386 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9387 int i;
9389 torture_assert(tctx,
9390 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9391 "failed to connect to driver share");
9393 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
9394 server_name, share_name);
9396 torture_assert(tctx,
9397 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
9398 "failed to upload driver_path");
9399 torture_assert(tctx,
9400 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
9401 "failed to upload data_file");
9402 torture_assert(tctx,
9403 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
9404 "failed to upload config_file");
9405 torture_assert(tctx,
9406 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
9407 "failed to upload help_file");
9408 if (d->info8.dependent_files) {
9409 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9410 torture_assert(tctx,
9411 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9412 "failed to upload dependent_files");
9416 talloc_free(cli);
9418 return true;
9421 static bool check_printer_driver_file(struct torture_context *tctx,
9422 struct smbcli_state *cli,
9423 struct torture_driver_context *d,
9424 const char *file_name)
9426 const char *remote_arch_dir = driver_directory_dir(d->remote.driver_directory);
9427 const char *remote_name = talloc_asprintf(tctx, "%s\\%d\\%s",
9428 remote_arch_dir,
9429 d->info8.version,
9430 file_name);
9431 int fnum;
9433 torture_assert(tctx, (file_name && strlen(file_name) != 0), "invalid filename");
9435 torture_comment(tctx, "checking for driver file at %s\n", remote_name);
9437 fnum = smbcli_open(cli->tree, remote_name, O_RDONLY, DENY_NONE);
9438 if (fnum == -1) {
9439 return false;
9442 torture_assert_ntstatus_ok(tctx,
9443 smbcli_close(cli->tree, fnum),
9444 "failed to close driver file");
9446 return true;
9449 static bool check_printer_driver_files(struct torture_context *tctx,
9450 const char *server_name,
9451 struct torture_driver_context *d,
9452 bool expect_exist)
9454 struct smbcli_state *cli;
9455 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9456 int i;
9458 torture_assert(tctx,
9459 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9460 "failed to connect to driver share");
9462 torture_comment(tctx, "checking %sexistent driver files at \\\\%s\\%s\n",
9463 (expect_exist ? "": "non-"),
9464 server_name, share_name);
9466 if (d->info8.driver_path && d->info8.driver_path[0]) {
9467 torture_assert(tctx,
9468 check_printer_driver_file(tctx, cli, d, d->info8.driver_path) == expect_exist,
9469 "failed driver_path check");
9471 if (d->info8.data_file && d->info8.data_file[0]) {
9472 torture_assert(tctx,
9473 check_printer_driver_file(tctx, cli, d, d->info8.data_file) == expect_exist,
9474 "failed data_file check");
9476 if (d->info8.config_file && d->info8.config_file[0]) {
9477 torture_assert(tctx,
9478 check_printer_driver_file(tctx, cli, d, d->info8.config_file) == expect_exist,
9479 "failed config_file check");
9481 if (d->info8.help_file && d->info8.help_file[0]) {
9482 torture_assert(tctx,
9483 check_printer_driver_file(tctx, cli, d, d->info8.help_file) == expect_exist,
9484 "failed help_file check");
9486 if (d->info8.dependent_files) {
9487 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9488 torture_assert(tctx,
9489 check_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]) == expect_exist,
9490 "failed dependent_files check");
9494 talloc_free(cli);
9496 return true;
9499 static bool remove_printer_driver_file(struct torture_context *tctx,
9500 struct smbcli_state *cli,
9501 struct torture_driver_context *d,
9502 const char *file_name)
9504 const char *remote_name;
9505 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
9507 if (!file_name || strlen(file_name) == 0) {
9508 return true;
9511 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
9513 torture_comment(tctx, "Removing %s\n", remote_name);
9515 torture_assert_ntstatus_ok(tctx,
9516 smbcli_unlink(cli->tree, remote_name),
9517 "failed to unlink");
9519 return true;
9522 static bool remove_printer_driver(struct torture_context *tctx,
9523 const char *server_name,
9524 struct torture_driver_context *d)
9526 struct smbcli_state *cli;
9527 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9528 int i;
9530 torture_assert(tctx,
9531 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9532 "failed to connect to driver share");
9534 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
9535 server_name, share_name);
9537 torture_assert(tctx,
9538 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
9539 "failed to remove driver_path");
9540 torture_assert(tctx,
9541 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
9542 "failed to remove data_file");
9543 if (!strequal(d->info8.config_file, d->info8.driver_path)) {
9544 torture_assert(tctx,
9545 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
9546 "failed to remove config_file");
9548 torture_assert(tctx,
9549 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
9550 "failed to remove help_file");
9551 if (d->info8.dependent_files) {
9552 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9553 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
9554 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
9555 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
9556 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
9557 continue;
9559 torture_assert(tctx,
9560 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9561 "failed to remove dependent_files");
9565 talloc_free(cli);
9567 return true;
9571 static bool test_add_driver_arg(struct torture_context *tctx,
9572 struct dcerpc_pipe *p,
9573 struct torture_driver_context *d)
9575 bool ret = true;
9576 struct dcerpc_binding_handle *b = p->binding_handle;
9577 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9578 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
9579 int i;
9580 struct spoolss_AddDriverInfo8 info8;
9581 uint32_t add_flags = APD_COPY_NEW_FILES;
9582 uint32_t delete_flags = 0;
9584 ZERO_STRUCT(info8);
9586 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
9587 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
9589 torture_assert(tctx,
9590 fillup_printserver_info(tctx, p, d),
9591 "failed to fillup printserver info");
9593 if (!directory_exist(d->local.driver_directory)) {
9594 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9597 torture_assert(tctx,
9598 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9599 "failed to upload printer driver");
9601 info8 = d->info8;
9602 if (d->info8.dependent_files) {
9603 info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
9604 if (d->info8.dependent_files->string) {
9605 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9607 info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
9608 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9609 info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
9613 info8.architecture = d->local.environment;
9615 for (i=0; i < ARRAY_SIZE(levels); i++) {
9617 if (torture_setting_bool(tctx, "samba3", false)) {
9618 switch (levels[i]) {
9619 case 2:
9620 case 4:
9621 case 8:
9622 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9623 continue;
9624 default:
9625 break;
9628 if (torture_setting_bool(tctx, "w2k3", false)) {
9629 switch (levels[i]) {
9630 case 8:
9631 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9632 continue;
9633 default:
9634 break;
9638 torture_comment(tctx,
9639 "Testing PrinterDriver%s '%s' add & delete level %d\n",
9640 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9642 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);
9645 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
9646 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
9647 if (d->info8.config_file) {
9648 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
9650 if (d->info8.help_file) {
9651 info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
9653 if (d->info8.dependent_files && d->info8.dependent_files->string) {
9654 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9655 info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
9659 for (i=0; i < ARRAY_SIZE(levels); i++) {
9661 if (torture_setting_bool(tctx, "samba3", false)) {
9662 switch (levels[i]) {
9663 case 2:
9664 case 4:
9665 case 8:
9666 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9667 continue;
9668 default:
9669 break;
9672 if (torture_setting_bool(tctx, "w2k3", false)) {
9673 switch (levels[i]) {
9674 case 8:
9675 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9676 continue;
9677 default:
9678 break;
9682 torture_comment(tctx,
9683 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
9684 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9686 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);
9689 torture_assert(tctx,
9690 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9691 "failed to remove printer driver");
9693 torture_comment(tctx, "\n");
9695 return ret;
9698 static bool test_add_driver_ex_64(struct torture_context *tctx,
9699 struct dcerpc_pipe *p)
9701 struct torture_driver_context *d;
9703 d = talloc_zero(tctx, struct torture_driver_context);
9705 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9706 d->info8.driver_name = TORTURE_DRIVER_EX;
9707 d->info8.architecture = NULL;
9708 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9709 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9710 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9711 d->local.environment = talloc_strdup(d, "Windows x64");
9712 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9713 d->ex = true;
9715 return test_add_driver_arg(tctx, p, d);
9718 static bool test_add_driver_ex_32(struct torture_context *tctx,
9719 struct dcerpc_pipe *p)
9721 struct torture_driver_context *d;
9723 d = talloc_zero(tctx, struct torture_driver_context);
9725 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9726 d->info8.driver_name = TORTURE_DRIVER_EX;
9727 d->info8.architecture = NULL;
9728 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9729 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9730 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9731 d->local.environment = talloc_strdup(d, "Windows NT x86");
9732 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9733 d->ex = true;
9735 return test_add_driver_arg(tctx, p, d);
9738 static bool test_add_driver_64(struct torture_context *tctx,
9739 struct dcerpc_pipe *p)
9741 struct torture_driver_context *d;
9743 d = talloc_zero(tctx, struct torture_driver_context);
9745 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9746 d->info8.driver_name = TORTURE_DRIVER;
9747 d->info8.architecture = NULL;
9748 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9749 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9750 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9751 d->local.environment = talloc_strdup(d, "Windows x64");
9752 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9753 d->ex = false;
9755 return test_add_driver_arg(tctx, p, d);
9758 static bool test_add_driver_32(struct torture_context *tctx,
9759 struct dcerpc_pipe *p)
9761 struct torture_driver_context *d;
9763 d = talloc_zero(tctx, struct torture_driver_context);
9765 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9766 d->info8.driver_name = TORTURE_DRIVER;
9767 d->info8.architecture = NULL;
9768 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9769 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9770 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9771 d->local.environment = talloc_strdup(d, "Windows NT x86");
9772 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9773 d->ex = false;
9775 return test_add_driver_arg(tctx, p, d);
9778 static bool test_add_driver_adobe(struct torture_context *tctx,
9779 struct dcerpc_pipe *p)
9781 struct torture_driver_context *d;
9783 if (!torture_setting_bool(tctx, "samba3", false)) {
9784 torture_skip(tctx, "skipping adobe test which only works against samba3");
9787 d = talloc_zero(tctx, struct torture_driver_context);
9789 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9790 d->info8.driver_name = TORTURE_DRIVER_ADOBE;
9791 d->info8.architecture = NULL;
9792 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9793 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9794 d->info8.config_file = talloc_strdup(d, "ADOBEPS4.DRV");
9795 #if 0
9796 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9797 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9798 #endif
9799 d->local.environment = talloc_strdup(d, "Windows 4.0");
9800 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9801 d->ex = false;
9803 return test_add_driver_arg(tctx, p, d);
9806 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
9807 struct dcerpc_pipe *p)
9809 struct torture_driver_context *d;
9810 struct spoolss_StringArray *a;
9812 if (!torture_setting_bool(tctx, "samba3", false)) {
9813 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
9816 d = talloc_zero(tctx, struct torture_driver_context);
9818 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9819 d->info8.driver_name = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
9820 d->info8.architecture = NULL;
9821 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9822 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9823 d->info8.config_file = NULL;
9824 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9825 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9826 d->info8.default_datatype = talloc_strdup(d, "RAW");
9828 a = talloc_zero(d, struct spoolss_StringArray);
9829 a->string = talloc_zero_array(a, const char *, 7);
9830 a->string[0] = talloc_strdup(a->string, "ADOBEPS4.DRV");
9831 a->string[1] = talloc_strdup(a->string, "DEFPRTR2.PPD");
9832 a->string[2] = talloc_strdup(a->string, "ADOBEPS4.HLP");
9833 a->string[3] = talloc_strdup(a->string, "PSMON.DLL");
9834 a->string[4] = talloc_strdup(a->string, "ADFONTS.MFM");
9835 a->string[5] = talloc_strdup(a->string, "ICONLIB.DLL");
9837 d->info8.dependent_files = a;
9838 d->local.environment = talloc_strdup(d, "Windows 4.0");
9839 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9840 d->ex = false;
9842 return test_add_driver_arg(tctx, p, d);
9845 static bool test_add_driver_timestamps(struct torture_context *tctx,
9846 struct dcerpc_pipe *p)
9848 struct torture_driver_context *d;
9849 struct timeval t = timeval_current();
9851 d = talloc_zero(tctx, struct torture_driver_context);
9853 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9854 d->info8.driver_name = TORTURE_DRIVER_TIMESTAMPS;
9855 d->info8.architecture = NULL;
9856 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9857 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9858 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9859 d->info8.driver_date = timeval_to_nttime(&t);
9860 d->local.environment = talloc_strdup(d, "Windows NT x86");
9861 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9862 d->ex = true;
9864 torture_assert(tctx,
9865 test_add_driver_arg(tctx, p, d),
9866 "");
9868 unix_to_nt_time(&d->info8.driver_date, 1);
9870 torture_assert(tctx,
9871 test_add_driver_arg(tctx, p, d),
9872 "");
9874 return true;
9877 static bool test_multiple_drivers(struct torture_context *tctx,
9878 struct dcerpc_pipe *p)
9880 struct torture_driver_context *d;
9881 struct dcerpc_binding_handle *b = p->binding_handle;
9882 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9883 int i;
9884 struct spoolss_AddDriverInfo8 info8;
9885 uint32_t add_flags = APD_COPY_NEW_FILES;
9886 uint32_t delete_flags = 0;
9888 d = talloc_zero(tctx, struct torture_driver_context);
9890 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9891 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9892 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9893 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9894 d->local.environment = talloc_strdup(d, "Windows NT x86");
9895 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9896 d->ex = true;
9898 torture_assert(tctx,
9899 fillup_printserver_info(tctx, p, d),
9900 "failed to fillup printserver info");
9902 if (!directory_exist(d->local.driver_directory)) {
9903 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9906 torture_assert(tctx,
9907 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9908 "failed to upload printer driver");
9910 info8 = d->info8;
9911 info8.architecture = d->local.environment;
9913 for (i=0; i < 3; i++) {
9914 info8.driver_name = talloc_asprintf(d, "torture_test_driver_%d", i);
9916 torture_assert(tctx,
9917 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &info8, add_flags, true, NULL),
9918 "failed to add driver");
9921 torture_assert(tctx,
9922 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_0", info8.architecture, delete_flags, info8.version),
9923 "failed to delete driver");
9925 torture_assert(tctx,
9926 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_1", NULL),
9927 "torture_test_driver_1 no longer on the server");
9929 torture_assert(tctx,
9930 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
9931 "torture_test_driver_2 no longer on the server");
9933 torture_assert(tctx,
9934 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_1", info8.architecture, delete_flags, info8.version),
9935 "failed to delete driver");
9937 torture_assert(tctx,
9938 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
9939 "torture_test_driver_2 no longer on the server");
9941 torture_assert(tctx,
9942 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_2", info8.architecture, delete_flags, info8.version),
9943 "failed to delete driver");
9945 torture_assert(tctx,
9946 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9947 "failed to remove printer driver");
9949 return true;
9952 static bool test_del_driver_all_files(struct torture_context *tctx,
9953 struct dcerpc_pipe *p)
9955 struct torture_driver_context *d;
9956 struct spoolss_StringArray *a;
9957 uint32_t add_flags = APD_COPY_NEW_FILES;
9958 uint32_t delete_flags = DPD_DELETE_ALL_FILES;
9959 struct dcerpc_binding_handle *b = p->binding_handle;
9960 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9962 d = talloc_zero(tctx, struct torture_driver_context);
9964 d->ex = true;
9965 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9966 d->info8.driver_name = TORTURE_DRIVER_DELETER;
9967 d->info8.architecture = NULL;
9968 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9969 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9970 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9971 d->info8.help_file = talloc_strdup(d, "pscript.hlp");
9972 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
9973 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9975 a = talloc_zero(d, struct spoolss_StringArray);
9976 a->string = talloc_zero_array(a, const char *, 3);
9977 a->string[0] = talloc_strdup(a->string, "cups6.inf");
9978 a->string[1] = talloc_strdup(a->string, "cups6.ini");
9980 d->info8.dependent_files = a;
9981 d->info8.architecture = d->local.environment;
9983 torture_assert(tctx,
9984 fillup_printserver_info(tctx, p, d),
9985 "failed to fillup printserver info");
9987 if (!directory_exist(d->local.driver_directory)) {
9988 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9991 torture_assert(tctx,
9992 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9993 "failed to upload printer driver");
9995 torture_assert(tctx,
9996 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d->info8, add_flags, true, NULL),
9997 "failed to add driver");
9999 torture_assert(tctx,
10000 test_DeletePrinterDriverEx(tctx, b, server_name_slash,
10001 d->info8.driver_name,
10002 d->local.environment,
10003 delete_flags,
10004 d->info8.version),
10005 "failed to delete driver");
10007 torture_assert(tctx,
10008 check_printer_driver_files(tctx, dcerpc_server_name(p), d, false),
10009 "printer driver file check failed");
10011 talloc_free(d);
10012 return true;
10015 static bool test_del_driver_unused_files(struct torture_context *tctx,
10016 struct dcerpc_pipe *p)
10018 struct torture_driver_context *d1;
10019 struct torture_driver_context *d2;
10020 uint32_t add_flags = APD_COPY_NEW_FILES;
10021 struct dcerpc_binding_handle *b = p->binding_handle;
10022 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10024 d1 = talloc_zero(tctx, struct torture_driver_context);
10025 d1->ex = true;
10026 d1->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10027 d1->info8.driver_name = TORTURE_DRIVER_DELETER;
10028 d1->info8.architecture = NULL;
10029 d1->info8.driver_path = talloc_strdup(d1, "pscript5.dll");
10030 d1->info8.data_file = talloc_strdup(d1, "cups6.ppd");
10031 d1->info8.config_file = talloc_strdup(d1, "cupsui6.dll");
10032 d1->info8.help_file = talloc_strdup(d1, "pscript.hlp");
10033 d1->local.environment = talloc_strdup(d1, SPOOLSS_ARCHITECTURE_x64);
10034 d1->local.driver_directory = talloc_strdup(d1, "/usr/share/cups/drivers/x64");
10035 d1->info8.architecture = d1->local.environment;
10037 d2 = talloc_zero(tctx, struct torture_driver_context);
10038 d2->ex = true;
10039 d2->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10040 d2->info8.driver_name = TORTURE_DRIVER_DELETERIN;
10041 d2->info8.architecture = NULL;
10042 d2->info8.driver_path = talloc_strdup(d2, "pscript5.dll"); /* overlapping */
10043 d2->info8.data_file = talloc_strdup(d2, "cupsps6.dll");
10044 d2->info8.config_file = talloc_strdup(d2, "cups6.ini");
10045 d2->info8.help_file = talloc_strdup(d2, "pscript.hlp"); /* overlapping */
10046 d2->local.environment = talloc_strdup(d2, SPOOLSS_ARCHITECTURE_x64);
10047 d2->local.driver_directory = talloc_strdup(d2, "/usr/share/cups/drivers/x64");
10048 d2->info8.architecture = d2->local.environment;
10050 torture_assert(tctx,
10051 fillup_printserver_info(tctx, p, d1),
10052 "failed to fillup printserver info");
10053 torture_assert(tctx,
10054 fillup_printserver_info(tctx, p, d2),
10055 "failed to fillup printserver info");
10057 if (!directory_exist(d1->local.driver_directory)) {
10058 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10061 torture_assert(tctx,
10062 upload_printer_driver(tctx, dcerpc_server_name(p), d1),
10063 "failed to upload printer driver");
10064 torture_assert(tctx,
10065 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d1->info8, add_flags, true, NULL),
10066 "failed to add driver");
10068 torture_assert(tctx,
10069 upload_printer_driver(tctx, dcerpc_server_name(p), d2),
10070 "failed to upload printer driver");
10071 torture_assert(tctx,
10072 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d2->info8, add_flags, true, NULL),
10073 "failed to add driver");
10075 /* some files are in use by a separate driver, should fail */
10076 torture_assert(tctx,
10077 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10078 d1->info8.driver_name,
10079 d1->local.environment,
10080 DPD_DELETE_ALL_FILES,
10081 d1->info8.version,
10082 WERR_PRINTER_DRIVER_IN_USE),
10083 "invalid delete driver response");
10085 /* should only delete files not in use by other driver */
10086 torture_assert(tctx,
10087 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10088 d1->info8.driver_name,
10089 d1->local.environment,
10090 DPD_DELETE_UNUSED_FILES,
10091 d1->info8.version,
10092 WERR_OK),
10093 "failed to delete driver (unused files)");
10095 /* check non-overlapping were deleted */
10096 d1->info8.driver_path = NULL;
10097 d1->info8.help_file = NULL;
10098 torture_assert(tctx,
10099 check_printer_driver_files(tctx, dcerpc_server_name(p), d1, false),
10100 "printer driver file check failed");
10101 /* d2 files should be uneffected */
10102 torture_assert(tctx,
10103 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, true),
10104 "printer driver file check failed");
10106 torture_assert(tctx,
10107 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10108 d2->info8.driver_name,
10109 d2->local.environment,
10110 DPD_DELETE_ALL_FILES,
10111 d2->info8.version,
10112 WERR_OK),
10113 "failed to delete driver");
10115 torture_assert(tctx,
10116 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, false),
10117 "printer driver file check failed");
10119 talloc_free(d1);
10120 talloc_free(d2);
10121 return true;
10124 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
10126 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
10128 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
10129 "driver", &ndr_table_spoolss);
10130 torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
10131 torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
10133 torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
10134 torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
10136 torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
10138 torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
10140 torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
10142 torture_rpc_tcase_add_test(tcase, "multiple_drivers", test_multiple_drivers);
10144 torture_rpc_tcase_add_test(tcase, "del_driver_all_files", test_del_driver_all_files);
10146 torture_rpc_tcase_add_test(tcase, "del_driver_unused_files", test_del_driver_unused_files);
10148 return suite;