docs: mention --update and --encrypt in smbget manpage.
[Samba.git] / source4 / torture / rpc / spoolss.c
blobf2a44c9c46d018d69888c221f6d758599291c0f2
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(tctx, (W_ERROR_EQUAL(r.out.result, WERR_OK)
1251 || W_ERROR_EQUAL(r.out.result, WERR_IO_PENDING)),
1252 "SetPrinter failed");
1254 return true;
1257 static bool test_SetPrinter_errors(struct torture_context *tctx,
1258 struct dcerpc_binding_handle *b,
1259 struct policy_handle *handle)
1261 struct spoolss_SetPrinter r;
1262 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1263 int i;
1265 struct spoolss_SetPrinterInfoCtr info_ctr;
1266 struct spoolss_DevmodeContainer devmode_ctr;
1267 struct sec_desc_buf secdesc_ctr;
1269 info_ctr.level = 0;
1270 info_ctr.info.info0 = NULL;
1272 ZERO_STRUCT(devmode_ctr);
1273 ZERO_STRUCT(secdesc_ctr);
1275 r.in.handle = handle;
1276 r.in.info_ctr = &info_ctr;
1277 r.in.devmode_ctr = &devmode_ctr;
1278 r.in.secdesc_ctr = &secdesc_ctr;
1279 r.in.command = 0;
1281 torture_comment(tctx, "Testing SetPrinter all zero\n");
1283 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1284 "failed to call SetPrinter");
1285 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1286 "failed to call SetPrinter");
1288 again:
1289 for (i=0; i < ARRAY_SIZE(levels); i++) {
1291 struct spoolss_SetPrinterInfo0 info0;
1292 struct spoolss_SetPrinterInfo1 info1;
1293 struct spoolss_SetPrinterInfo2 info2;
1294 struct spoolss_SetPrinterInfo3 info3;
1295 struct spoolss_SetPrinterInfo4 info4;
1296 struct spoolss_SetPrinterInfo5 info5;
1297 struct spoolss_SetPrinterInfo6 info6;
1298 struct spoolss_SetPrinterInfo7 info7;
1299 struct spoolss_SetPrinterInfo8 info8;
1300 struct spoolss_SetPrinterInfo9 info9;
1303 info_ctr.level = levels[i];
1304 switch (levels[i]) {
1305 case 0:
1306 ZERO_STRUCT(info0);
1307 info_ctr.info.info0 = &info0;
1308 break;
1309 case 1:
1310 ZERO_STRUCT(info1);
1311 info_ctr.info.info1 = &info1;
1312 break;
1313 case 2:
1314 ZERO_STRUCT(info2);
1315 info_ctr.info.info2 = &info2;
1316 break;
1317 case 3:
1318 ZERO_STRUCT(info3);
1319 info_ctr.info.info3 = &info3;
1320 break;
1321 case 4:
1322 ZERO_STRUCT(info4);
1323 info_ctr.info.info4 = &info4;
1324 break;
1325 case 5:
1326 ZERO_STRUCT(info5);
1327 info_ctr.info.info5 = &info5;
1328 break;
1329 case 6:
1330 ZERO_STRUCT(info6);
1331 info_ctr.info.info6 = &info6;
1332 break;
1333 case 7:
1334 ZERO_STRUCT(info7);
1335 info_ctr.info.info7 = &info7;
1336 break;
1337 case 8:
1338 ZERO_STRUCT(info8);
1339 info_ctr.info.info8 = &info8;
1340 break;
1341 case 9:
1342 ZERO_STRUCT(info9);
1343 info_ctr.info.info9 = &info9;
1344 break;
1347 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1348 info_ctr.level, r.in.command);
1350 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1351 "failed to call SetPrinter");
1353 switch (r.in.command) {
1354 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1355 /* is ignored for all levels other then 0 */
1356 if (info_ctr.level > 0) {
1357 /* ignored then */
1358 break;
1360 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1361 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1362 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1363 if (info_ctr.level > 0) {
1364 /* is invalid for all levels other then 0 */
1365 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1366 "unexpected error code returned");
1367 continue;
1368 } else {
1369 torture_assert_werr_ok(tctx, r.out.result,
1370 "failed to call SetPrinter with non 0 command");
1371 continue;
1373 break;
1375 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1376 /* FIXME: gd needs further investigation */
1377 default:
1378 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1379 "unexpected error code returned");
1380 continue;
1383 switch (info_ctr.level) {
1384 case 1:
1385 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1386 "unexpected error code returned");
1387 break;
1388 case 2:
1389 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1390 "unexpected error code returned");
1391 break;
1392 case 3:
1393 case 4:
1394 case 5:
1395 case 7:
1396 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1397 "unexpected error code returned");
1398 break;
1399 case 9:
1400 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1401 "unexpected error code returned");
1402 break;
1403 default:
1404 torture_assert_werr_ok(tctx, r.out.result,
1405 "failed to call SetPrinter");
1406 break;
1410 if (r.in.command < 5) {
1411 r.in.command++;
1412 goto again;
1415 return true;
1418 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1420 if ((r->level == 2) && (r->info.info2)) {
1421 r->info.info2->secdesc_ptr = NULL;
1422 r->info.info2->devmode_ptr = NULL;
1426 static bool test_PrinterInfo(struct torture_context *tctx,
1427 struct dcerpc_binding_handle *b,
1428 struct policy_handle *handle)
1430 NTSTATUS status;
1431 struct spoolss_SetPrinter s;
1432 struct spoolss_GetPrinter q;
1433 struct spoolss_GetPrinter q0;
1434 struct spoolss_SetPrinterInfoCtr info_ctr;
1435 union spoolss_PrinterInfo info;
1436 struct spoolss_DevmodeContainer devmode_ctr;
1437 struct sec_desc_buf secdesc_ctr;
1438 uint32_t needed;
1439 bool ret = true;
1440 int i;
1442 torture_skip(tctx, "Printer Info test is currently broken, skipping");
1444 uint32_t status_list[] = {
1445 /* these do not stick
1446 PRINTER_STATUS_PAUSED,
1447 PRINTER_STATUS_ERROR,
1448 PRINTER_STATUS_PENDING_DELETION, */
1449 PRINTER_STATUS_PAPER_JAM,
1450 PRINTER_STATUS_PAPER_OUT,
1451 PRINTER_STATUS_MANUAL_FEED,
1452 PRINTER_STATUS_PAPER_PROBLEM,
1453 PRINTER_STATUS_OFFLINE,
1454 PRINTER_STATUS_IO_ACTIVE,
1455 PRINTER_STATUS_BUSY,
1456 PRINTER_STATUS_PRINTING,
1457 PRINTER_STATUS_OUTPUT_BIN_FULL,
1458 PRINTER_STATUS_NOT_AVAILABLE,
1459 PRINTER_STATUS_WAITING,
1460 PRINTER_STATUS_PROCESSING,
1461 PRINTER_STATUS_INITIALIZING,
1462 PRINTER_STATUS_WARMING_UP,
1463 PRINTER_STATUS_TONER_LOW,
1464 PRINTER_STATUS_NO_TONER,
1465 PRINTER_STATUS_PAGE_PUNT,
1466 PRINTER_STATUS_USER_INTERVENTION,
1467 PRINTER_STATUS_OUT_OF_MEMORY,
1468 PRINTER_STATUS_DOOR_OPEN,
1469 PRINTER_STATUS_SERVER_UNKNOWN,
1470 PRINTER_STATUS_POWER_SAVE,
1471 /* these do not stick
1472 0x02000000,
1473 0x04000000,
1474 0x08000000,
1475 0x10000000,
1476 0x20000000,
1477 0x40000000,
1478 0x80000000 */
1480 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1481 uint32_t attribute_list[] = {
1482 PRINTER_ATTRIBUTE_QUEUED,
1483 /* fails with WERR_INVALID_DATATYPE:
1484 PRINTER_ATTRIBUTE_DIRECT, */
1485 /* does not stick
1486 PRINTER_ATTRIBUTE_DEFAULT, */
1487 PRINTER_ATTRIBUTE_SHARED,
1488 /* does not stick
1489 PRINTER_ATTRIBUTE_NETWORK, */
1490 PRINTER_ATTRIBUTE_HIDDEN,
1491 PRINTER_ATTRIBUTE_LOCAL,
1492 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1493 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1494 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1495 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1496 /* does not stick
1497 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1498 /* fails with WERR_INVALID_DATATYPE:
1499 PRINTER_ATTRIBUTE_RAW_ONLY, */
1500 /* these do not stick
1501 PRINTER_ATTRIBUTE_PUBLISHED,
1502 PRINTER_ATTRIBUTE_FAX,
1503 PRINTER_ATTRIBUTE_TS,
1504 0x00010000,
1505 0x00020000,
1506 0x00040000,
1507 0x00080000,
1508 0x00100000,
1509 0x00200000,
1510 0x00400000,
1511 0x00800000,
1512 0x01000000,
1513 0x02000000,
1514 0x04000000,
1515 0x08000000,
1516 0x10000000,
1517 0x20000000,
1518 0x40000000,
1519 0x80000000 */
1522 ZERO_STRUCT(devmode_ctr);
1523 ZERO_STRUCT(secdesc_ctr);
1525 s.in.handle = handle;
1526 s.in.command = 0;
1527 s.in.info_ctr = &info_ctr;
1528 s.in.devmode_ctr = &devmode_ctr;
1529 s.in.secdesc_ctr = &secdesc_ctr;
1531 q.in.handle = handle;
1532 q.out.info = &info;
1533 q0 = q;
1535 #define TESTGETCALL(call, r) \
1536 r.in.buffer = NULL; \
1537 r.in.offered = 0;\
1538 r.out.needed = &needed; \
1539 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1540 if (!NT_STATUS_IS_OK(status)) { \
1541 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1542 r.in.level, nt_errstr(status), __location__); \
1543 ret = false; \
1544 break; \
1546 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1547 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1548 r.in.buffer = &blob; \
1549 r.in.offered = needed; \
1551 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1552 if (!NT_STATUS_IS_OK(status)) { \
1553 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1554 r.in.level, nt_errstr(status), __location__); \
1555 ret = false; \
1556 break; \
1558 if (!W_ERROR_IS_OK(r.out.result)) { \
1559 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1560 r.in.level, win_errstr(r.out.result), __location__); \
1561 ret = false; \
1562 break; \
1566 #define TESTSETCALL_EXP(call, r, err) \
1567 clear_info2(&info_ctr);\
1568 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1569 if (!NT_STATUS_IS_OK(status)) { \
1570 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1571 r.in.info_ctr->level, nt_errstr(status), __location__); \
1572 ret = false; \
1573 break; \
1575 if (!W_ERROR_IS_OK(err)) { \
1576 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1577 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1578 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1579 ret = false; \
1581 break; \
1583 if (!W_ERROR_IS_OK(r.out.result)) { \
1584 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1585 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1586 ret = false; \
1587 break; \
1590 #define TESTSETCALL(call, r) \
1591 TESTSETCALL_EXP(call, r, WERR_OK)
1593 #define STRING_EQUAL(s1, s2, field) \
1594 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1595 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1596 #field, s2, __location__); \
1597 ret = false; \
1598 break; \
1601 #define MEM_EQUAL(s1, s2, length, field) \
1602 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1603 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1604 #field, (const char *)s2, __location__); \
1605 ret = false; \
1606 break; \
1609 #define INT_EQUAL(i1, i2, field) \
1610 if (i1 != i2) { \
1611 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1612 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1613 ret = false; \
1614 break; \
1617 #define SD_EQUAL(sd1, sd2, field) \
1618 if (!security_descriptor_equal(sd1, sd2)) { \
1619 torture_comment(tctx, "Failed to set %s (%s)\n", \
1620 #field, __location__); \
1621 ret = false; \
1622 break; \
1625 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1626 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1627 q.in.level = lvl1; \
1628 TESTGETCALL(GetPrinter, q) \
1629 info_ctr.level = lvl1; \
1630 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1631 info_ctr.info.info ## lvl1->field1 = value;\
1632 TESTSETCALL_EXP(SetPrinter, s, err) \
1633 info_ctr.info.info ## lvl1->field1 = ""; \
1634 TESTGETCALL(GetPrinter, q) \
1635 info_ctr.info.info ## lvl1->field1 = value; \
1636 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1637 q.in.level = lvl2; \
1638 TESTGETCALL(GetPrinter, q) \
1639 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1640 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1641 } while (0)
1643 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1644 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1645 } while (0);
1647 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1648 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1649 q.in.level = lvl1; \
1650 TESTGETCALL(GetPrinter, q) \
1651 info_ctr.level = lvl1; \
1652 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1653 info_ctr.info.info ## lvl1->field1 = value; \
1654 TESTSETCALL(SetPrinter, s) \
1655 info_ctr.info.info ## lvl1->field1 = 0; \
1656 TESTGETCALL(GetPrinter, q) \
1657 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1658 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1659 q.in.level = lvl2; \
1660 TESTGETCALL(GetPrinter, q) \
1661 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1662 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1663 } while (0)
1665 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1666 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1667 } while (0)
1669 q0.in.level = 0;
1670 do { TESTGETCALL(GetPrinter, q0) } while (0);
1672 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1673 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1675 /* level 0 printername does not stick */
1676 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1677 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1678 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1679 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1680 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1681 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1682 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1683 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1684 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1685 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1686 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1687 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1688 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1689 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1690 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1692 /* servername can be set but does not stick
1693 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1694 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1695 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1698 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1699 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1700 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1701 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1702 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1704 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1705 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1706 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1707 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1708 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1709 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1710 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1711 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1712 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1713 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1715 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1716 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1717 attribute_list[i],
1718 (attribute_list[i] | default_attribute)
1719 ); */
1720 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1721 attribute_list[i],
1722 (attribute_list[i] | default_attribute)
1724 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1725 attribute_list[i],
1726 (attribute_list[i] | default_attribute)
1728 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1729 attribute_list[i],
1730 (attribute_list[i] | default_attribute)
1732 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1733 attribute_list[i],
1734 (attribute_list[i] | default_attribute)
1735 ); */
1736 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1737 attribute_list[i],
1738 (attribute_list[i] | default_attribute)
1740 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1741 attribute_list[i],
1742 (attribute_list[i] | default_attribute)
1744 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1745 attribute_list[i],
1746 (attribute_list[i] | default_attribute)
1748 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1749 attribute_list[i],
1750 (attribute_list[i] | default_attribute)
1751 ); */
1752 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1753 attribute_list[i],
1754 (attribute_list[i] | default_attribute)
1756 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1757 attribute_list[i],
1758 (attribute_list[i] | default_attribute)
1760 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1761 attribute_list[i],
1762 (attribute_list[i] | default_attribute)
1766 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1767 /* level 2 sets do not stick
1768 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1769 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1770 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1771 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1772 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1773 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1776 /* priorities need to be between 0 and 99
1777 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1778 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1779 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1780 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1781 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1782 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1783 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1784 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1785 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1787 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1788 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1790 /* does not stick
1791 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1792 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1794 /* does not stick
1795 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1796 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1798 /* FIXME: gd also test devmode and secdesc behavior */
1801 /* verify composition of level 1 description field */
1802 const char *description;
1803 const char *tmp;
1805 q0.in.level = 1;
1806 do { TESTGETCALL(GetPrinter, q0) } while (0);
1808 description = talloc_strdup(tctx, q0.out.info->info1.description);
1810 q0.in.level = 2;
1811 do { TESTGETCALL(GetPrinter, q0) } while (0);
1813 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1814 q0.out.info->info2.printername,
1815 q0.out.info->info2.drivername,
1816 q0.out.info->info2.location);
1818 do { STRING_EQUAL(description, tmp, "description")} while (0);
1821 return ret;
1824 static bool test_security_descriptor_equal(struct torture_context *tctx,
1825 const struct security_descriptor *sd1,
1826 const struct security_descriptor *sd2)
1828 if (sd1 == sd2) {
1829 return true;
1832 if (!sd1 || !sd2) {
1833 torture_comment(tctx, "%s\n", __location__);
1834 return false;
1837 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1838 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1840 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1841 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1843 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1844 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1845 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1846 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1847 return false;
1849 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1850 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1851 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1852 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1853 return false;
1856 return true;
1859 static bool test_sd_set_level(struct torture_context *tctx,
1860 struct dcerpc_binding_handle *b,
1861 struct policy_handle *handle,
1862 uint32_t level,
1863 struct security_descriptor *sd)
1865 struct spoolss_SetPrinterInfoCtr info_ctr;
1866 struct spoolss_DevmodeContainer devmode_ctr;
1867 struct sec_desc_buf secdesc_ctr;
1868 union spoolss_SetPrinterInfo sinfo;
1870 ZERO_STRUCT(devmode_ctr);
1871 ZERO_STRUCT(secdesc_ctr);
1873 switch (level) {
1874 case 2: {
1875 union spoolss_PrinterInfo info;
1876 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1877 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1879 info_ctr.level = 2;
1880 info_ctr.info = sinfo;
1882 break;
1884 case 3: {
1885 struct spoolss_SetPrinterInfo3 info3;
1887 info3.sec_desc_ptr = NULL;
1889 info_ctr.level = 3;
1890 info_ctr.info.info3 = &info3;
1892 break;
1894 default:
1895 return false;
1898 secdesc_ctr.sd = sd;
1900 torture_assert(tctx,
1901 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1903 return true;
1906 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1907 struct dcerpc_binding_handle *b,
1908 struct policy_handle *handle)
1910 union spoolss_PrinterInfo info;
1911 struct security_descriptor *sd1, *sd2;
1912 int i;
1914 /* just compare level 2 and level 3 */
1916 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1918 sd1 = info.info2.secdesc;
1920 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1922 sd2 = info.info3.secdesc;
1924 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1925 "SD level 2 != SD level 3");
1928 /* query level 2, set level 2, query level 2 */
1930 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1932 sd1 = info.info2.secdesc;
1934 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1936 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1938 sd2 = info.info2.secdesc;
1939 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1940 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1941 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1944 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1945 "SD level 2 != SD level 2 after SD has been set via level 2");
1948 /* query level 2, set level 3, query level 2 */
1950 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1952 sd1 = info.info2.secdesc;
1954 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1956 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1958 sd2 = info.info2.secdesc;
1960 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1961 "SD level 2 != SD level 2 after SD has been set via level 3");
1963 /* set modified sd level 3, query level 2 */
1965 for (i=0; i < 93; i++) {
1966 struct security_ace a;
1967 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1968 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1969 a.flags = 0;
1970 a.size = 0; /* autogenerated */
1971 a.access_mask = 0;
1972 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1973 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1976 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1978 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1979 sd2 = info.info2.secdesc;
1981 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1982 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1983 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1986 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1987 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1990 return true;
1994 * wrapper call that saves original sd, runs tests, and restores sd
1997 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1998 struct dcerpc_binding_handle *b,
1999 struct policy_handle *handle)
2001 union spoolss_PrinterInfo info;
2002 struct security_descriptor *sd;
2003 bool ret = true;
2005 torture_comment(tctx, "Testing Printer Security Descriptors\n");
2007 /* save original sd */
2009 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
2010 "failed to get initial security descriptor");
2012 sd = security_descriptor_copy(tctx, info.info2.secdesc);
2014 /* run tests */
2016 ret = test_PrinterInfo_SDs(tctx, b, handle);
2018 /* restore original sd */
2020 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
2021 "failed to restore initial security descriptor");
2023 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
2024 ret ? "succeeded" : "failed");
2027 return ret;
2030 static bool test_devmode_set_level(struct torture_context *tctx,
2031 struct dcerpc_binding_handle *b,
2032 struct policy_handle *handle,
2033 uint32_t level,
2034 struct spoolss_DeviceMode *devmode)
2036 struct spoolss_SetPrinterInfoCtr info_ctr;
2037 struct spoolss_DevmodeContainer devmode_ctr;
2038 struct sec_desc_buf secdesc_ctr;
2039 union spoolss_SetPrinterInfo sinfo;
2041 ZERO_STRUCT(devmode_ctr);
2042 ZERO_STRUCT(secdesc_ctr);
2044 switch (level) {
2045 case 2: {
2046 union spoolss_PrinterInfo info;
2047 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2048 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
2050 info_ctr.level = 2;
2051 info_ctr.info = sinfo;
2053 break;
2055 case 8: {
2056 struct spoolss_SetPrinterInfo8 info8;
2058 info8.devmode_ptr = NULL;
2060 info_ctr.level = 8;
2061 info_ctr.info.info8 = &info8;
2063 break;
2065 default:
2066 return false;
2069 devmode_ctr.devmode = devmode;
2071 torture_assert(tctx,
2072 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
2074 return true;
2078 static bool test_devicemode_equal(struct torture_context *tctx,
2079 const struct spoolss_DeviceMode *d1,
2080 const struct spoolss_DeviceMode *d2)
2082 if (d1 == d2) {
2083 return true;
2086 if (!d1 || !d2) {
2087 torture_comment(tctx, "%s\n", __location__);
2088 return false;
2090 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
2091 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
2092 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
2093 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
2094 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
2095 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
2096 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
2097 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
2098 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
2099 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
2100 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
2101 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
2102 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
2103 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2104 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2105 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2106 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2107 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2108 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2109 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2110 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2111 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2112 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2113 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2114 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2115 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2116 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2117 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2118 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2119 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2120 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2121 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2122 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2123 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2124 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2126 return true;
2129 static bool test_devicemode_full(struct torture_context *tctx,
2130 struct dcerpc_binding_handle *b,
2131 struct policy_handle *handle)
2133 struct spoolss_SetPrinter s;
2134 struct spoolss_GetPrinter q;
2135 struct spoolss_GetPrinter q0;
2136 struct spoolss_SetPrinterInfoCtr info_ctr;
2137 struct spoolss_SetPrinterInfo8 info8;
2138 union spoolss_PrinterInfo info;
2139 struct spoolss_DevmodeContainer devmode_ctr;
2140 struct sec_desc_buf secdesc_ctr;
2141 uint32_t needed;
2142 bool ret = true;
2143 NTSTATUS status;
2145 #define TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, exp_value, expected_result) do { \
2146 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2147 q.in.level = lvl1; \
2148 TESTGETCALL(GetPrinter, q) \
2149 info_ctr.level = lvl1; \
2150 if (lvl1 == 2) {\
2151 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
2152 } else if (lvl1 == 8) {\
2153 info_ctr.info.info ## lvl1 = &info8; \
2155 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2156 devmode_ctr.devmode->field1 = value; \
2157 TESTSETCALL_EXP(SetPrinter, s, expected_result) \
2158 if (W_ERROR_IS_OK(expected_result)) { \
2159 TESTGETCALL(GetPrinter, q) \
2160 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2161 q.in.level = lvl2; \
2162 TESTGETCALL(GetPrinter, q) \
2163 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2165 } while (0)
2167 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, expected_result) do { \
2168 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, expected_result); \
2169 } while (0)
2171 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2172 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, WERR_OK); \
2173 } while (0)
2175 ZERO_STRUCT(devmode_ctr);
2176 ZERO_STRUCT(secdesc_ctr);
2177 ZERO_STRUCT(info8);
2179 s.in.handle = handle;
2180 s.in.command = 0;
2181 s.in.info_ctr = &info_ctr;
2182 s.in.devmode_ctr = &devmode_ctr;
2183 s.in.secdesc_ctr = &secdesc_ctr;
2185 q.in.handle = handle;
2186 q.out.info = &info;
2187 q0 = q;
2189 #if 0
2190 const char *devicename;/* [charset(UTF16)] */
2191 enum spoolss_DeviceModeSpecVersion specversion;
2192 uint16_t driverversion;
2193 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2194 uint32_t fields;
2195 #endif
2196 TEST_DEVMODE_INT_EXP(8, size, 8, size, __LINE__, WERR_INVALID_PARAM);
2197 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0, WERR_INVALID_PARAM);
2198 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0xffff, WERR_INVALID_PARAM);
2199 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);
2200 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2202 devmode_ctr.devmode->driverextra_data = data_blob_string_const("foobar");
2203 torture_assert(tctx,
2204 test_devmode_set_level(tctx, b, handle, 8, devmode_ctr.devmode),
2205 "failed to set devmode");
2207 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);
2208 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2210 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
2211 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
2212 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
2213 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
2214 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
2215 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
2216 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
2217 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
2218 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
2219 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
2220 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
2221 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
2222 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
2223 #if 0
2224 const char *formname;/* [charset(UTF16)] */
2225 #endif
2226 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
2227 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
2228 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
2229 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
2230 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
2231 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
2232 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
2233 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
2234 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
2235 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
2236 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
2237 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
2238 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
2239 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
2241 return ret;
2244 static bool call_OpenPrinterEx(struct torture_context *tctx,
2245 struct dcerpc_pipe *p,
2246 const char *name,
2247 struct spoolss_DeviceMode *devmode,
2248 struct policy_handle *handle);
2250 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2251 struct dcerpc_pipe *p,
2252 struct policy_handle *handle,
2253 const char *name)
2255 union spoolss_PrinterInfo info;
2256 struct spoolss_DeviceMode *devmode;
2257 struct spoolss_DeviceMode *devmode2;
2258 struct policy_handle handle_devmode;
2259 struct dcerpc_binding_handle *b = p->binding_handle;
2261 /* simply compare level8 and level2 devmode */
2263 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2265 devmode = info.info8.devmode;
2267 if (devmode && devmode->size == 0) {
2268 torture_fail(tctx,
2269 "devmode of zero size!");
2272 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2274 devmode2 = info.info2.devmode;
2276 if (devmode2 && devmode2->size == 0) {
2277 torture_fail(tctx,
2278 "devmode of zero size!");
2281 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2282 "DM level 8 != DM level 2");
2285 /* set devicemode level 8 and see if it persists */
2287 devmode->copies = 93;
2288 devmode->formname = talloc_strdup(tctx, "Legal");
2290 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2292 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2294 devmode2 = info.info8.devmode;
2296 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2297 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2299 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2301 devmode2 = info.info2.devmode;
2303 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2304 "modified DM level 8 != DM level 2");
2307 /* set devicemode level 2 and see if it persists */
2309 devmode->copies = 39;
2310 devmode->formname = talloc_strdup(tctx, "Executive");
2312 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2314 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2316 devmode2 = info.info8.devmode;
2318 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2319 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2321 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2323 devmode2 = info.info2.devmode;
2325 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2326 "modified DM level 8 != DM level 2");
2329 /* check every single bit in public part of devicemode */
2331 torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2332 "failed to set every single devicemode component");
2335 /* change formname upon open and see if it persists in getprinter calls */
2337 devmode->formname = talloc_strdup(tctx, "A4");
2338 devmode->copies = 42;
2340 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2341 "failed to open printer handle");
2343 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2345 devmode2 = info.info8.devmode;
2347 if (strequal(devmode->devicename, devmode2->devicename)) {
2348 torture_warning(tctx, "devicenames are the same\n");
2349 } else {
2350 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2351 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2354 if (strequal(devmode->formname, devmode2->formname)) {
2355 torture_warning(tctx, "formname are the same\n");
2356 } else {
2357 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2358 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2361 if (devmode->copies == devmode2->copies) {
2362 torture_warning(tctx, "copies are the same\n");
2363 } else {
2364 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2365 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2368 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2370 devmode2 = info.info2.devmode;
2372 if (strequal(devmode->devicename, devmode2->devicename)) {
2373 torture_warning(tctx, "devicenames are the same\n");
2374 } else {
2375 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2376 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2379 if (strequal(devmode->formname, devmode2->formname)) {
2380 torture_warning(tctx, "formname is the same\n");
2381 } else {
2382 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2383 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2386 if (devmode->copies == devmode2->copies) {
2387 torture_warning(tctx, "copies are the same\n");
2388 } else {
2389 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2390 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2393 test_ClosePrinter(tctx, b, &handle_devmode);
2395 return true;
2399 * wrapper call that saves original devmode, runs tests, and restores devmode
2402 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2403 struct dcerpc_pipe *p,
2404 struct policy_handle *handle,
2405 const char *name,
2406 struct spoolss_DeviceMode *addprinter_devmode)
2408 union spoolss_PrinterInfo info;
2409 struct spoolss_DeviceMode *devmode;
2410 bool ret = true;
2411 struct dcerpc_binding_handle *b = p->binding_handle;
2413 torture_comment(tctx, "Testing Printer Devicemodes\n");
2415 /* save original devmode */
2417 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2418 "failed to get initial global devicemode");
2420 devmode = info.info8.devmode;
2422 if (devmode && devmode->size == 0) {
2423 torture_fail(tctx,
2424 "devmode of zero size!");
2427 if (addprinter_devmode) {
2428 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
2429 torture_warning(tctx, "current global DM is != DM provided in addprinter");
2433 /* run tests */
2435 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2437 /* restore original devmode */
2439 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2440 "failed to restore initial global device mode");
2442 torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2443 ret ? "succeeded" : "failed");
2446 return ret;
2449 bool test_ClosePrinter(struct torture_context *tctx,
2450 struct dcerpc_binding_handle *b,
2451 struct policy_handle *handle)
2453 NTSTATUS status;
2454 struct spoolss_ClosePrinter r;
2456 r.in.handle = handle;
2457 r.out.handle = handle;
2459 torture_comment(tctx, "Testing ClosePrinter\n");
2461 status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2462 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2463 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2465 return true;
2468 static bool test_GetForm_args(struct torture_context *tctx,
2469 struct dcerpc_binding_handle *b,
2470 struct policy_handle *handle,
2471 const char *form_name,
2472 uint32_t level,
2473 union spoolss_FormInfo *info_p)
2475 NTSTATUS status;
2476 struct spoolss_GetForm r;
2477 uint32_t needed;
2479 r.in.handle = handle;
2480 r.in.form_name = form_name;
2481 r.in.level = level;
2482 r.in.buffer = NULL;
2483 r.in.offered = 0;
2484 r.out.needed = &needed;
2486 torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2488 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2489 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2491 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2492 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2493 r.in.buffer = &blob;
2494 r.in.offered = needed;
2495 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2496 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2498 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2500 torture_assert(tctx, r.out.info, "No form info returned");
2503 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2505 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
2507 if (info_p) {
2508 *info_p = *r.out.info;
2511 return true;
2514 static bool test_GetForm(struct torture_context *tctx,
2515 struct dcerpc_binding_handle *b,
2516 struct policy_handle *handle,
2517 const char *form_name,
2518 uint32_t level)
2520 return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2523 static bool test_EnumForms(struct torture_context *tctx,
2524 struct dcerpc_binding_handle *b,
2525 struct policy_handle *handle,
2526 bool print_server,
2527 uint32_t level,
2528 uint32_t *count_p,
2529 union spoolss_FormInfo **info_p)
2531 struct spoolss_EnumForms r;
2532 uint32_t needed;
2533 uint32_t count;
2534 union spoolss_FormInfo *info;
2536 r.in.handle = handle;
2537 r.in.level = level;
2538 r.in.buffer = NULL;
2539 r.in.offered = 0;
2540 r.out.needed = &needed;
2541 r.out.count = &count;
2542 r.out.info = &info;
2544 torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2546 torture_assert_ntstatus_ok(tctx,
2547 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2548 "EnumForms failed");
2550 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2551 torture_skip(tctx, "EnumForms level 2 not supported");
2554 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2555 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2558 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2559 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2560 r.in.buffer = &blob;
2561 r.in.offered = needed;
2563 torture_assert_ntstatus_ok(tctx,
2564 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2565 "EnumForms failed");
2567 torture_assert(tctx, info, "No forms returned");
2570 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2572 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
2574 if (info_p) {
2575 *info_p = info;
2577 if (count_p) {
2578 *count_p = count;
2581 return true;
2584 static bool test_EnumForms_all(struct torture_context *tctx,
2585 struct dcerpc_binding_handle *b,
2586 struct policy_handle *handle,
2587 bool print_server)
2589 uint32_t levels[] = { 1, 2 };
2590 int i, j;
2592 for (i=0; i<ARRAY_SIZE(levels); i++) {
2594 uint32_t count = 0;
2595 union spoolss_FormInfo *info = NULL;
2597 torture_assert(tctx,
2598 test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2599 "failed to enum forms");
2601 for (j = 0; j < count; j++) {
2602 if (!print_server) {
2603 torture_assert(tctx,
2604 test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2605 "failed to get form");
2610 return true;
2613 static bool test_EnumForms_find_one(struct torture_context *tctx,
2614 struct dcerpc_binding_handle *b,
2615 struct policy_handle *handle,
2616 bool print_server,
2617 const char *form_name)
2619 union spoolss_FormInfo *info;
2620 uint32_t count;
2621 bool found = false;
2622 int i;
2624 torture_assert(tctx,
2625 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2626 "failed to enumerate forms");
2628 for (i=0; i<count; i++) {
2629 if (strequal(form_name, info[i].info1.form_name)) {
2630 found = true;
2631 break;
2635 return found;
2638 static bool test_DeleteForm(struct torture_context *tctx,
2639 struct dcerpc_binding_handle *b,
2640 struct policy_handle *handle,
2641 const char *form_name,
2642 WERROR expected_result)
2644 struct spoolss_DeleteForm r;
2646 r.in.handle = handle;
2647 r.in.form_name = form_name;
2649 torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2651 torture_assert_ntstatus_ok(tctx,
2652 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2653 "DeleteForm failed");
2654 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2655 "DeleteForm gave unexpected result");
2656 if (W_ERROR_IS_OK(r.out.result)) {
2657 torture_assert_ntstatus_ok(tctx,
2658 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2659 "2nd DeleteForm failed");
2660 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2661 "2nd DeleteForm failed");
2664 return true;
2667 static bool test_AddForm(struct torture_context *tctx,
2668 struct dcerpc_binding_handle *b,
2669 struct policy_handle *handle,
2670 uint32_t level,
2671 union spoolss_AddFormInfo *info,
2672 WERROR expected_result)
2674 struct spoolss_AddForm r;
2675 struct spoolss_AddFormInfoCtr info_ctr;
2677 info_ctr.level = level;
2678 info_ctr.info = *info;
2680 if (level != 1) {
2681 torture_skip(tctx, "only level 1 supported");
2684 r.in.handle = handle;
2685 r.in.info_ctr = &info_ctr;
2687 torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2688 r.in.info_ctr->info.info1->form_name, level,
2689 r.in.info_ctr->info.info1->flags);
2691 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2692 "AddForm failed");
2693 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2694 "AddForm gave unexpected result");
2696 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2697 "2nd AddForm failed");
2698 if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2699 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2700 "2nd AddForm gave unexpected result");
2701 } else {
2702 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2703 "2nd AddForm gave unexpected result");
2706 return true;
2709 static bool test_SetForm(struct torture_context *tctx,
2710 struct dcerpc_binding_handle *b,
2711 struct policy_handle *handle,
2712 const char *form_name,
2713 uint32_t level,
2714 union spoolss_AddFormInfo *info)
2716 struct spoolss_SetForm r;
2717 struct spoolss_AddFormInfoCtr info_ctr;
2719 info_ctr.level = level;
2720 info_ctr.info = *info;
2722 r.in.handle = handle;
2723 r.in.form_name = form_name;
2724 r.in.info_ctr = &info_ctr;
2726 torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2727 form_name, level);
2729 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2730 "SetForm failed");
2732 torture_assert_werr_ok(tctx, r.out.result,
2733 "SetForm failed");
2735 return true;
2738 static bool test_GetForm_winreg(struct torture_context *tctx,
2739 struct dcerpc_binding_handle *b,
2740 struct policy_handle *handle,
2741 const char *key_name,
2742 const char *form_name,
2743 enum winreg_Type *w_type,
2744 uint32_t *w_size,
2745 uint32_t *w_length,
2746 uint8_t **w_data);
2748 static bool test_Forms_args(struct torture_context *tctx,
2749 struct dcerpc_binding_handle *b,
2750 struct policy_handle *handle,
2751 bool print_server,
2752 const char *printer_name,
2753 struct dcerpc_binding_handle *winreg_handle,
2754 struct policy_handle *hive_handle,
2755 const char *form_name,
2756 struct spoolss_AddFormInfo1 *info1,
2757 WERROR expected_add_result,
2758 WERROR expected_delete_result)
2760 union spoolss_FormInfo info;
2761 union spoolss_AddFormInfo add_info;
2763 enum winreg_Type w_type;
2764 uint32_t w_size;
2765 uint32_t w_length;
2766 uint8_t *w_data;
2768 add_info.info1 = info1;
2770 torture_assert(tctx,
2771 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2772 "failed to add form");
2774 if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2776 struct spoolss_FormInfo1 i1;
2778 torture_assert(tctx,
2779 test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2780 "failed to get form via winreg");
2782 i1.size.width = IVAL(w_data, 0);
2783 i1.size.height = IVAL(w_data, 4);
2784 i1.area.left = IVAL(w_data, 8);
2785 i1.area.top = IVAL(w_data, 12);
2786 i1.area.right = IVAL(w_data, 16);
2787 i1.area.bottom = IVAL(w_data, 20);
2788 /* skip index here */
2789 i1.flags = IVAL(w_data, 28);
2791 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2792 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2793 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2794 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
2795 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
2796 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
2797 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
2798 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
2799 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2800 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
2803 if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2804 torture_assert(tctx,
2805 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2806 "failed to get added form");
2808 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2809 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2810 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2811 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2812 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2813 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2814 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2816 if (winreg_handle && hive_handle) {
2818 struct spoolss_FormInfo1 i1;
2820 i1.size.width = IVAL(w_data, 0);
2821 i1.size.height = IVAL(w_data, 4);
2822 i1.area.left = IVAL(w_data, 8);
2823 i1.area.top = IVAL(w_data, 12);
2824 i1.area.right = IVAL(w_data, 16);
2825 i1.area.bottom = IVAL(w_data, 20);
2826 /* skip index here */
2827 i1.flags = IVAL(w_data, 28);
2829 torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
2830 torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
2831 torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
2832 torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
2833 torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
2834 torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
2835 torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
2838 add_info.info1->size.width = 1234;
2840 torture_assert(tctx,
2841 test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2842 "failed to set form");
2843 torture_assert(tctx,
2844 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2845 "failed to get setted form");
2847 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2850 if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2851 torture_assert(tctx,
2852 test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2853 "Newly added form not found in enum call");
2856 torture_assert(tctx,
2857 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2858 "failed to delete form");
2860 return true;
2863 static bool test_Forms(struct torture_context *tctx,
2864 struct dcerpc_binding_handle *b,
2865 struct policy_handle *handle,
2866 bool print_server,
2867 const char *printer_name,
2868 struct dcerpc_binding_handle *winreg_handle,
2869 struct policy_handle *hive_handle)
2871 const struct spoolss_FormSize size = {
2872 .width = 50,
2873 .height = 25
2875 const struct spoolss_FormArea area = {
2876 .left = 5,
2877 .top = 10,
2878 .right = 45,
2879 .bottom = 15
2881 int i;
2883 struct {
2884 struct spoolss_AddFormInfo1 info1;
2885 WERROR expected_add_result;
2886 WERROR expected_delete_result;
2887 } forms[] = {
2889 .info1 = {
2890 .flags = SPOOLSS_FORM_USER,
2891 .form_name = "testform_user",
2892 .size = size,
2893 .area = area,
2895 .expected_add_result = WERR_OK,
2896 .expected_delete_result = WERR_OK
2899 weird, we can add a builtin form but we can never remove it
2900 again - gd
2903 .info1 = {
2904 .flags = SPOOLSS_FORM_BUILTIN,
2905 .form_name = "testform_builtin",
2906 .size = size,
2907 .area = area,
2909 .expected_add_result = WERR_OK,
2910 .expected_delete_result = WERR_INVALID_PARAM,
2914 .info1 = {
2915 .flags = SPOOLSS_FORM_PRINTER,
2916 .form_name = "testform_printer",
2917 .size = size,
2918 .area = area,
2920 .expected_add_result = WERR_OK,
2921 .expected_delete_result = WERR_OK
2924 .info1 = {
2925 .flags = SPOOLSS_FORM_USER,
2926 .form_name = "Letter",
2927 .size = size,
2928 .area = area,
2930 .expected_add_result = WERR_FILE_EXISTS,
2931 .expected_delete_result = WERR_INVALID_PARAM
2934 .info1 = {
2935 .flags = SPOOLSS_FORM_BUILTIN,
2936 .form_name = "Letter",
2937 .size = size,
2938 .area = area,
2940 .expected_add_result = WERR_FILE_EXISTS,
2941 .expected_delete_result = WERR_INVALID_PARAM
2944 .info1 = {
2945 .flags = SPOOLSS_FORM_PRINTER,
2946 .form_name = "Letter",
2947 .size = size,
2948 .area = area,
2950 .expected_add_result = WERR_FILE_EXISTS,
2951 .expected_delete_result = WERR_INVALID_PARAM
2954 .info1 = {
2955 .flags = 12345,
2956 .form_name = "invalid_flags",
2957 .size = size,
2958 .area = area,
2960 .expected_add_result = WERR_INVALID_PARAM,
2961 .expected_delete_result = WERR_INVALID_FORM_NAME
2966 for (i=0; i < ARRAY_SIZE(forms); i++) {
2967 torture_assert(tctx,
2968 test_Forms_args(tctx, b, handle, print_server, printer_name,
2969 winreg_handle, hive_handle,
2970 forms[i].info1.form_name,
2971 &forms[i].info1,
2972 forms[i].expected_add_result,
2973 forms[i].expected_delete_result),
2974 talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2977 return true;
2980 static bool test_EnumPorts_old(struct torture_context *tctx,
2981 void *private_data)
2983 struct test_spoolss_context *ctx =
2984 talloc_get_type_abort(private_data, struct test_spoolss_context);
2986 NTSTATUS status;
2987 struct spoolss_EnumPorts r;
2988 uint32_t needed;
2989 uint32_t count;
2990 union spoolss_PortInfo *info;
2991 struct dcerpc_pipe *p = ctx->spoolss_pipe;
2992 struct dcerpc_binding_handle *b = p->binding_handle;
2994 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2995 dcerpc_server_name(p));
2996 r.in.level = 2;
2997 r.in.buffer = NULL;
2998 r.in.offered = 0;
2999 r.out.needed = &needed;
3000 r.out.count = &count;
3001 r.out.info = &info;
3003 torture_comment(tctx, "Testing EnumPorts\n");
3005 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3007 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3009 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3010 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3011 r.in.buffer = &blob;
3012 r.in.offered = needed;
3014 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3015 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3016 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3018 torture_assert(tctx, info, "No ports returned");
3021 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3023 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
3025 return true;
3028 static bool test_AddPort(struct torture_context *tctx,
3029 void *private_data)
3031 struct test_spoolss_context *ctx =
3032 talloc_get_type_abort(private_data, struct test_spoolss_context);
3034 NTSTATUS status;
3035 struct spoolss_AddPort r;
3036 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3037 struct dcerpc_binding_handle *b = p->binding_handle;
3039 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
3040 dcerpc_server_name(p));
3041 r.in.unknown = 0;
3042 r.in.monitor_name = "foo";
3044 torture_comment(tctx, "Testing AddPort\n");
3046 status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
3048 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
3050 /* win2k3 returns WERR_NOT_SUPPORTED */
3052 #if 0
3054 if (!W_ERROR_IS_OK(r.out.result)) {
3055 printf("AddPort failed - %s\n", win_errstr(r.out.result));
3056 return false;
3059 #endif
3061 return true;
3064 static bool test_GetJob_args(struct torture_context *tctx,
3065 struct dcerpc_binding_handle *b,
3066 struct policy_handle *handle,
3067 uint32_t job_id,
3068 uint32_t level,
3069 union spoolss_JobInfo *info_p)
3071 NTSTATUS status;
3072 struct spoolss_GetJob r;
3073 union spoolss_JobInfo info;
3074 uint32_t needed;
3076 r.in.handle = handle;
3077 r.in.job_id = job_id;
3078 r.in.level = level;
3079 r.in.buffer = NULL;
3080 r.in.offered = 0;
3081 r.out.needed = &needed;
3082 r.out.info = &info;
3084 torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
3086 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3087 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3088 if (level == 0) {
3089 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
3092 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3093 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3094 r.in.buffer = &blob;
3095 r.in.offered = needed;
3097 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3098 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3101 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
3102 torture_assert(tctx, r.out.info, "No job info returned");
3104 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
3106 if (info_p) {
3107 *info_p = *r.out.info;
3110 return true;
3113 static bool test_GetJob(struct torture_context *tctx,
3114 struct dcerpc_binding_handle *b,
3115 struct policy_handle *handle,
3116 uint32_t job_id)
3118 uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
3119 uint32_t i;
3121 for (i=0; i < ARRAY_SIZE(levels); i++) {
3122 torture_assert(tctx,
3123 test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
3124 "GetJob failed");
3127 return true;
3130 static bool test_SetJob(struct torture_context *tctx,
3131 struct dcerpc_binding_handle *b,
3132 struct policy_handle *handle,
3133 uint32_t job_id,
3134 struct spoolss_JobInfoContainer *ctr,
3135 enum spoolss_JobControl command)
3137 NTSTATUS status;
3138 struct spoolss_SetJob r;
3140 r.in.handle = handle;
3141 r.in.job_id = job_id;
3142 r.in.ctr = ctr;
3143 r.in.command = command;
3145 switch (command) {
3146 case SPOOLSS_JOB_CONTROL_PAUSE:
3147 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3148 break;
3149 case SPOOLSS_JOB_CONTROL_RESUME:
3150 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3151 break;
3152 case SPOOLSS_JOB_CONTROL_CANCEL:
3153 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3154 break;
3155 case SPOOLSS_JOB_CONTROL_RESTART:
3156 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3157 break;
3158 case SPOOLSS_JOB_CONTROL_DELETE:
3159 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3160 break;
3161 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3162 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3163 break;
3164 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3165 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3166 break;
3167 case SPOOLSS_JOB_CONTROL_RETAIN:
3168 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3169 break;
3170 case SPOOLSS_JOB_CONTROL_RELEASE:
3171 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3172 break;
3173 default:
3174 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3175 break;
3178 status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3179 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3180 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3182 return true;
3185 static bool test_AddJob(struct torture_context *tctx,
3186 struct dcerpc_binding_handle *b,
3187 struct policy_handle *handle)
3189 NTSTATUS status;
3190 struct spoolss_AddJob r;
3191 uint32_t needed;
3193 r.in.level = 0;
3194 r.in.handle = handle;
3195 r.in.offered = 0;
3196 r.out.needed = &needed;
3197 r.in.buffer = r.out.buffer = NULL;
3199 torture_comment(tctx, "Testing AddJob\n");
3201 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3202 torture_assert_ntstatus_ok(tctx, status, "AddJob failed");
3203 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3205 r.in.level = 1;
3207 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3208 torture_assert_ntstatus_ok(tctx, status, "AddJob failed");
3209 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3211 return true;
3215 static bool test_EnumJobs_args(struct torture_context *tctx,
3216 struct dcerpc_binding_handle *b,
3217 struct policy_handle *handle,
3218 uint32_t level,
3219 uint32_t *count_p,
3220 union spoolss_JobInfo **info_p)
3222 NTSTATUS status;
3223 struct spoolss_EnumJobs r;
3224 uint32_t needed;
3225 uint32_t count;
3226 union spoolss_JobInfo *info;
3228 r.in.handle = handle;
3229 r.in.firstjob = 0;
3230 r.in.numjobs = 0xffffffff;
3231 r.in.level = level;
3232 r.in.buffer = NULL;
3233 r.in.offered = 0;
3234 r.out.needed = &needed;
3235 r.out.count = &count;
3236 r.out.info = &info;
3238 torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3240 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3242 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3244 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3245 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3246 r.in.buffer = &blob;
3247 r.in.offered = needed;
3249 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3251 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3252 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3253 torture_assert(tctx, info, "No jobs returned");
3255 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3257 } else {
3258 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3261 if (count_p) {
3262 *count_p = count;
3264 if (info_p) {
3265 *info_p = info;
3268 return true;
3271 static bool test_JobPropertiesEnum(struct torture_context *tctx,
3272 struct dcerpc_binding_handle *b,
3273 struct policy_handle *handle,
3274 uint32_t job_id)
3276 struct spoolss_RpcEnumJobNamedProperties r;
3277 uint32_t pcProperties = 0;
3278 struct RPC_PrintNamedProperty *ppProperties = NULL;
3280 r.in.hPrinter = handle;
3281 r.in.JobId = job_id;
3282 r.out.pcProperties = &pcProperties;
3283 r.out.ppProperties = &ppProperties;
3285 torture_comment(tctx, "Testing RpcEnumJobNamedProperties(%d)\n", job_id);
3287 torture_assert_ntstatus_ok(tctx,
3288 dcerpc_spoolss_RpcEnumJobNamedProperties_r(b, tctx, &r),
3289 "spoolss_RpcEnumJobNamedProperties failed");
3290 torture_assert_werr_ok(tctx, r.out.result,
3291 "spoolss_RpcEnumJobNamedProperties failed");
3293 return true;
3296 static bool test_JobPropertySet(struct torture_context *tctx,
3297 struct dcerpc_binding_handle *b,
3298 struct policy_handle *handle,
3299 uint32_t job_id,
3300 struct RPC_PrintNamedProperty *property)
3302 struct spoolss_RpcSetJobNamedProperty r;
3304 r.in.hPrinter = handle;
3305 r.in.JobId = job_id;
3306 r.in.pProperty = property;
3308 torture_comment(tctx, "Testing RpcSetJobNamedProperty(%d) %s - %d\n",
3309 job_id, property->propertyName,
3310 property->propertyValue.ePropertyType);
3312 torture_assert_ntstatus_ok(tctx,
3313 dcerpc_spoolss_RpcSetJobNamedProperty_r(b, tctx, &r),
3314 "spoolss_RpcSetJobNamedProperty failed");
3315 torture_assert_werr_ok(tctx, r.out.result,
3316 "spoolss_RpcSetJobNamedProperty failed");
3318 return true;
3321 static bool test_JobPropertyGetValue(struct torture_context *tctx,
3322 struct dcerpc_binding_handle *b,
3323 struct policy_handle *handle,
3324 uint32_t job_id,
3325 const char *property_name,
3326 struct RPC_PrintPropertyValue *value)
3328 struct spoolss_RpcGetJobNamedPropertyValue r;
3330 r.in.hPrinter = handle;
3331 r.in.JobId = job_id;
3332 r.in.pszName = property_name;
3333 r.out.pValue = value;
3335 torture_comment(tctx, "Testing RpcGetJobNamedPropertyValue(%d) %s\n",
3336 job_id, property_name);
3338 torture_assert_ntstatus_ok(tctx,
3339 dcerpc_spoolss_RpcGetJobNamedPropertyValue_r(b, tctx, &r),
3340 "spoolss_RpcGetJobNamedPropertyValue failed");
3341 torture_assert_werr_ok(tctx, r.out.result,
3342 "spoolss_RpcGetJobNamedPropertyValue failed");
3344 return true;
3347 static bool test_JobPropertyDelete(struct torture_context *tctx,
3348 struct dcerpc_binding_handle *b,
3349 struct policy_handle *handle,
3350 uint32_t job_id,
3351 const char *property_name)
3353 struct spoolss_RpcDeleteJobNamedProperty r;
3355 r.in.hPrinter = handle;
3356 r.in.JobId = job_id;
3357 r.in.pszName = property_name;
3359 torture_comment(tctx, "Testing RpcDeleteJobNamedProperty(%d) %s\n",
3360 job_id, property_name);
3362 torture_assert_ntstatus_ok(tctx,
3363 dcerpc_spoolss_RpcDeleteJobNamedProperty_r(b, tctx, &r),
3364 "spoolss_RpcDeleteJobNamedProperty failed");
3365 torture_assert_werr_ok(tctx, r.out.result,
3366 "spoolss_RpcDeleteJobNamedProperty failed");
3368 return true;
3372 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3373 struct dcerpc_binding_handle *b,
3374 struct policy_handle *handle,
3375 const char *document_name,
3376 uint32_t *job_id)
3378 NTSTATUS status;
3379 struct spoolss_StartDocPrinter s;
3380 struct spoolss_DocumentInfoCtr info_ctr;
3381 struct spoolss_DocumentInfo1 info1;
3382 struct spoolss_StartPagePrinter sp;
3383 struct spoolss_WritePrinter w;
3384 struct spoolss_EndPagePrinter ep;
3385 struct spoolss_EndDocPrinter e;
3386 int i;
3387 uint32_t num_written;
3389 torture_comment(tctx, "Testing StartDocPrinter\n");
3391 s.in.handle = handle;
3392 s.in.info_ctr = &info_ctr;
3393 s.out.job_id = job_id;
3395 info1.document_name = document_name;
3396 info1.output_file = NULL;
3397 info1.datatype = "RAW";
3399 info_ctr.level = 1;
3400 info_ctr.info.info1 = &info1;
3402 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3403 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3404 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3406 for (i=1; i < 4; i++) {
3407 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3409 sp.in.handle = handle;
3411 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3412 torture_assert_ntstatus_ok(tctx, status,
3413 "dcerpc_spoolss_StartPagePrinter failed");
3414 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3416 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3418 w.in.handle = handle;
3419 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3420 w.out.num_written = &num_written;
3422 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3423 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3424 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3426 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3428 ep.in.handle = handle;
3430 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3431 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3432 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3435 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3437 e.in.handle = handle;
3439 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3440 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3441 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3443 return true;
3446 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3447 struct dcerpc_binding_handle *b,
3448 struct policy_handle *handle,
3449 uint32_t num_jobs,
3450 uint32_t *job_ids)
3452 uint32_t count;
3453 union spoolss_JobInfo *info = NULL;
3454 int i;
3456 torture_assert(tctx,
3457 test_AddJob(tctx, b, handle),
3458 "AddJob failed");
3460 torture_assert(tctx,
3461 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3462 "EnumJobs level 1 failed");
3464 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3466 for (i=0; i < num_jobs; i++) {
3467 union spoolss_JobInfo ginfo;
3468 const char *document_name;
3469 const char *new_document_name = "any_other_docname";
3470 struct spoolss_JobInfoContainer ctr;
3471 struct spoolss_SetJobInfo1 info1;
3473 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3475 torture_assert(tctx,
3476 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3477 "failed to call test_GetJob");
3479 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3481 document_name = ginfo.info1.document_name;
3483 info1.job_id = ginfo.info1.job_id;
3484 info1.printer_name = ginfo.info1.printer_name;
3485 info1.server_name = ginfo.info1.server_name;
3486 info1.user_name = ginfo.info1.user_name;
3487 info1.document_name = new_document_name;
3488 info1.data_type = ginfo.info1.data_type;
3489 info1.text_status = ginfo.info1.text_status;
3490 info1.status = ginfo.info1.status;
3491 info1.priority = ginfo.info1.priority;
3492 info1.position = ginfo.info1.position;
3493 info1.total_pages = ginfo.info1.total_pages;
3494 info1.pages_printed = ginfo.info1.pages_printed;
3495 info1.submitted = ginfo.info1.submitted;
3497 ctr.level = 1;
3498 ctr.info.info1 = &info1;
3500 torture_assert(tctx,
3501 test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3502 "failed to call test_SetJob level 1");
3504 torture_assert(tctx,
3505 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3506 "failed to call test_GetJob");
3508 if (strequal(ginfo.info1.document_name, document_name)) {
3509 torture_warning(tctx,
3510 "document_name did *NOT* change from '%s' to '%s'\n",
3511 document_name, new_document_name);
3515 for (i=0; i < num_jobs; i++) {
3516 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3517 torture_warning(tctx, "failed to pause printjob\n");
3519 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3520 torture_warning(tctx, "failed to resume printjob\n");
3524 return true;
3527 static bool test_DoPrintTest(struct torture_context *tctx,
3528 struct dcerpc_binding_handle *b,
3529 struct policy_handle *handle)
3531 bool ret = true;
3532 uint32_t num_jobs = 8;
3533 uint32_t *job_ids;
3534 int i;
3536 torture_comment(tctx, "Testing real print operations\n");
3538 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3540 for (i=0; i < num_jobs; i++) {
3541 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3544 for (i=0; i < num_jobs; i++) {
3545 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3548 if (ret == true) {
3549 torture_comment(tctx, "real print operations test succeeded\n\n");
3552 return ret;
3555 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3556 struct dcerpc_binding_handle *b,
3557 struct policy_handle *handle)
3559 bool ret = true;
3560 uint32_t num_jobs = 8;
3561 uint32_t *job_ids;
3562 int i;
3563 torture_comment(tctx, "Testing real print operations (extended)\n");
3565 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3567 for (i=0; i < num_jobs; i++) {
3568 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3571 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3573 for (i=0; i < num_jobs; i++) {
3574 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3577 if (ret == true) {
3578 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3581 return ret;
3584 static bool test_JobPrintProperties_equal(struct torture_context *tctx,
3585 struct RPC_PrintPropertyValue *got,
3586 struct RPC_PrintNamedProperty *exp)
3588 torture_assert_int_equal(tctx,
3589 got->ePropertyType,
3590 exp->propertyValue.ePropertyType,
3591 "ePropertyType");
3593 switch (exp->propertyValue.ePropertyType) {
3594 case kRpcPropertyTypeString:
3595 torture_assert_str_equal(tctx,
3596 got->value.propertyString,
3597 exp->propertyValue.value.propertyString,
3598 "propertyString");
3599 break;
3600 case kRpcPropertyTypeInt32:
3601 torture_assert_int_equal(tctx,
3602 got->value.propertyInt32,
3603 exp->propertyValue.value.propertyInt32,
3604 "propertyInt32");
3605 break;
3606 case kRpcPropertyTypeInt64:
3607 torture_assert_u64_equal(tctx,
3608 got->value.propertyInt64,
3609 exp->propertyValue.value.propertyInt64,
3610 "propertyInt64");
3611 break;
3612 case kRpcPropertyTypeByte:
3613 torture_assert_int_equal(tctx,
3614 got->value.propertyByte,
3615 exp->propertyValue.value.propertyByte,
3616 "propertyByte");
3617 break;
3618 case kRpcPropertyTypeBuffer:
3619 torture_assert_int_equal(tctx,
3620 got->value.propertyBlob.cbBuf,
3621 exp->propertyValue.value.propertyBlob.cbBuf,
3622 "propertyBlob.cbBuf");
3623 torture_assert_mem_equal(tctx,
3624 got->value.propertyBlob.pBuf,
3625 exp->propertyValue.value.propertyBlob.pBuf,
3626 exp->propertyValue.value.propertyBlob.cbBuf,
3627 "propertyBlob.pBuf");
3629 break;
3633 return true;
3636 static bool test_JobPrintProperties(struct torture_context *tctx,
3637 struct dcerpc_binding_handle *b,
3638 struct policy_handle *handle,
3639 uint32_t job_id)
3641 struct RPC_PrintNamedProperty in;
3642 struct RPC_PrintPropertyValue out;
3643 int i;
3644 DATA_BLOB blob = data_blob_string_const("blob");
3645 struct {
3646 const char *property_name;
3647 enum RPC_EPrintPropertyType type;
3648 union RPC_PrintPropertyValueUnion value;
3649 WERROR expected_result;
3650 } tests[] = {
3652 .property_name = "torture_property_string",
3653 .type = kRpcPropertyTypeString,
3654 .value.propertyString = "torture_property_value_string",
3656 .property_name = "torture_property_int32",
3657 .type = kRpcPropertyTypeInt32,
3658 .value.propertyInt32 = 42,
3660 .property_name = "torture_property_int64",
3661 .type = kRpcPropertyTypeInt64,
3662 .value.propertyInt64 = 0xaffe,
3664 .property_name = "torture_property_byte",
3665 .type = kRpcPropertyTypeByte,
3666 .value.propertyByte = 0xab,
3668 .property_name = "torture_property_buffer",
3669 .type = kRpcPropertyTypeBuffer,
3670 .value.propertyBlob.cbBuf = blob.length,
3671 .value.propertyBlob.pBuf = blob.data,
3675 torture_assert(tctx,
3676 test_JobPropertiesEnum(tctx, b, handle, job_id),
3677 "failed to enum properties");
3679 for (i=0; i <ARRAY_SIZE(tests); i++) {
3681 in.propertyName = tests[i].property_name;
3682 in.propertyValue.ePropertyType = tests[i].type;
3683 in.propertyValue.value = tests[i].value;
3685 torture_assert(tctx,
3686 test_JobPropertySet(tctx, b, handle, job_id, &in),
3687 "failed to set property");
3689 torture_assert(tctx,
3690 test_JobPropertyGetValue(tctx, b, handle, job_id, in.propertyName, &out),
3691 "failed to get property");
3693 torture_assert(tctx,
3694 test_JobPrintProperties_equal(tctx, &out, &in),
3695 "property unequal");
3697 torture_assert(tctx,
3698 test_JobPropertiesEnum(tctx, b, handle, job_id),
3699 "failed to enum properties");
3701 torture_assert(tctx,
3702 test_JobPropertyDelete(tctx, b, handle, job_id, in.propertyName),
3703 "failed to delete job property");
3706 torture_assert(tctx,
3707 test_JobPropertiesEnum(tctx, b, handle, job_id),
3708 "failed to enum properties");
3710 return true;
3713 static bool test_DoPrintTest_properties(struct torture_context *tctx,
3714 struct dcerpc_binding_handle *b,
3715 struct policy_handle *handle)
3717 uint32_t num_jobs = 8;
3718 uint32_t *job_ids;
3719 int i;
3720 torture_comment(tctx, "Testing real print operations (properties)\n");
3722 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3724 for (i=0; i < num_jobs; i++) {
3725 torture_assert(tctx,
3726 test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]),
3727 "failed to create print job");
3730 for (i=0; i < num_jobs; i++) {
3731 torture_assert(tctx,
3732 test_JobPrintProperties(tctx, b, handle, job_ids[i]),
3733 "failed to test job properties");
3737 for (i=0; i < num_jobs; i++) {
3738 torture_assert(tctx,
3739 test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE),
3740 "failed to delete printjob");
3743 torture_comment(tctx, "real print operations (properties) test succeeded\n\n");
3745 return true;
3748 static bool test_PausePrinter(struct torture_context *tctx,
3749 struct dcerpc_binding_handle *b,
3750 struct policy_handle *handle)
3752 NTSTATUS status;
3753 struct spoolss_SetPrinter r;
3754 struct spoolss_SetPrinterInfoCtr info_ctr;
3755 struct spoolss_DevmodeContainer devmode_ctr;
3756 struct sec_desc_buf secdesc_ctr;
3758 info_ctr.level = 0;
3759 info_ctr.info.info0 = NULL;
3761 ZERO_STRUCT(devmode_ctr);
3762 ZERO_STRUCT(secdesc_ctr);
3764 r.in.handle = handle;
3765 r.in.info_ctr = &info_ctr;
3766 r.in.devmode_ctr = &devmode_ctr;
3767 r.in.secdesc_ctr = &secdesc_ctr;
3768 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3770 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3772 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3774 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3776 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3778 return true;
3781 static bool test_ResumePrinter(struct torture_context *tctx,
3782 struct dcerpc_binding_handle *b,
3783 struct policy_handle *handle)
3785 NTSTATUS status;
3786 struct spoolss_SetPrinter r;
3787 struct spoolss_SetPrinterInfoCtr info_ctr;
3788 struct spoolss_DevmodeContainer devmode_ctr;
3789 struct sec_desc_buf secdesc_ctr;
3791 info_ctr.level = 0;
3792 info_ctr.info.info0 = NULL;
3794 ZERO_STRUCT(devmode_ctr);
3795 ZERO_STRUCT(secdesc_ctr);
3797 r.in.handle = handle;
3798 r.in.info_ctr = &info_ctr;
3799 r.in.devmode_ctr = &devmode_ctr;
3800 r.in.secdesc_ctr = &secdesc_ctr;
3801 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3803 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3805 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3807 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3809 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3811 return true;
3814 static bool test_GetPrinterData_checktype(struct torture_context *tctx,
3815 struct dcerpc_binding_handle *b,
3816 struct policy_handle *handle,
3817 const char *value_name,
3818 enum winreg_Type *expected_type,
3819 enum winreg_Type *type_p,
3820 uint8_t **data_p,
3821 uint32_t *needed_p)
3823 NTSTATUS status;
3824 struct spoolss_GetPrinterData r;
3825 uint32_t needed;
3826 enum winreg_Type type;
3827 union spoolss_PrinterData data;
3829 r.in.handle = handle;
3830 r.in.value_name = value_name;
3831 r.in.offered = 0;
3832 r.out.needed = &needed;
3833 r.out.type = &type;
3834 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3836 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3838 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3839 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3841 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3842 if (expected_type) {
3843 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3845 r.in.offered = needed;
3846 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3847 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3848 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3851 torture_assert_werr_ok(tctx, r.out.result,
3852 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3854 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3856 if (type_p) {
3857 *type_p = type;
3860 if (data_p) {
3861 *data_p = r.out.data;
3864 if (needed_p) {
3865 *needed_p = needed;
3868 return true;
3871 static bool test_GetPrinterData(struct torture_context *tctx,
3872 struct dcerpc_binding_handle *b,
3873 struct policy_handle *handle,
3874 const char *value_name,
3875 enum winreg_Type *type_p,
3876 uint8_t **data_p,
3877 uint32_t *needed_p)
3879 return test_GetPrinterData_checktype(tctx, b, handle, value_name,
3880 NULL, type_p, data_p, needed_p);
3883 static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
3884 struct dcerpc_pipe *p,
3885 struct policy_handle *handle,
3886 const char *key_name,
3887 const char *value_name,
3888 enum winreg_Type *expected_type,
3889 enum winreg_Type *type_p,
3890 uint8_t **data_p,
3891 uint32_t *needed_p)
3893 NTSTATUS status;
3894 struct spoolss_GetPrinterDataEx r;
3895 enum winreg_Type type;
3896 uint32_t needed;
3897 union spoolss_PrinterData data;
3898 struct dcerpc_binding_handle *b = p->binding_handle;
3900 r.in.handle = handle;
3901 r.in.key_name = key_name;
3902 r.in.value_name = value_name;
3903 r.in.offered = 0;
3904 r.out.type = &type;
3905 r.out.needed = &needed;
3906 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3908 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3909 r.in.key_name, r.in.value_name);
3911 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3912 if (!NT_STATUS_IS_OK(status)) {
3913 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3914 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3916 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3919 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3920 if (expected_type) {
3921 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3923 r.in.offered = needed;
3924 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3925 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3926 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3929 torture_assert_werr_ok(tctx, r.out.result,
3930 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3932 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3934 if (type_p) {
3935 *type_p = type;
3938 if (data_p) {
3939 *data_p = r.out.data;
3942 if (needed_p) {
3943 *needed_p = needed;
3946 return true;
3949 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3950 struct dcerpc_pipe *p,
3951 struct policy_handle *handle,
3952 const char *key_name,
3953 const char *value_name,
3954 enum winreg_Type *type_p,
3955 uint8_t **data_p,
3956 uint32_t *needed_p)
3958 return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
3959 NULL, type_p, data_p, needed_p);
3962 static bool test_get_environment(struct torture_context *tctx,
3963 struct dcerpc_binding_handle *b,
3964 struct policy_handle *handle,
3965 const char **architecture)
3967 DATA_BLOB blob;
3968 enum winreg_Type type;
3969 uint8_t *data;
3970 uint32_t needed;
3972 torture_assert(tctx,
3973 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3974 "failed to get Architecture");
3976 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3978 blob = data_blob_const(data, needed);
3979 *architecture = reg_val_data_string(tctx, REG_SZ, blob);
3981 return true;
3984 static bool test_GetPrinterData_list(struct torture_context *tctx,
3985 void *private_data)
3987 struct test_spoolss_context *ctx =
3988 talloc_get_type_abort(private_data, struct test_spoolss_context);
3989 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3990 struct dcerpc_binding_handle *b = p->binding_handle;
3991 const char *list[] = {
3992 "W3SvcInstalled",
3993 "BeepEnabled",
3994 "EventLog",
3995 /* "NetPopup", not on w2k8 */
3996 /* "NetPopupToComputer", not on w2k8 */
3997 "MajorVersion",
3998 "MinorVersion",
3999 "DefaultSpoolDirectory",
4000 "Architecture",
4001 "DsPresent",
4002 "OSVersion",
4003 /* "OSVersionEx", not on s3 */
4004 "DNSMachineName"
4006 int i;
4008 for (i=0; i < ARRAY_SIZE(list); i++) {
4009 enum winreg_Type type, type_ex;
4010 uint8_t *data, *data_ex;
4011 uint32_t needed, needed_ex;
4013 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
4014 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
4015 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
4016 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
4017 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
4018 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
4019 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
4022 return true;
4025 static bool test_EnumPrinterData(struct torture_context *tctx,
4026 struct dcerpc_pipe *p,
4027 struct policy_handle *handle,
4028 uint32_t enum_index,
4029 uint32_t value_offered,
4030 uint32_t data_offered,
4031 enum winreg_Type *type_p,
4032 uint32_t *value_needed_p,
4033 uint32_t *data_needed_p,
4034 const char **value_name_p,
4035 uint8_t **data_p,
4036 WERROR *result_p)
4038 struct spoolss_EnumPrinterData r;
4039 uint32_t data_needed;
4040 uint32_t value_needed;
4041 enum winreg_Type type;
4042 struct dcerpc_binding_handle *b = p->binding_handle;
4044 r.in.handle = handle;
4045 r.in.enum_index = enum_index;
4046 r.in.value_offered = value_offered;
4047 r.in.data_offered = data_offered;
4048 r.out.data_needed = &data_needed;
4049 r.out.value_needed = &value_needed;
4050 r.out.type = &type;
4051 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
4052 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
4054 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
4056 torture_assert_ntstatus_ok(tctx,
4057 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
4058 "EnumPrinterData failed");
4060 if (type_p) {
4061 *type_p = type;
4063 if (value_needed_p) {
4064 *value_needed_p = value_needed;
4066 if (data_needed_p) {
4067 *data_needed_p = data_needed;
4069 if (value_name_p) {
4070 *value_name_p = r.out.value_name;
4072 if (data_p) {
4073 *data_p = r.out.data;
4075 if (result_p) {
4076 *result_p = r.out.result;
4079 return true;
4083 static bool test_EnumPrinterData_all(struct torture_context *tctx,
4084 struct dcerpc_pipe *p,
4085 struct policy_handle *handle)
4087 uint32_t enum_index = 0;
4088 enum winreg_Type type;
4089 uint32_t value_needed;
4090 uint32_t data_needed;
4091 uint8_t *data;
4092 const char *value_name;
4093 WERROR result;
4095 torture_comment(tctx, "Testing EnumPrinterData\n");
4097 do {
4098 torture_assert(tctx,
4099 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
4100 &type, &value_needed, &data_needed,
4101 &value_name, &data, &result),
4102 "EnumPrinterData failed");
4104 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
4105 break;
4108 torture_assert(tctx,
4109 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
4110 &type, &value_needed, &data_needed,
4111 &value_name, &data, &result),
4112 "EnumPrinterData failed");
4114 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
4115 break;
4118 enum_index++;
4120 } while (W_ERROR_IS_OK(result));
4122 torture_comment(tctx, "EnumPrinterData test succeeded\n");
4124 return true;
4127 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
4128 struct dcerpc_binding_handle *b,
4129 struct policy_handle *handle,
4130 const char *key_name,
4131 uint32_t *count_p,
4132 struct spoolss_PrinterEnumValues **info_p)
4134 struct spoolss_EnumPrinterDataEx r;
4135 struct spoolss_PrinterEnumValues *info;
4136 uint32_t needed;
4137 uint32_t count;
4139 r.in.handle = handle;
4140 r.in.key_name = key_name;
4141 r.in.offered = 0;
4142 r.out.needed = &needed;
4143 r.out.count = &count;
4144 r.out.info = &info;
4146 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
4148 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
4149 "EnumPrinterDataEx failed");
4150 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4151 r.in.offered = needed;
4152 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
4153 "EnumPrinterDataEx failed");
4156 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
4158 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
4160 if (count_p) {
4161 *count_p = count;
4163 if (info_p) {
4164 *info_p = info;
4167 return true;
4170 static bool test_SetPrinterData(struct torture_context *tctx,
4171 struct dcerpc_binding_handle *b,
4172 struct policy_handle *handle,
4173 const char *value_name,
4174 enum winreg_Type type,
4175 uint8_t *data,
4176 uint32_t offered);
4177 static bool test_DeletePrinterData(struct torture_context *tctx,
4178 struct dcerpc_binding_handle *b,
4179 struct policy_handle *handle,
4180 const char *value_name);
4182 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
4183 struct dcerpc_pipe *p,
4184 struct policy_handle *handle)
4186 uint32_t count;
4187 struct spoolss_PrinterEnumValues *info;
4188 int i;
4189 uint32_t value_needed, data_needed;
4190 uint32_t value_offered, data_offered;
4191 WERROR result;
4192 struct dcerpc_binding_handle *b = p->binding_handle;
4194 enum winreg_Type type;
4195 DATA_BLOB blob;
4197 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
4199 torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
4200 type = REG_SZ;
4202 torture_assert(tctx,
4203 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
4204 "SetPrinterData failed");
4206 blob = data_blob_string_const("torture_data2");
4208 torture_assert(tctx,
4209 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
4210 "SetPrinterData failed");
4212 blob = data_blob_talloc(tctx, NULL, 4);
4213 SIVAL(blob.data, 0, 0x11223344);
4215 torture_assert(tctx,
4216 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
4217 "SetPrinterData failed");
4219 torture_assert(tctx,
4220 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
4221 "failed to call EnumPrinterDataEx");
4223 /* get the max sizes for value and data */
4225 torture_assert(tctx,
4226 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
4227 NULL, &value_needed, &data_needed,
4228 NULL, NULL, &result),
4229 "EnumPrinterData failed");
4230 torture_assert_werr_ok(tctx, result, "unexpected result");
4232 /* check if the reply from the EnumPrinterData really matches max values */
4234 for (i=0; i < count; i++) {
4235 if (info[i].value_name_len > value_needed) {
4236 torture_fail(tctx,
4237 talloc_asprintf(tctx,
4238 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
4239 info[i].value_name_len, value_needed));
4241 if (info[i].data_length > data_needed) {
4242 torture_fail(tctx,
4243 talloc_asprintf(tctx,
4244 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
4245 info[i].data_length, data_needed));
4249 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
4250 * sort or not sort the replies by value name, we should be able to do
4251 * the following entry comparison */
4253 data_offered = data_needed;
4254 value_offered = value_needed;
4256 for (i=0; i < count; i++) {
4258 const char *value_name;
4259 uint8_t *data;
4261 torture_assert(tctx,
4262 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
4263 &type, &value_needed, &data_needed,
4264 &value_name, &data, &result),
4265 "EnumPrinterData failed");
4267 if (i -1 == count) {
4268 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
4269 "unexpected result");
4270 break;
4271 } else {
4272 torture_assert_werr_ok(tctx, result, "unexpected result");
4275 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
4276 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
4277 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
4278 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
4279 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
4282 torture_assert(tctx,
4283 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
4284 "DeletePrinterData failed");
4285 torture_assert(tctx,
4286 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
4287 "DeletePrinterData failed");
4288 torture_assert(tctx,
4289 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
4290 "DeletePrinterData failed");
4292 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4294 return true;
4297 static bool test_DeletePrinterData(struct torture_context *tctx,
4298 struct dcerpc_binding_handle *b,
4299 struct policy_handle *handle,
4300 const char *value_name)
4302 NTSTATUS status;
4303 struct spoolss_DeletePrinterData r;
4305 r.in.handle = handle;
4306 r.in.value_name = value_name;
4308 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
4309 r.in.value_name);
4311 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
4313 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
4314 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
4316 return true;
4319 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
4320 struct dcerpc_binding_handle *b,
4321 struct policy_handle *handle,
4322 const char *key_name,
4323 const char *value_name)
4325 struct spoolss_DeletePrinterDataEx r;
4327 r.in.handle = handle;
4328 r.in.key_name = key_name;
4329 r.in.value_name = value_name;
4331 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
4332 r.in.key_name, r.in.value_name);
4334 torture_assert_ntstatus_ok(tctx,
4335 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
4336 "DeletePrinterDataEx failed");
4337 torture_assert_werr_ok(tctx, r.out.result,
4338 "DeletePrinterDataEx failed");
4340 return true;
4343 static bool test_DeletePrinterKey(struct torture_context *tctx,
4344 struct dcerpc_binding_handle *b,
4345 struct policy_handle *handle,
4346 const char *key_name)
4348 struct spoolss_DeletePrinterKey r;
4350 r.in.handle = handle;
4351 r.in.key_name = key_name;
4353 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
4355 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
4356 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
4357 return true;
4360 torture_assert_ntstatus_ok(tctx,
4361 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
4362 "DeletePrinterKey failed");
4363 torture_assert_werr_ok(tctx, r.out.result,
4364 "DeletePrinterKey failed");
4366 return true;
4369 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4370 struct dcerpc_binding_handle *b,
4371 struct policy_handle *handle)
4373 struct winreg_OpenHKLM r;
4375 r.in.system_name = NULL;
4376 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4377 r.out.handle = handle;
4379 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4381 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4382 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4384 return true;
4387 static void init_winreg_String(struct winreg_String *name, const char *s)
4389 name->name = s;
4390 if (s) {
4391 name->name_len = 2 * (strlen_m(s) + 1);
4392 name->name_size = name->name_len;
4393 } else {
4394 name->name_len = 0;
4395 name->name_size = 0;
4399 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4400 struct dcerpc_binding_handle *b,
4401 struct policy_handle *hive_handle,
4402 const char *keyname,
4403 uint32_t options,
4404 struct policy_handle *key_handle)
4406 struct winreg_OpenKey r;
4408 r.in.parent_handle = hive_handle;
4409 init_winreg_String(&r.in.keyname, keyname);
4410 r.in.options = options;
4411 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4412 r.out.handle = key_handle;
4414 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4416 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4417 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4419 return true;
4422 static bool test_winreg_OpenKey(struct torture_context *tctx,
4423 struct dcerpc_binding_handle *b,
4424 struct policy_handle *hive_handle,
4425 const char *keyname,
4426 struct policy_handle *key_handle)
4428 return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4429 REG_OPTION_NON_VOLATILE, key_handle);
4432 static bool test_winreg_CloseKey(struct torture_context *tctx,
4433 struct dcerpc_binding_handle *b,
4434 struct policy_handle *handle)
4436 struct winreg_CloseKey r;
4438 r.in.handle = handle;
4439 r.out.handle = handle;
4441 torture_comment(tctx, "Testing winreg_CloseKey\n");
4443 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4444 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4446 return true;
4449 bool test_winreg_QueryValue(struct torture_context *tctx,
4450 struct dcerpc_binding_handle *b,
4451 struct policy_handle *handle,
4452 const char *value_name,
4453 enum winreg_Type *type_p,
4454 uint32_t *data_size_p,
4455 uint32_t *data_length_p,
4456 uint8_t **data_p)
4458 struct winreg_QueryValue r;
4459 enum winreg_Type type = REG_NONE;
4460 uint32_t data_size = 0;
4461 uint32_t data_length = 0;
4462 struct winreg_String valuename;
4463 uint8_t *data = NULL;
4465 init_winreg_String(&valuename, value_name);
4467 data = talloc_zero_array(tctx, uint8_t, 0);
4469 r.in.handle = handle;
4470 r.in.value_name = &valuename;
4471 r.in.type = &type;
4472 r.in.data_size = &data_size;
4473 r.in.data_length = &data_length;
4474 r.in.data = data;
4475 r.out.type = &type;
4476 r.out.data = data;
4477 r.out.data_size = &data_size;
4478 r.out.data_length = &data_length;
4480 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4482 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4483 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4484 *r.in.data_size = *r.out.data_size;
4485 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4486 r.in.data = data;
4487 r.out.data = data;
4488 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4490 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4492 if (type_p) {
4493 *type_p = *r.out.type;
4495 if (data_size_p) {
4496 *data_size_p = *r.out.data_size;
4498 if (data_length_p) {
4499 *data_length_p = *r.out.data_length;
4501 if (data_p) {
4502 *data_p = r.out.data;
4505 return true;
4508 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4509 struct dcerpc_binding_handle *b,
4510 struct policy_handle *handle,
4511 const char *printer_name,
4512 const char *key_name,
4513 const char *value_name,
4514 enum winreg_Type *w_type,
4515 uint32_t *w_size,
4516 uint32_t *w_length,
4517 uint8_t **w_data)
4519 const char *printer_key;
4520 struct policy_handle key_handle;
4522 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4523 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4525 torture_assert(tctx,
4526 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4528 torture_assert(tctx,
4529 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4531 torture_assert(tctx,
4532 test_winreg_CloseKey(tctx, b, &key_handle), "");
4534 return true;
4537 static bool test_GetForm_winreg(struct torture_context *tctx,
4538 struct dcerpc_binding_handle *b,
4539 struct policy_handle *handle,
4540 const char *key_name,
4541 const char *form_name,
4542 enum winreg_Type *w_type,
4543 uint32_t *w_size,
4544 uint32_t *w_length,
4545 uint8_t **w_data)
4547 struct policy_handle key_handle;
4549 torture_assert(tctx,
4550 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4552 torture_assert(tctx,
4553 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4555 torture_assert(tctx,
4556 test_winreg_CloseKey(tctx, b, &key_handle), "");
4558 return true;
4561 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4562 struct dcerpc_binding_handle *b,
4563 struct policy_handle *handle,
4564 const char *symlink_keyname,
4565 const char *symlink_destination)
4567 /* check if the first key is a symlink to the second key */
4569 enum winreg_Type w_type;
4570 uint32_t w_size;
4571 uint32_t w_length;
4572 uint8_t *w_data;
4573 struct policy_handle key_handle;
4574 DATA_BLOB blob;
4575 const char *str;
4577 if (torture_setting_bool(tctx, "samba3", false)) {
4578 torture_skip(tctx, "skip winreg symlink test against samba");
4581 torture_assert(tctx,
4582 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4583 "failed to open key link");
4585 torture_assert(tctx,
4586 test_winreg_QueryValue(tctx, b, &key_handle,
4587 "SymbolicLinkValue",
4588 &w_type, &w_size, &w_length, &w_data),
4589 "failed to query for 'SymbolicLinkValue' attribute");
4591 torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4593 blob = data_blob(w_data, w_size);
4594 str = reg_val_data_string(tctx, REG_SZ, blob);
4596 torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4598 torture_assert(tctx,
4599 test_winreg_CloseKey(tctx, b, &key_handle),
4600 "failed to close key link");
4602 return true;
4605 static const char *strip_unc(const char *unc)
4607 char *name;
4609 if (!unc) {
4610 return NULL;
4613 if (unc[0] == '\\' && unc[1] == '\\') {
4614 unc +=2;
4617 name = strchr(unc, '\\');
4618 if (name) {
4619 return name+1;
4622 return unc;
4625 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4626 struct dcerpc_binding_handle *b,
4627 struct policy_handle *handle,
4628 const char *printer_name,
4629 struct dcerpc_binding_handle *winreg_handle,
4630 struct policy_handle *hive_handle)
4632 union spoolss_PrinterInfo info;
4633 const char *keys[] = {
4634 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4635 TOP_LEVEL_PRINT_PRINTERS_KEY
4637 int i;
4638 const char *printername, *sharename;
4640 torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4642 torture_assert(tctx,
4643 test_GetPrinter_level(tctx, b, handle, 2, &info),
4644 "failed to get printer info level 2");
4646 printername = strip_unc(info.info2.printername);
4647 sharename = strip_unc(info.info2.sharename);
4649 #define test_sz(wname, iname) \
4650 do {\
4651 DATA_BLOB blob;\
4652 const char *str;\
4653 enum winreg_Type w_type;\
4654 uint32_t w_size;\
4655 uint32_t w_length;\
4656 uint8_t *w_data;\
4657 torture_assert(tctx,\
4658 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4659 &w_type, &w_size, &w_length, &w_data),\
4660 "failed to query winreg");\
4661 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4662 blob = data_blob(w_data, w_size);\
4663 str = reg_val_data_string(tctx, REG_SZ, blob);\
4664 if (w_size == 2 && iname == NULL) {\
4665 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4666 } else {\
4667 torture_assert_str_equal(tctx, str, iname,\
4668 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4670 } while(0);
4672 #define test_dword(wname, iname) \
4673 do {\
4674 uint32_t value;\
4675 enum winreg_Type w_type;\
4676 uint32_t w_size;\
4677 uint32_t w_length;\
4678 uint8_t *w_data;\
4679 torture_assert(tctx,\
4680 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4681 &w_type, &w_size, &w_length, &w_data),\
4682 "failed to query winreg");\
4683 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4684 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4685 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4686 value = IVAL(w_data, 0);\
4687 torture_assert_int_equal(tctx, value, iname,\
4688 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4689 } while(0);
4691 #define test_binary(wname, iname) \
4692 do {\
4693 enum winreg_Type w_type;\
4694 uint32_t w_size;\
4695 uint32_t w_length;\
4696 uint8_t *w_data;\
4697 torture_assert(tctx,\
4698 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4699 &w_type, &w_size, &w_length, &w_data),\
4700 "failed to query winreg");\
4701 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4702 torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4703 torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4704 "binary unequal");\
4705 } while(0);
4708 #define test_dm(wname, iname) \
4709 do {\
4710 DATA_BLOB blob;\
4711 struct spoolss_DeviceMode dm;\
4712 enum ndr_err_code ndr_err;\
4713 enum winreg_Type w_type;\
4714 uint32_t w_size;\
4715 uint32_t w_length;\
4716 uint8_t *w_data;\
4717 torture_assert(tctx,\
4718 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4719 &w_type, &w_size, &w_length, &w_data),\
4720 "failed to query winreg");\
4721 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4722 blob = data_blob(w_data, w_size);\
4723 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4724 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4725 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4726 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4727 "dm unequal");\
4728 } while(0);
4730 #define test_sd(wname, iname) \
4731 do {\
4732 DATA_BLOB blob;\
4733 struct security_descriptor sd;\
4734 enum ndr_err_code ndr_err;\
4735 enum winreg_Type w_type;\
4736 uint32_t w_size;\
4737 uint32_t w_length;\
4738 uint8_t *w_data;\
4739 torture_assert(tctx,\
4740 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4741 &w_type, &w_size, &w_length, &w_data),\
4742 "failed to query winreg");\
4743 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4744 blob = data_blob(w_data, w_size);\
4745 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4746 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4747 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4748 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4749 "sd unequal");\
4750 } while(0);
4752 #define test_multi_sz(wname, iname) \
4753 do {\
4754 DATA_BLOB blob;\
4755 const char **array;\
4756 enum winreg_Type w_type;\
4757 uint32_t w_size;\
4758 uint32_t w_length;\
4759 uint8_t *w_data;\
4760 int i;\
4761 torture_assert(tctx,\
4762 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4763 &w_type, &w_size, &w_length, &w_data),\
4764 "failed to query winreg");\
4765 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4766 blob = data_blob(w_data, w_size);\
4767 torture_assert(tctx, \
4768 pull_reg_multi_sz(tctx, &blob, &array),\
4769 "failed to pull multi sz");\
4770 for (i=0; array[i] != NULL; i++) {\
4771 torture_assert_str_equal(tctx, array[i], iname[i],\
4772 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4774 } while(0);
4776 if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4777 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4778 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4780 torture_warning(tctx, "failed to check for winreg symlink");
4783 for (i=0; i < ARRAY_SIZE(keys); i++) {
4785 const char *printer_key;
4786 struct policy_handle key_handle;
4788 printer_key = talloc_asprintf(tctx, "%s\\%s",
4789 keys[i], printer_name);
4791 torture_assert(tctx,
4792 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4794 test_sz("Name", printername);
4795 test_sz("Share Name", sharename);
4796 test_sz("Port", info.info2.portname);
4797 test_sz("Printer Driver", info.info2.drivername);
4798 test_sz("Description", info.info2.comment);
4799 test_sz("Location", info.info2.location);
4800 test_sz("Separator File", info.info2.sepfile);
4801 test_sz("Print Processor", info.info2.printprocessor);
4802 test_sz("Datatype", info.info2.datatype);
4803 test_sz("Parameters", info.info2.parameters);
4804 /* winreg: 0, spoolss not */
4805 /* test_dword("Attributes", info.info2.attributes); */
4806 test_dword("Priority", info.info2.priority);
4807 test_dword("Default Priority", info.info2.defaultpriority);
4808 /* winreg: 60, spoolss: 0 */
4809 /* test_dword("StartTime", info.info2.starttime); */
4810 /* test_dword("UntilTime", info.info2.untiltime); */
4811 /* winreg != spoolss */
4812 /* test_dword("Status", info.info2.status); */
4813 test_dm("Default DevMode", info.info2.devmode);
4814 test_sd("Security", info.info2.secdesc);
4816 torture_assert(tctx,
4817 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4820 #undef test_dm
4821 #undef test_sd
4823 torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4825 return true;
4828 static bool test_PrintProcessors(struct torture_context *tctx,
4829 struct dcerpc_binding_handle *b,
4830 const char *environment,
4831 struct dcerpc_binding_handle *winreg_handle,
4832 struct policy_handle *hive_handle)
4834 union spoolss_PrintProcessorInfo *info;
4835 uint32_t count;
4836 int i;
4838 torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4840 torture_assert(tctx,
4841 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
4842 "failed to enum print processors level 1");
4844 for (i=0; i < count; i++) {
4846 const char *processor_key;
4847 struct policy_handle key_handle;
4849 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4850 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4851 environment,
4852 info[i].info1.print_processor_name);
4854 torture_assert(tctx,
4855 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4857 /* nothing to check in there so far */
4859 torture_assert(tctx,
4860 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4863 torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4865 return true;
4868 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4869 struct dcerpc_binding_handle *b,
4870 struct policy_handle *handle,
4871 const char *driver_name,
4872 const char *architecture,
4873 uint32_t level,
4874 uint32_t client_major_version,
4875 uint32_t client_minor_version,
4876 union spoolss_DriverInfo *info_p,
4877 WERROR *result);
4879 static const char *strip_path(const char *path)
4881 char *p;
4883 if (path == NULL) {
4884 return NULL;
4887 p = strrchr(path, '\\');
4888 if (p) {
4889 return p+1;
4892 return path;
4895 static const char **strip_paths(const char **path_array)
4897 int i;
4899 if (path_array == NULL) {
4900 return NULL;
4903 for (i=0; path_array[i] != NULL; i++) {
4904 path_array[i] = strip_path(path_array[i]);
4907 return path_array;
4910 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4912 time_t t;
4913 struct tm *tm;
4915 if (nt == 0) {
4916 return talloc_strdup(mem_ctx, "01/01/1601");
4919 t = nt_time_to_unix(nt);
4920 tm = localtime(&t);
4922 return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4923 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4926 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4928 return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4929 (unsigned)((v >> 48) & 0xFFFF),
4930 (unsigned)((v >> 32) & 0xFFFF),
4931 (unsigned)((v >> 16) & 0xFFFF),
4932 (unsigned)(v & 0xFFFF));
4935 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4936 struct dcerpc_binding_handle *b,
4937 struct policy_handle *handle,
4938 const char *printer_name,
4939 const char *driver_name,
4940 const char *environment,
4941 enum spoolss_DriverOSVersion version,
4942 struct dcerpc_binding_handle *winreg_handle,
4943 struct policy_handle *hive_handle,
4944 const char *server_name_slash)
4946 WERROR result;
4947 union spoolss_DriverInfo info;
4948 const char *driver_key;
4949 struct policy_handle key_handle;
4951 const char *driver_path;
4952 const char *data_file;
4953 const char *config_file;
4954 const char *help_file;
4955 const char **dependent_files;
4957 const char *driver_date;
4958 const char *inbox_driver_date;
4960 const char *driver_version;
4961 const char *inbox_driver_version;
4963 torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4965 driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4966 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4967 environment,
4968 version,
4969 driver_name);
4971 torture_assert(tctx,
4972 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4973 "failed to open driver key");
4975 if (torture_setting_bool(tctx, "samba3", false) ||
4976 torture_setting_bool(tctx, "w2k3", false)) {
4977 goto try_level6;
4980 if (handle) {
4981 torture_assert(tctx,
4982 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
4983 "failed to get driver info level 8");
4984 } else {
4985 torture_assert(tctx,
4986 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
4987 "failed to get driver info level 8");
4990 if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4991 goto try_level6;
4994 driver_path = strip_path(info.info8.driver_path);
4995 data_file = strip_path(info.info8.data_file);
4996 config_file = strip_path(info.info8.config_file);
4997 help_file = strip_path(info.info8.help_file);
4998 dependent_files = strip_paths(info.info8.dependent_files);
5000 driver_date = driver_winreg_date(tctx, info.info8.driver_date);
5001 inbox_driver_date = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
5003 driver_version = driver_winreg_version(tctx, info.info8.driver_version);
5004 inbox_driver_version = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
5006 test_sz("Configuration File", config_file);
5007 test_sz("Data File", data_file);
5008 test_sz("Datatype", info.info8.default_datatype);
5009 test_sz("Driver", driver_path);
5010 test_sz("DriverDate", driver_date);
5011 test_sz("DriverVersion", driver_version);
5012 test_sz("HardwareID", info.info8.hardware_id);
5013 test_sz("Help File", help_file);
5014 test_sz("InfPath", info.info8.inf_path);
5015 test_sz("Manufacturer", info.info8.manufacturer_name);
5016 test_sz("MinInboxDriverVerDate", inbox_driver_date);
5017 test_sz("MinInboxDriverVerVersion", inbox_driver_version);
5018 test_sz("Monitor", info.info8.monitor_name);
5019 test_sz("OEM URL", info.info8.manufacturer_url);
5020 test_sz("Print Processor", info.info8.print_processor);
5021 test_sz("Provider", info.info8.provider);
5022 test_sz("VendorSetup", info.info8.vendor_setup);
5023 test_multi_sz("ColorProfiles", info.info8.color_profiles);
5024 test_multi_sz("Dependent Files", dependent_files);
5025 test_multi_sz("CoreDependencies", info.info8.core_driver_dependencies);
5026 test_multi_sz("Previous Names", info.info8.previous_names);
5027 /* test_dword("Attributes", ?); */
5028 test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
5029 test_dword("Version", info.info8.version);
5030 /* test_dword("TempDir", ?); */
5032 try_level6:
5034 if (handle) {
5035 torture_assert(tctx,
5036 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
5037 "failed to get driver info level 6");
5038 } else {
5039 torture_assert(tctx,
5040 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
5041 "failed to get driver info level 6");
5044 driver_path = strip_path(info.info6.driver_path);
5045 data_file = strip_path(info.info6.data_file);
5046 config_file = strip_path(info.info6.config_file);
5047 help_file = strip_path(info.info6.help_file);
5048 dependent_files = strip_paths(info.info6.dependent_files);
5050 driver_date = driver_winreg_date(tctx, info.info6.driver_date);
5052 driver_version = driver_winreg_version(tctx, info.info6.driver_version);
5054 test_sz("Configuration File", config_file);
5055 test_sz("Data File", data_file);
5056 test_sz("Datatype", info.info6.default_datatype);
5057 test_sz("Driver", driver_path);
5058 if (torture_setting_bool(tctx, "w2k3", false)) {
5059 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
5060 push_nttime(blob.data, 0, info.info6.driver_date);
5061 test_binary("DriverDate", blob);
5062 SBVAL(blob.data, 0, info.info6.driver_version);
5063 test_binary("DriverVersion", blob);
5064 } else {
5065 test_sz("DriverDate", driver_date);
5066 test_sz("DriverVersion", driver_version);
5068 test_sz("HardwareID", info.info6.hardware_id);
5069 test_sz("Help File", help_file);
5070 test_sz("Manufacturer", info.info6.manufacturer_name);
5071 test_sz("Monitor", info.info6.monitor_name);
5072 test_sz("OEM URL", info.info6.manufacturer_url);
5073 test_sz("Provider", info.info6.provider);
5074 test_multi_sz("Dependent Files", dependent_files);
5075 test_multi_sz("Previous Names", info.info6.previous_names);
5076 /* test_dword("Attributes", ?); */
5077 test_dword("Version", info.info6.version);
5078 /* test_dword("TempDir", ?); */
5080 if (handle) {
5081 torture_assert(tctx,
5082 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
5083 "failed to get driver info level 3");
5084 } else {
5085 torture_assert(tctx,
5086 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
5087 "failed to get driver info level 3");
5090 driver_path = strip_path(info.info3.driver_path);
5091 data_file = strip_path(info.info3.data_file);
5092 config_file = strip_path(info.info3.config_file);
5093 help_file = strip_path(info.info3.help_file);
5094 dependent_files = strip_paths(info.info3.dependent_files);
5096 test_sz("Configuration File", config_file);
5097 test_sz("Data File", data_file);
5098 test_sz("Datatype", info.info3.default_datatype);
5099 test_sz("Driver", driver_path);
5100 test_sz("Help File", help_file);
5101 test_sz("Monitor", info.info3.monitor_name);
5102 test_multi_sz("Dependent Files", dependent_files);
5103 /* test_dword("Attributes", ?); */
5104 test_dword("Version", info.info3.version);
5105 /* test_dword("TempDir", ?); */
5108 torture_assert(tctx,
5109 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
5111 torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
5113 return true;
5116 #undef test_sz
5117 #undef test_dword
5119 static bool test_SetPrinterData(struct torture_context *tctx,
5120 struct dcerpc_binding_handle *b,
5121 struct policy_handle *handle,
5122 const char *value_name,
5123 enum winreg_Type type,
5124 uint8_t *data,
5125 uint32_t offered)
5127 struct spoolss_SetPrinterData r;
5129 r.in.handle = handle;
5130 r.in.value_name = value_name;
5131 r.in.type = type;
5132 r.in.data = data;
5133 r.in.offered = offered;
5135 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
5136 r.in.value_name);
5138 torture_assert_ntstatus_ok(tctx,
5139 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
5140 "SetPrinterData failed");
5141 torture_assert_werr_ok(tctx, r.out.result,
5142 "SetPrinterData failed");
5144 return true;
5147 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
5148 struct dcerpc_binding_handle *b,
5149 struct policy_handle *handle,
5150 const char *printer_name,
5151 struct dcerpc_binding_handle *winreg_handle,
5152 struct policy_handle *hive_handle)
5154 const char *values[] = {
5155 "spootyfoot",
5156 "spooty\\foot",
5157 #if 0
5158 /* FIXME: not working with s3 atm. */
5159 "spooty,foot",
5160 "spooty,fo,ot",
5161 #endif
5162 "spooty foot",
5163 #if 0
5164 /* FIXME: not working with s3 atm. */
5165 "spooty\\fo,ot",
5166 "spooty,fo\\ot"
5167 #endif
5169 int i;
5171 for (i=0; i < ARRAY_SIZE(values); i++) {
5173 enum winreg_Type type, expected_type = REG_SZ;
5174 DATA_BLOB blob;
5175 uint8_t *data;
5176 uint32_t needed;
5178 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
5179 type = REG_SZ;
5181 torture_assert(tctx,
5182 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
5183 "SetPrinterData failed");
5185 torture_assert(tctx,
5186 test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
5187 "GetPrinterData failed");
5189 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
5190 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
5191 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
5193 if (winreg_handle && hive_handle) {
5195 enum winreg_Type w_type;
5196 uint32_t w_size;
5197 uint32_t w_length;
5198 uint8_t *w_data;
5200 torture_assert(tctx,
5201 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5202 printer_name, "PrinterDriverData", values[i],
5203 &w_type, &w_size, &w_length, &w_data), "");
5205 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
5206 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
5207 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
5208 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
5211 torture_assert(tctx,
5212 test_DeletePrinterData(tctx, b, handle, values[i]),
5213 "DeletePrinterData failed");
5216 return true;
5220 static bool test_EnumPrinterKey(struct torture_context *tctx,
5221 struct dcerpc_binding_handle *b,
5222 struct policy_handle *handle,
5223 const char *key_name,
5224 const char ***array);
5226 static bool test_SetPrinterDataEx(struct torture_context *tctx,
5227 struct dcerpc_binding_handle *b,
5228 struct policy_handle *handle,
5229 const char *key_name,
5230 const char *value_name,
5231 enum winreg_Type type,
5232 uint8_t *data,
5233 uint32_t offered)
5235 NTSTATUS status;
5236 struct spoolss_SetPrinterDataEx r;
5238 r.in.handle = handle;
5239 r.in.key_name = key_name;
5240 r.in.value_name = value_name;
5241 r.in.type = type;
5242 r.in.data = data;
5243 r.in.offered = offered;
5245 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
5246 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
5248 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
5250 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
5251 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
5253 return true;
5256 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
5257 struct dcerpc_pipe *p,
5258 struct policy_handle *handle)
5260 struct dcerpc_binding_handle *b = p->binding_handle;
5261 const char *value_name = "dog";
5262 const char *keys[] = {
5263 "torturedataex",
5264 "torture data ex",
5265 "torturedataex_with_subkey\\subkey",
5266 "torturedataex_with_subkey\\subkey:0",
5267 "torturedataex_with_subkey\\subkey:1",
5268 "torturedataex_with_subkey\\subkey\\subsubkey",
5269 "torturedataex_with_subkey\\subkey\\subsubkey:0",
5270 "torturedataex_with_subkey\\subkey\\subsubkey:1",
5271 "torture,data",
5272 "torture,data,ex",
5273 "torture,data\\ex",
5274 "torture\\data,ex",
5275 "torture/data",
5276 "torture/data ex",
5277 "torture/data ex/sub",
5278 "torture//data",
5279 "torture//data ex",
5280 "torture//data ex/sub",
5281 "torture//data ex//sub",
5283 int i;
5285 for (i=0; i < ARRAY_SIZE(keys); i++) {
5287 char *c;
5288 const char *key;
5289 enum winreg_Type type;
5290 DATA_BLOB blob_in, blob_out;
5291 const char **subkeys;
5292 uint32_t ecount;
5293 struct spoolss_PrinterEnumValues *einfo;
5294 uint32_t needed;
5296 blob_in = data_blob_talloc(tctx, NULL, 42);
5298 generate_random_buffer(blob_in.data, blob_in.length);
5300 torture_assert(tctx,
5301 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
5302 "failed to call SetPrinterDataEx");
5304 torture_assert(tctx,
5305 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
5306 "failed to call GetPrinterDataEx");
5308 blob_out.length = needed;
5309 torture_assert(tctx,
5310 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
5311 "failed to call EnumPrinterDataEx");
5313 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5314 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5315 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5317 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5318 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5319 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5320 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5321 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5322 if (einfo[0].data_length > 0) {
5323 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5326 key = talloc_strdup(tctx, keys[i]);
5328 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
5329 return false;
5332 c = strchr(key, '\\');
5333 if (c) {
5334 int k;
5336 /* we have subkeys */
5338 *c = 0;
5340 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
5341 return false;
5344 for (k=0; subkeys && subkeys[k]; k++) {
5346 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
5348 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
5349 return false;
5353 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5354 return false;
5357 } else {
5358 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5359 return false;
5364 return true;
5367 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
5368 struct dcerpc_pipe *p,
5369 struct policy_handle *handle)
5371 struct dcerpc_binding_handle *b = p->binding_handle;
5372 const char *key = "torturedataex";
5373 const char *values[] = {
5374 "torture_value",
5375 "torture value",
5376 "torture,value",
5377 "torture/value",
5378 "torture\\value",
5379 "torture\\\\value"
5381 int i;
5383 for (i=0; i < ARRAY_SIZE(values); i++) {
5385 enum winreg_Type type;
5386 DATA_BLOB blob_in, blob_out;
5387 uint32_t ecount;
5388 struct spoolss_PrinterEnumValues *einfo;
5389 uint32_t needed;
5391 if (torture_setting_bool(tctx, "samba3", false)) {
5392 char *q;
5393 q = strrchr(values[i], ',');
5394 if (q) {
5395 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
5396 values[i]);
5397 continue;
5401 blob_in = data_blob_talloc(tctx, NULL, 42);
5403 generate_random_buffer(blob_in.data, blob_in.length);
5405 torture_assert(tctx,
5406 test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
5407 "failed to call SetPrinterDataEx");
5409 torture_assert(tctx,
5410 test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
5411 "failed to call GetPrinterDataEx");
5413 blob_out.length = needed;
5414 torture_assert(tctx,
5415 test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
5416 "failed to call EnumPrinterDataEx");
5418 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5419 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5420 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5422 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5423 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5424 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5425 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5426 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5427 if (einfo[0].data_length > 0) {
5428 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5431 torture_assert(tctx,
5432 test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5433 "failed to call DeletePrinterDataEx");
5436 return true;
5440 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5441 struct dcerpc_pipe *p,
5442 struct policy_handle *handle,
5443 const char *printername,
5444 struct dcerpc_binding_handle *winreg_handle,
5445 struct policy_handle *hive_handle)
5447 struct dcerpc_binding_handle *b = p->binding_handle;
5448 const char *value_name = "dog";
5449 const char *key_name = "torturedataex";
5450 enum winreg_Type types[] = {
5451 REG_SZ,
5452 REG_MULTI_SZ,
5453 REG_DWORD,
5454 REG_BINARY
5456 const char *str = "abcdefghi";
5457 int t, s;
5459 for (t=0; t < ARRAY_SIZE(types); t++) {
5460 for (s=0; s < strlen(str); s++) {
5462 enum winreg_Type type;
5463 const char *string = talloc_strndup(tctx, str, s);
5464 const char *array[2];
5465 DATA_BLOB blob = data_blob_string_const(string);
5466 DATA_BLOB data;
5467 uint8_t *data_out;
5468 uint32_t needed, offered = 0;
5469 uint32_t ecount;
5470 struct spoolss_PrinterEnumValues *einfo;
5472 array[0] = talloc_strdup(tctx, string);
5473 array[1] = NULL;
5475 if (types[t] == REG_DWORD) {
5476 s = 0xffff;
5479 switch (types[t]) {
5480 case REG_BINARY:
5481 data = blob;
5482 offered = blob.length;
5483 break;
5484 case REG_DWORD:
5485 data = data_blob_talloc(tctx, NULL, 4);
5486 SIVAL(data.data, 0, 0x12345678);
5487 offered = 4;
5488 break;
5489 case REG_SZ:
5490 torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5491 type = REG_SZ;
5492 offered = data.length;
5493 /*strlen_m_term(data.string)*2;*/
5494 break;
5495 case REG_MULTI_SZ:
5496 torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5497 type = REG_MULTI_SZ;
5498 offered = data.length;
5499 break;
5500 default:
5501 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5504 torture_assert(tctx,
5505 test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5506 "failed to call SetPrinterDataEx");
5508 torture_assert(tctx,
5509 test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
5510 "failed to call GetPrinterDataEx");
5512 torture_assert(tctx,
5513 test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5514 "failed to call EnumPrinterDataEx");
5516 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5517 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5518 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5520 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5521 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5522 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5523 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5524 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5525 if (einfo[0].data_length > 0) {
5526 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5529 if (winreg_handle && hive_handle) {
5530 enum winreg_Type w_type;
5531 uint32_t w_size;
5532 uint32_t w_length;
5533 uint8_t *w_data;
5535 torture_assert(tctx,
5536 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5537 printername, key_name, value_name,
5538 &w_type, &w_size, &w_length, &w_data), "");
5540 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5541 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5542 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5543 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5546 torture_assert(tctx,
5547 test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5548 "failed to call DeletePrinterDataEx");
5552 return true;
5555 static bool test_PrinterData_winreg(struct torture_context *tctx,
5556 struct dcerpc_pipe *p,
5557 struct policy_handle *handle,
5558 const char *printer_name)
5560 struct dcerpc_binding_handle *b = p->binding_handle;
5561 struct dcerpc_pipe *p2;
5562 bool ret = true;
5563 struct policy_handle hive_handle;
5564 struct dcerpc_binding_handle *b2;
5566 torture_assert_ntstatus_ok(tctx,
5567 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5568 "could not open winreg pipe");
5569 b2 = p2->binding_handle;
5571 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5573 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5574 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5576 test_winreg_CloseKey(tctx, b2, &hive_handle);
5578 talloc_free(p2);
5580 return ret;
5583 static bool test_Forms_winreg(struct torture_context *tctx,
5584 struct dcerpc_binding_handle *b,
5585 struct policy_handle *handle,
5586 bool print_server,
5587 const char *printer_name)
5589 struct dcerpc_pipe *p2;
5590 bool ret = true;
5591 struct policy_handle hive_handle;
5592 struct dcerpc_binding_handle *b2;
5594 torture_assert_ntstatus_ok(tctx,
5595 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5596 "could not open winreg pipe");
5597 b2 = p2->binding_handle;
5599 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5601 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5603 test_winreg_CloseKey(tctx, b2, &hive_handle);
5605 talloc_free(p2);
5607 return ret;
5610 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5611 struct dcerpc_pipe *p,
5612 struct policy_handle *handle,
5613 const char *printer_name)
5615 struct dcerpc_binding_handle *b = p->binding_handle;
5616 struct dcerpc_pipe *p2;
5617 bool ret = true;
5618 struct policy_handle hive_handle;
5619 struct dcerpc_binding_handle *b2;
5621 torture_assert_ntstatus_ok(tctx,
5622 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5623 "could not open winreg pipe");
5624 b2 = p2->binding_handle;
5626 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5628 ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5630 test_winreg_CloseKey(tctx, b2, &hive_handle);
5632 talloc_free(p2);
5634 return ret;
5637 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5638 struct dcerpc_pipe *p,
5639 struct policy_handle *handle,
5640 const char *printer_name,
5641 const char *driver_name,
5642 const char *environment,
5643 enum spoolss_DriverOSVersion version)
5645 struct dcerpc_binding_handle *b = p->binding_handle;
5646 struct dcerpc_pipe *p2;
5647 bool ret = true;
5648 struct policy_handle hive_handle;
5649 struct dcerpc_binding_handle *b2;
5651 torture_assert_ntstatus_ok(tctx,
5652 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5653 "could not open winreg pipe");
5654 b2 = p2->binding_handle;
5656 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5658 ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
5660 test_winreg_CloseKey(tctx, b2, &hive_handle);
5662 talloc_free(p2);
5664 return ret;
5667 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5668 struct dcerpc_binding_handle *b,
5669 const char *environment)
5671 struct dcerpc_pipe *p2;
5672 bool ret = true;
5673 struct policy_handle hive_handle;
5674 struct dcerpc_binding_handle *b2;
5676 torture_assert_ntstatus_ok(tctx,
5677 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5678 "could not open winreg pipe");
5679 b2 = p2->binding_handle;
5681 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5683 ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5685 test_winreg_CloseKey(tctx, b2, &hive_handle);
5687 talloc_free(p2);
5689 return ret;
5692 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5693 struct dcerpc_pipe *p,
5694 struct policy_handle *handle,
5695 const char *printer_name)
5697 struct spoolss_SetPrinterInfoCtr info_ctr;
5698 struct spoolss_DevmodeContainer devmode_ctr;
5699 struct sec_desc_buf secdesc_ctr;
5700 union spoolss_SetPrinterInfo sinfo;
5701 union spoolss_PrinterInfo info;
5702 struct dcerpc_binding_handle *b = p->binding_handle;
5703 const char *pname;
5705 ZERO_STRUCT(info_ctr);
5706 ZERO_STRUCT(devmode_ctr);
5707 ZERO_STRUCT(secdesc_ctr);
5709 torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5711 torture_assert(tctx,
5712 test_GetPrinter_level(tctx, b, handle, 2, &info),
5713 "failed to query Printer level 2");
5715 torture_assert(tctx,
5716 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5717 "failed to convert");
5719 info_ctr.level = 2;
5720 info_ctr.info = sinfo;
5722 #define TEST_SZ(wname, iname) \
5723 do {\
5724 enum winreg_Type type;\
5725 uint8_t *data;\
5726 uint32_t needed;\
5727 DATA_BLOB blob;\
5728 const char *str;\
5729 torture_assert(tctx,\
5730 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5731 "failed to query");\
5732 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5733 blob = data_blob_const(data, needed);\
5734 torture_assert(tctx,\
5735 pull_reg_sz(tctx, &blob, &str),\
5736 "failed to pull REG_SZ");\
5737 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5738 } while(0);
5741 #define TEST_SET_SZ(wname, iname, val) \
5742 do {\
5743 enum winreg_Type type;\
5744 uint8_t *data;\
5745 uint32_t needed;\
5746 DATA_BLOB blob;\
5747 const char *str;\
5748 sinfo.info2->iname = val;\
5749 torture_assert(tctx,\
5750 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5751 "failed to call SetPrinter");\
5752 torture_assert(tctx,\
5753 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5754 "failed to query");\
5755 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5756 blob = data_blob_const(data, needed);\
5757 torture_assert(tctx,\
5758 pull_reg_sz(tctx, &blob, &str),\
5759 "failed to pull REG_SZ");\
5760 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5761 } while(0);
5763 #define TEST_SET_DWORD(wname, iname, val) \
5764 do {\
5765 enum winreg_Type type;\
5766 uint8_t *data;\
5767 uint32_t needed;\
5768 uint32_t value;\
5769 sinfo.info2->iname = val;\
5770 torture_assert(tctx,\
5771 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5772 "failed to call SetPrinter");\
5773 torture_assert(tctx,\
5774 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5775 "failed to query");\
5776 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5777 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5778 value = IVAL(data, 0); \
5779 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5780 } while(0);
5782 TEST_SET_SZ("description", comment, "newval");
5783 TEST_SET_SZ("location", location, "newval");
5784 TEST_SET_SZ("driverName", drivername, "newval");
5785 /* TEST_SET_DWORD("priority", priority, 25); */
5787 torture_assert(tctx,
5788 test_GetPrinter_level(tctx, b, handle, 2, &info),
5789 "failed to query Printer level 2");
5791 TEST_SZ("description", info.info2.comment);
5792 TEST_SZ("driverName", info.info2.drivername);
5793 TEST_SZ("location", info.info2.location);
5795 pname = strrchr(info.info2.printername, '\\');
5796 if (pname == NULL) {
5797 pname = info.info2.printername;
5798 } else {
5799 pname++;
5801 TEST_SZ("printerName", pname);
5802 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5803 /* TEST_SZ("printShareName", info.info2.sharename); */
5805 /* FIXME gd: complete the list */
5807 #undef TEST_SZ
5808 #undef TEST_SET_SZ
5809 #undef TEST_DWORD
5811 torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5813 return true;
5816 static bool test_print_processors_winreg(struct torture_context *tctx,
5817 void *private_data)
5819 struct test_spoolss_context *ctx =
5820 talloc_get_type_abort(private_data, struct test_spoolss_context);
5821 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5822 struct dcerpc_binding_handle *b = p->binding_handle;
5824 return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5827 static bool test_AddPrintProcessor(struct torture_context *tctx,
5828 struct dcerpc_binding_handle *b,
5829 const char *environment,
5830 const char *path_name,
5831 const char *print_processor_name,
5832 WERROR expected_error)
5834 struct spoolss_AddPrintProcessor r;
5836 r.in.server = NULL;
5837 r.in.architecture = environment;
5838 r.in.path_name = path_name;
5839 r.in.print_processor_name = print_processor_name;
5841 torture_comment(tctx, "Testing AddPrintProcessor(%s)\n",
5842 print_processor_name);
5844 torture_assert_ntstatus_ok(tctx,
5845 dcerpc_spoolss_AddPrintProcessor_r(b, tctx, &r),
5846 "spoolss_AddPrintProcessor failed");
5847 torture_assert_werr_equal(tctx, r.out.result, expected_error,
5848 "spoolss_AddPrintProcessor failed");
5850 return true;
5853 static bool test_DeletePrintProcessor(struct torture_context *tctx,
5854 struct dcerpc_binding_handle *b,
5855 const char *environment,
5856 const char *print_processor_name,
5857 WERROR expected_error)
5859 struct spoolss_DeletePrintProcessor r;
5861 r.in.server = NULL;
5862 r.in.architecture = environment;
5863 r.in.print_processor_name = print_processor_name;
5865 torture_comment(tctx, "Testing DeletePrintProcessor(%s)\n",
5866 print_processor_name);
5868 torture_assert_ntstatus_ok(tctx,
5869 dcerpc_spoolss_DeletePrintProcessor_r(b, tctx, &r),
5870 "spoolss_DeletePrintProcessor failed");
5871 torture_assert_werr_equal(tctx, r.out.result, expected_error,
5872 "spoolss_DeletePrintProcessor failed");
5874 return true;
5877 static bool test_add_print_processor(struct torture_context *tctx,
5878 void *private_data)
5880 struct test_spoolss_context *ctx =
5881 talloc_get_type_abort(private_data, struct test_spoolss_context);
5882 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5883 struct dcerpc_binding_handle *b = p->binding_handle;
5884 int i;
5886 struct {
5887 const char *environment;
5888 const char *path_name;
5889 const char *print_processor_name;
5890 WERROR expected_add_result;
5891 WERROR expected_del_result;
5892 } tests[] = {
5894 .environment = ctx->environment,
5895 .path_name = "",
5896 .print_processor_name = "winprint",
5897 .expected_add_result = WERR_PRINT_PROCESSOR_ALREADY_INSTALLED,
5898 .expected_del_result = WERR_CAN_NOT_COMPLETE
5900 .environment = ctx->environment,
5901 .path_name = "",
5902 .print_processor_name = "unknown",
5903 .expected_add_result = WERR_MOD_NOT_FOUND,
5904 .expected_del_result = WERR_UNKNOWN_PRINTPROCESSOR
5908 for (i=0; i < ARRAY_SIZE(tests); i++) {
5909 torture_assert(tctx,
5910 test_AddPrintProcessor(tctx, b,
5911 tests[i].environment,
5912 tests[i].path_name,
5913 tests[i].print_processor_name,
5914 tests[i].expected_add_result),
5915 "add print processor failed");
5916 torture_assert(tctx,
5917 test_DeletePrintProcessor(tctx, b,
5918 tests[i].environment,
5919 tests[i].print_processor_name,
5920 tests[i].expected_del_result),
5921 "delete print processor failed");
5924 return true;
5927 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5928 struct dcerpc_binding_handle *b,
5929 struct policy_handle *handle,
5930 uint32_t *change_id)
5932 enum winreg_Type type;
5933 uint8_t *data;
5934 uint32_t needed;
5936 torture_assert(tctx,
5937 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5938 "failed to call GetPrinterData");
5940 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5941 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5943 *change_id = IVAL(data, 0);
5945 return true;
5948 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5949 struct dcerpc_pipe *p,
5950 struct policy_handle *handle,
5951 uint32_t *change_id)
5953 enum winreg_Type type;
5954 uint8_t *data;
5955 uint32_t needed;
5957 torture_assert(tctx,
5958 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5959 "failed to call GetPrinterData");
5961 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5962 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5964 *change_id = IVAL(data, 0);
5966 return true;
5969 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5970 struct dcerpc_binding_handle *b,
5971 struct policy_handle *handle,
5972 uint32_t *change_id)
5974 union spoolss_PrinterInfo info;
5976 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5977 "failed to query Printer level 0");
5979 *change_id = info.info0.change_id;
5981 return true;
5984 static bool test_ChangeID(struct torture_context *tctx,
5985 struct dcerpc_pipe *p,
5986 struct policy_handle *handle)
5988 uint32_t change_id, change_id_ex, change_id_info;
5989 uint32_t change_id2, change_id_ex2, change_id_info2;
5990 union spoolss_PrinterInfo info;
5991 const char *comment;
5992 struct dcerpc_binding_handle *b = p->binding_handle;
5994 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5996 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5997 "failed to query for ChangeID");
5998 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5999 "failed to query for ChangeID");
6000 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6001 "failed to query for ChangeID");
6003 torture_assert_int_equal(tctx, change_id, change_id_ex,
6004 "change_ids should all be equal");
6005 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
6006 "change_ids should all be equal");
6009 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
6011 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6012 "failed to query for ChangeID");
6013 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
6014 "failed to query Printer level 2");
6015 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6016 "failed to query for ChangeID");
6017 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6018 "failed to query for ChangeID");
6019 torture_assert_int_equal(tctx, change_id, change_id_ex,
6020 "change_id should not have changed");
6021 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
6022 "change_id should not have changed");
6025 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
6027 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6028 "failed to query for ChangeID");
6029 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6030 "failed to query for ChangeID");
6031 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6032 "failed to query for ChangeID");
6033 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
6034 "failed to query Printer level 2");
6035 comment = talloc_strdup(tctx, info.info2.comment);
6038 struct spoolss_SetPrinterInfoCtr info_ctr;
6039 struct spoolss_DevmodeContainer devmode_ctr;
6040 struct sec_desc_buf secdesc_ctr;
6041 union spoolss_SetPrinterInfo sinfo;
6043 ZERO_STRUCT(info_ctr);
6044 ZERO_STRUCT(devmode_ctr);
6045 ZERO_STRUCT(secdesc_ctr);
6048 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
6049 sinfo.info2->comment = "torture_comment";
6051 info_ctr.level = 2;
6052 info_ctr.info = sinfo;
6054 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6055 "failed to call SetPrinter");
6057 sinfo.info2->comment = comment;
6059 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6060 "failed to call SetPrinter");
6064 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
6065 "failed to query for ChangeID");
6066 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
6067 "failed to query for ChangeID");
6068 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
6069 "failed to query for ChangeID");
6071 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
6072 "change_ids should all be equal");
6073 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
6074 "change_ids should all be equal");
6076 torture_assert(tctx, (change_id < change_id2),
6077 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6078 change_id2, change_id));
6079 torture_assert(tctx, (change_id_ex < change_id_ex2),
6080 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6081 change_id_ex2, change_id_ex));
6082 torture_assert(tctx, (change_id_info < change_id_info2),
6083 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6084 change_id_info2, change_id_info));
6086 torture_comment(tctx, "ChangeID tests succeeded\n\n");
6088 return true;
6091 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
6092 struct dcerpc_pipe *p,
6093 struct policy_handle *handle)
6095 NTSTATUS status;
6096 struct dcerpc_binding *b;
6097 struct dcerpc_pipe *p2;
6098 struct spoolss_ClosePrinter cp;
6100 /* only makes sense on SMB */
6101 if (p->conn->transport.transport != NCACN_NP) {
6102 return true;
6105 torture_comment(tctx, "Testing close on secondary pipe\n");
6107 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
6108 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
6110 status = dcerpc_secondary_connection(p, &p2, b);
6111 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
6113 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
6114 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
6116 cp.in.handle = handle;
6117 cp.out.handle = handle;
6119 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
6120 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
6121 "ERROR: Allowed close on secondary connection");
6123 talloc_free(p2);
6125 return true;
6128 static bool test_OpenPrinter_badname(struct torture_context *tctx,
6129 struct dcerpc_binding_handle *b, const char *name)
6131 NTSTATUS status;
6132 struct spoolss_OpenPrinter op;
6133 struct spoolss_OpenPrinterEx opEx;
6134 struct policy_handle handle;
6135 bool ret = true;
6137 op.in.printername = name;
6138 op.in.datatype = NULL;
6139 op.in.devmode_ctr.devmode= NULL;
6140 op.in.access_mask = 0;
6141 op.out.handle = &handle;
6143 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
6145 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
6146 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
6147 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
6148 "unexpected result");
6150 if (W_ERROR_IS_OK(op.out.result)) {
6151 ret &=test_ClosePrinter(tctx, b, &handle);
6154 opEx.in.printername = name;
6155 opEx.in.datatype = NULL;
6156 opEx.in.devmode_ctr.devmode = NULL;
6157 opEx.in.access_mask = 0;
6158 opEx.in.userlevel_ctr.level = 1;
6159 opEx.in.userlevel_ctr.user_info.level1 = NULL;
6160 opEx.out.handle = &handle;
6162 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
6164 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
6165 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
6166 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
6167 "unexpected result");
6169 if (W_ERROR_IS_OK(opEx.out.result)) {
6170 ret &=test_ClosePrinter(tctx, b, &handle);
6173 return ret;
6176 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
6177 void *private_data)
6179 struct test_spoolss_context *ctx =
6180 talloc_get_type_abort(private_data, struct test_spoolss_context);
6182 const char *badnames[] = {
6183 "__INVALID_PRINTER__",
6184 "\\\\__INVALID_HOST__",
6186 "\\\\\\",
6187 "\\\\\\__INVALID_PRINTER__"
6189 const char *badname;
6190 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6191 const char *server_name = dcerpc_server_name(p);
6192 struct dcerpc_binding_handle *b = p->binding_handle;
6193 int i;
6195 for (i=0; i < ARRAY_SIZE(badnames); i++) {
6196 torture_assert(tctx,
6197 test_OpenPrinter_badname(tctx, b, badnames[i]),
6198 "");
6201 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
6202 torture_assert(tctx,
6203 test_OpenPrinter_badname(tctx, b, badname),
6204 "");
6206 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
6207 torture_assert(tctx,
6208 test_OpenPrinter_badname(tctx, b, badname),
6209 "");
6211 return true;
6214 static bool test_OpenPrinter(struct torture_context *tctx,
6215 struct dcerpc_pipe *p,
6216 const char *name,
6217 const char *environment,
6218 bool open_only)
6220 NTSTATUS status;
6221 struct spoolss_OpenPrinter r;
6222 struct policy_handle handle;
6223 bool ret = true;
6224 struct dcerpc_binding_handle *b = p->binding_handle;
6226 r.in.printername = name;
6227 r.in.datatype = NULL;
6228 r.in.devmode_ctr.devmode= NULL;
6229 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6230 r.out.handle = &handle;
6232 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
6234 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
6236 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
6238 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
6240 if (open_only) {
6241 goto close_printer;
6244 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6245 ret = false;
6248 if (!torture_setting_bool(tctx, "samba3", false)) {
6249 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6250 ret = false;
6254 close_printer:
6255 if (!test_ClosePrinter(tctx, b, &handle)) {
6256 ret = false;
6259 return ret;
6262 static bool test_OpenPrinterEx(struct torture_context *tctx,
6263 struct dcerpc_binding_handle *b,
6264 const char *printername,
6265 const char *datatype,
6266 struct spoolss_DeviceMode *devmode,
6267 uint32_t access_mask,
6268 struct spoolss_UserLevelCtr *userlevel_ctr,
6269 struct policy_handle *handle,
6270 WERROR expected_result)
6272 struct spoolss_OpenPrinterEx r;
6274 r.in.printername = printername;
6275 r.in.datatype = datatype;
6276 r.in.devmode_ctr.devmode= devmode;
6277 r.in.access_mask = access_mask;
6278 r.in.userlevel_ctr = *userlevel_ctr;
6279 r.out.handle = handle;
6281 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
6283 torture_assert_ntstatus_ok(tctx,
6284 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
6285 "OpenPrinterEx failed");
6287 torture_assert_werr_equal(tctx, r.out.result, expected_result,
6288 "OpenPrinterEx failed");
6290 return true;
6293 static bool call_OpenPrinterEx(struct torture_context *tctx,
6294 struct dcerpc_pipe *p,
6295 const char *name,
6296 struct spoolss_DeviceMode *devmode,
6297 struct policy_handle *handle)
6299 struct spoolss_UserLevelCtr userlevel_ctr;
6300 struct spoolss_UserLevel1 userlevel1;
6301 struct dcerpc_binding_handle *b = p->binding_handle;
6303 userlevel1.size = 1234;
6304 userlevel1.client = "hello";
6305 userlevel1.user = "spottyfoot!";
6306 userlevel1.build = 1;
6307 userlevel1.major = 2;
6308 userlevel1.minor = 3;
6309 userlevel1.processor = 4;
6311 userlevel_ctr.level = 1;
6312 userlevel_ctr.user_info.level1 = &userlevel1;
6314 return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
6315 SEC_FLAG_MAXIMUM_ALLOWED,
6316 &userlevel_ctr,
6317 handle,
6318 WERR_OK);
6321 static bool test_printer_rename(struct torture_context *tctx,
6322 void *private_data)
6324 struct torture_printer_context *t =
6325 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6326 struct dcerpc_pipe *p = t->spoolss_pipe;
6328 bool ret = true;
6329 union spoolss_PrinterInfo info;
6330 union spoolss_SetPrinterInfo sinfo;
6331 struct spoolss_SetPrinterInfoCtr info_ctr;
6332 struct spoolss_DevmodeContainer devmode_ctr;
6333 struct sec_desc_buf secdesc_ctr;
6334 const char *printer_name;
6335 const char *printer_name_orig;
6336 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
6337 struct policy_handle new_handle;
6338 const char *q;
6339 struct dcerpc_binding_handle *b = p->binding_handle;
6341 ZERO_STRUCT(devmode_ctr);
6342 ZERO_STRUCT(secdesc_ctr);
6344 torture_comment(tctx, "Testing Printer rename operations\n");
6346 torture_assert(tctx,
6347 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
6348 "failed to call GetPrinter level 2");
6350 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
6352 q = strrchr(info.info2.printername, '\\');
6353 if (q) {
6354 torture_warning(tctx,
6355 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6358 torture_assert(tctx,
6359 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
6361 sinfo.info2->printername = printer_name_new;
6363 info_ctr.level = 2;
6364 info_ctr.info = sinfo;
6366 torture_assert(tctx,
6367 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6368 "failed to call SetPrinter level 2");
6370 torture_assert(tctx,
6371 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
6372 "failed to call GetPrinter level 2");
6374 printer_name = talloc_strdup(tctx, info.info2.printername);
6376 q = strrchr(info.info2.printername, '\\');
6377 if (q) {
6378 torture_warning(tctx,
6379 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6380 q++;
6381 printer_name = q;
6384 torture_assert_str_equal(tctx, printer_name, printer_name_new,
6385 "new printer name was not set");
6387 /* samba currently cannot fully rename printers */
6388 if (!torture_setting_bool(tctx, "samba3", false)) {
6389 torture_assert(tctx,
6390 test_OpenPrinter_badname(tctx, b, printer_name_orig),
6391 "still can open printer with oldname after rename");
6392 } else {
6393 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
6396 torture_assert(tctx,
6397 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
6398 "failed to open printer with new name");
6400 torture_assert(tctx,
6401 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
6402 "failed to call GetPrinter level 2");
6404 torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
6405 "new printer name was not set");
6407 torture_assert(tctx,
6408 test_ClosePrinter(tctx, b, &new_handle),
6409 "failed to close printer");
6411 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
6413 return ret;
6416 static bool test_openprinter(struct torture_context *tctx,
6417 struct dcerpc_binding_handle *b,
6418 const char *real_printername)
6420 struct spoolss_UserLevelCtr userlevel_ctr;
6421 struct policy_handle handle;
6422 struct spoolss_UserLevel1 userlevel1;
6423 const char *printername = NULL;
6424 int i;
6426 struct {
6427 const char *suffix;
6428 WERROR expected_result;
6429 } tests[] = {
6431 .suffix = "rubbish",
6432 .expected_result = WERR_INVALID_PRINTER_NAME
6434 .suffix = ", LocalOnl",
6435 .expected_result = WERR_INVALID_PRINTER_NAME
6437 .suffix = ", localOnly",
6438 .expected_result = WERR_INVALID_PRINTER_NAME
6440 .suffix = ", localonl",
6441 .expected_result = WERR_INVALID_PRINTER_NAME
6443 .suffix = ",LocalOnl",
6444 .expected_result = WERR_INVALID_PRINTER_NAME
6446 .suffix = ",localOnl2",
6447 .expected_result = WERR_INVALID_PRINTER_NAME
6449 .suffix = ", DrvConver2t",
6450 .expected_result = WERR_INVALID_PRINTER_NAME
6452 .suffix = ", drvconvert",
6453 .expected_result = WERR_INVALID_PRINTER_NAME
6455 .suffix = ",drvconvert",
6456 .expected_result = WERR_INVALID_PRINTER_NAME
6458 .suffix = ", DrvConvert",
6459 .expected_result = WERR_OK
6461 .suffix = " , DrvConvert",
6462 .expected_result = WERR_INVALID_PRINTER_NAME
6464 .suffix = ",DrvConvert",
6465 .expected_result = WERR_OK
6467 .suffix = ", DrvConvertsadfasdf",
6468 .expected_result = WERR_OK
6470 .suffix = ",DrvConvertasdfasd",
6471 .expected_result = WERR_OK
6473 .suffix = ", LocalOnly",
6474 .expected_result = WERR_OK
6476 .suffix = " , LocalOnly",
6477 .expected_result = WERR_INVALID_PRINTER_NAME
6479 .suffix = ",LocalOnly",
6480 .expected_result = WERR_OK
6482 .suffix = ", LocalOnlysagi4gjfkd",
6483 .expected_result = WERR_OK
6485 .suffix = ",LocalOnlysagi4gjfkd",
6486 .expected_result = WERR_OK
6490 userlevel1.size = 1234;
6491 userlevel1.client = "hello";
6492 userlevel1.user = "spottyfoot!";
6493 userlevel1.build = 1;
6494 userlevel1.major = 2;
6495 userlevel1.minor = 3;
6496 userlevel1.processor = 4;
6498 userlevel_ctr.level = 1;
6499 userlevel_ctr.user_info.level1 = &userlevel1;
6501 torture_comment(tctx, "Testing openprinterex printername pattern\n");
6503 torture_assert(tctx,
6504 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0,
6505 &userlevel_ctr, &handle,
6506 WERR_OK),
6507 "OpenPrinterEx failed");
6508 test_ClosePrinter(tctx, b, &handle);
6510 for (i=0; i < ARRAY_SIZE(tests); i++) {
6512 printername = talloc_asprintf(tctx, "%s%s",
6513 real_printername,
6514 tests[i].suffix);
6516 torture_assert(tctx,
6517 test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0,
6518 &userlevel_ctr, &handle,
6519 tests[i].expected_result),
6520 "OpenPrinterEx failed");
6521 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6522 test_ClosePrinter(tctx, b, &handle);
6526 return true;
6530 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6531 struct dcerpc_pipe *p,
6532 const char *name,
6533 const char *environment)
6535 struct policy_handle handle;
6536 bool ret = true;
6537 struct dcerpc_binding_handle *b = p->binding_handle;
6539 if (!test_openprinter(tctx, b, name)) {
6540 return false;
6543 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6544 return false;
6547 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6548 ret = false;
6551 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6552 ret = false;
6555 if (!test_EnumForms_all(tctx, b, &handle, false)) {
6556 ret = false;
6559 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6560 ret = false;
6563 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6564 ret = false;
6567 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6568 ret = false;
6571 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6572 ret = false;
6575 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6576 ret = false;
6579 if (!test_printer_all_keys(tctx, b, &handle)) {
6580 ret = false;
6583 if (!test_PausePrinter(tctx, b, &handle)) {
6584 ret = false;
6587 if (!test_DoPrintTest(tctx, b, &handle)) {
6588 ret = false;
6591 if (!test_ResumePrinter(tctx, b, &handle)) {
6592 ret = false;
6595 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
6596 ret = false;
6599 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
6600 ret = false;
6603 if (!torture_setting_bool(tctx, "samba3", false)) {
6604 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6605 ret = false;
6609 if (!test_ClosePrinter(tctx, b, &handle)) {
6610 ret = false;
6613 return ret;
6616 static bool test_EnumPrinters_old(struct torture_context *tctx,
6617 void *private_data)
6619 struct test_spoolss_context *ctx =
6620 talloc_get_type_abort(private_data, struct test_spoolss_context);
6621 struct spoolss_EnumPrinters r;
6622 NTSTATUS status;
6623 uint16_t levels[] = {1, 2, 4, 5};
6624 int i;
6625 bool ret = true;
6626 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6627 struct dcerpc_binding_handle *b = p->binding_handle;
6629 for (i=0;i<ARRAY_SIZE(levels);i++) {
6630 union spoolss_PrinterInfo *info;
6631 int j;
6632 uint32_t needed;
6633 uint32_t count;
6635 r.in.flags = PRINTER_ENUM_LOCAL;
6636 r.in.server = "";
6637 r.in.level = levels[i];
6638 r.in.buffer = NULL;
6639 r.in.offered = 0;
6640 r.out.needed = &needed;
6641 r.out.count = &count;
6642 r.out.info = &info;
6644 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6646 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6647 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6649 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6650 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6651 r.in.buffer = &blob;
6652 r.in.offered = needed;
6653 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6656 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6658 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6660 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6662 if (!info) {
6663 torture_comment(tctx, "No printers returned\n");
6664 return true;
6667 for (j=0;j<count;j++) {
6668 if (r.in.level == 1) {
6669 char *unc = talloc_strdup(tctx, info[j].info1.name);
6670 char *slash, *name, *full_name;
6671 name = unc;
6672 if (unc[0] == '\\' && unc[1] == '\\') {
6673 unc +=2;
6675 slash = strchr(unc, '\\');
6676 if (slash) {
6677 slash++;
6678 name = slash;
6680 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6681 dcerpc_server_name(p), name);
6682 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6683 ret = false;
6685 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6686 ret = false;
6688 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6689 ret = false;
6691 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6692 ret = false;
6698 return ret;
6701 static bool test_EnumPrinters_level(struct torture_context *tctx,
6702 struct dcerpc_binding_handle *b,
6703 uint32_t flags,
6704 const char *servername,
6705 uint32_t level,
6706 uint32_t *count_p,
6707 union spoolss_PrinterInfo **info_p)
6709 struct spoolss_EnumPrinters r;
6710 union spoolss_PrinterInfo *info;
6711 uint32_t needed;
6712 uint32_t count;
6714 r.in.flags = flags;
6715 r.in.server = servername;
6716 r.in.level = level;
6717 r.in.buffer = NULL;
6718 r.in.offered = 0;
6719 r.out.needed = &needed;
6720 r.out.count = &count;
6721 r.out.info = &info;
6723 torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6724 r.in.server, r.in.level);
6726 torture_assert_ntstatus_ok(tctx,
6727 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6728 "EnumPrinters failed");
6729 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6730 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6731 r.in.buffer = &blob;
6732 r.in.offered = needed;
6733 torture_assert_ntstatus_ok(tctx,
6734 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6735 "EnumPrinters failed");
6738 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6740 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6742 if (count_p) {
6743 *count_p = count;
6745 if (info_p) {
6746 *info_p = info;
6749 return true;
6752 static const char *get_short_printername(struct torture_context *tctx,
6753 const char *name)
6755 const char *short_name;
6757 if (name[0] == '\\' && name[1] == '\\') {
6758 name += 2;
6759 short_name = strchr(name, '\\');
6760 if (short_name) {
6761 return talloc_strdup(tctx, short_name+1);
6765 return name;
6768 static const char *get_full_printername(struct torture_context *tctx,
6769 const char *name)
6771 const char *full_name = talloc_strdup(tctx, name);
6772 char *p;
6774 if (name && name[0] == '\\' && name[1] == '\\') {
6775 name += 2;
6776 p = strchr(name, '\\');
6777 if (p) {
6778 return full_name;
6782 return NULL;
6785 static bool test_OnePrinter_servername(struct torture_context *tctx,
6786 struct dcerpc_pipe *p,
6787 struct dcerpc_binding_handle *b,
6788 const char *servername,
6789 const char *printername)
6791 union spoolss_PrinterInfo info;
6792 const char *short_name = get_short_printername(tctx, printername);
6793 const char *full_name = get_full_printername(tctx, printername);
6795 if (short_name) {
6796 struct policy_handle handle;
6797 torture_assert(tctx,
6798 call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
6799 "failed to open printer");
6801 torture_assert(tctx,
6802 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6803 "failed to get printer info");
6805 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
6806 "unexpected servername");
6807 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
6808 "unexpected printername");
6810 if (info.info2.devmode) {
6811 const char *expected_devicename;
6812 expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
6813 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6814 "unexpected devicemode devicename");
6817 torture_assert(tctx,
6818 test_ClosePrinter(tctx, b, &handle),
6819 "failed to close printer");
6822 if (full_name) {
6823 struct policy_handle handle;
6825 torture_assert(tctx,
6826 call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
6827 "failed to open printer");
6829 torture_assert(tctx,
6830 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6831 "failed to get printer info");
6833 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
6834 "unexpected servername");
6835 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
6836 "unexpected printername");
6838 if (info.info2.devmode) {
6839 const char *expected_devicename;
6840 expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
6841 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6842 "unexpected devicemode devicename");
6845 torture_assert(tctx,
6846 test_ClosePrinter(tctx, b, &handle),
6847 "failed to close printer");
6850 return true;
6853 static bool test_EnumPrinters_servername(struct torture_context *tctx,
6854 void *private_data)
6856 struct test_spoolss_context *ctx =
6857 talloc_get_type_abort(private_data, struct test_spoolss_context);
6858 int i;
6859 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6860 struct dcerpc_binding_handle *b = p->binding_handle;
6861 uint32_t count;
6862 union spoolss_PrinterInfo *info;
6863 const char *servername;
6864 uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
6866 torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6868 servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6870 torture_assert(tctx,
6871 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6872 "failed to enumerate printers");
6874 for (i=0; i < count; i++) {
6876 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
6877 "unexpected servername");
6879 torture_assert(tctx,
6880 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6881 "failed to check printer");
6884 servername = "";
6886 torture_assert(tctx,
6887 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6888 "failed to enumerate printers");
6890 for (i=0; i < count; i++) {
6892 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
6893 "unexpected servername");
6895 torture_assert(tctx,
6896 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6897 "failed to check printer");
6901 return true;
6905 static bool test_GetPrinterDriver(struct torture_context *tctx,
6906 struct dcerpc_binding_handle *b,
6907 struct policy_handle *handle,
6908 const char *driver_name)
6910 struct spoolss_GetPrinterDriver r;
6911 uint32_t needed;
6913 r.in.handle = handle;
6914 r.in.architecture = "W32X86";
6915 r.in.level = 1;
6916 r.in.buffer = NULL;
6917 r.in.offered = 0;
6918 r.out.needed = &needed;
6920 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
6922 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6923 "failed to call GetPrinterDriver");
6924 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6925 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6926 r.in.buffer = &blob;
6927 r.in.offered = needed;
6928 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6929 "failed to call GetPrinterDriver");
6932 torture_assert_werr_ok(tctx, r.out.result,
6933 "failed to call GetPrinterDriver");
6935 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6937 return true;
6940 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
6941 struct dcerpc_binding_handle *b,
6942 struct policy_handle *handle,
6943 const char *driver_name,
6944 const char *architecture,
6945 uint32_t level,
6946 uint32_t client_major_version,
6947 uint32_t client_minor_version,
6948 union spoolss_DriverInfo *info_p,
6949 WERROR *result_p)
6952 struct spoolss_GetPrinterDriver2 r;
6953 uint32_t needed;
6954 uint32_t server_major_version;
6955 uint32_t server_minor_version;
6957 r.in.handle = handle;
6958 r.in.architecture = architecture;
6959 r.in.client_major_version = client_major_version;
6960 r.in.client_minor_version = client_minor_version;
6961 r.in.buffer = NULL;
6962 r.in.offered = 0;
6963 r.in.level = level;
6964 r.out.needed = &needed;
6965 r.out.server_major_version = &server_major_version;
6966 r.out.server_minor_version = &server_minor_version;
6968 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
6969 driver_name, r.in.level);
6971 torture_assert_ntstatus_ok(tctx,
6972 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6973 "failed to call GetPrinterDriver2");
6974 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6975 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6976 r.in.buffer = &blob;
6977 r.in.offered = needed;
6978 torture_assert_ntstatus_ok(tctx,
6979 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6980 "failed to call GetPrinterDriver2");
6983 if (result_p) {
6984 *result_p = r.out.result;
6987 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
6988 switch (r.in.level) {
6989 case 101:
6990 case 8:
6991 torture_comment(tctx,
6992 "level %d not implemented, not considering as an error\n",
6993 r.in.level);
6994 return true;
6995 default:
6996 break;
7000 torture_assert_werr_ok(tctx, r.out.result,
7001 "failed to call GetPrinterDriver2");
7003 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
7005 if (info_p) {
7006 *info_p = *r.out.info;
7009 return true;
7012 static bool test_GetPrinterDriver2(struct torture_context *tctx,
7013 struct dcerpc_binding_handle *b,
7014 struct policy_handle *handle,
7015 const char *driver_name,
7016 const char *architecture)
7018 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
7019 int i;
7022 for (i=0;i<ARRAY_SIZE(levels);i++) {
7024 torture_assert(tctx,
7025 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
7026 "");
7029 return true;
7032 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
7033 void *private_data)
7035 struct test_spoolss_context *ctx =
7036 talloc_get_type_abort(private_data, struct test_spoolss_context);
7037 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
7038 int i;
7039 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7040 struct dcerpc_binding_handle *b = p->binding_handle;
7041 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7043 for (i=0;i<ARRAY_SIZE(levels);i++) {
7045 uint32_t count;
7046 union spoolss_DriverInfo *info;
7048 torture_assert(tctx,
7049 test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
7050 "failed to enumerate drivers");
7052 if (!info) {
7053 torture_comment(tctx, "No printer drivers returned\n");
7054 break;
7058 return true;
7061 static bool test_DeletePrinter(struct torture_context *tctx,
7062 struct dcerpc_binding_handle *b,
7063 struct policy_handle *handle)
7065 struct spoolss_DeletePrinter r;
7067 torture_comment(tctx, "Testing DeletePrinter\n");
7069 r.in.handle = handle;
7071 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
7072 "failed to delete printer");
7073 torture_assert_werr_ok(tctx, r.out.result,
7074 "failed to delete printer");
7076 return true;
7079 static bool test_EnumPrinters_findname(struct torture_context *tctx,
7080 struct dcerpc_binding_handle *b,
7081 uint32_t flags,
7082 uint32_t level,
7083 const char *name,
7084 bool *found)
7086 struct spoolss_EnumPrinters e;
7087 uint32_t count;
7088 union spoolss_PrinterInfo *info;
7089 uint32_t needed;
7090 int i;
7092 *found = false;
7094 e.in.flags = flags;
7095 e.in.server = NULL;
7096 e.in.level = level;
7097 e.in.buffer = NULL;
7098 e.in.offered = 0;
7099 e.out.count = &count;
7100 e.out.info = &info;
7101 e.out.needed = &needed;
7103 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
7104 "failed to enum printers");
7106 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
7107 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7108 e.in.buffer = &blob;
7109 e.in.offered = needed;
7111 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
7112 "failed to enum printers");
7115 torture_assert_werr_ok(tctx, e.out.result,
7116 "failed to enum printers");
7118 for (i=0; i < count; i++) {
7120 const char *current = NULL;
7121 const char *q;
7123 switch (level) {
7124 case 1:
7125 current = info[i].info1.name;
7126 break;
7129 if (strequal(current, name)) {
7130 *found = true;
7131 break;
7134 q = strrchr(current, '\\');
7135 if (q) {
7136 if (!e.in.server) {
7137 torture_warning(tctx,
7138 "server returns printername %s incl. servername although we did not set servername", current);
7140 q++;
7141 if (strequal(q, name)) {
7142 *found = true;
7143 break;
7148 return true;
7151 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
7152 struct dcerpc_pipe *p,
7153 const char *printername,
7154 bool ex)
7156 WERROR result;
7157 struct spoolss_AddPrinter r;
7158 struct spoolss_AddPrinterEx rex;
7159 struct spoolss_SetPrinterInfoCtr info_ctr;
7160 struct spoolss_SetPrinterInfo1 info1;
7161 struct spoolss_DevmodeContainer devmode_ctr;
7162 struct sec_desc_buf secdesc_ctr;
7163 struct spoolss_UserLevelCtr userlevel_ctr;
7164 struct policy_handle handle;
7165 bool found = false;
7166 struct dcerpc_binding_handle *b = p->binding_handle;
7168 ZERO_STRUCT(devmode_ctr);
7169 ZERO_STRUCT(secdesc_ctr);
7170 ZERO_STRUCT(userlevel_ctr);
7171 ZERO_STRUCT(info1);
7173 torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
7174 ex ? "Ex":"", printername);
7176 /* try to add printer to wellknown printer list (level 1) */
7178 userlevel_ctr.level = 1;
7180 info_ctr.info.info1 = &info1;
7181 info_ctr.level = 1;
7183 rex.in.server = NULL;
7184 rex.in.info_ctr = &info_ctr;
7185 rex.in.devmode_ctr = &devmode_ctr;
7186 rex.in.secdesc_ctr = &secdesc_ctr;
7187 rex.in.userlevel_ctr = &userlevel_ctr;
7188 rex.out.handle = &handle;
7190 r.in.server = NULL;
7191 r.in.info_ctr = &info_ctr;
7192 r.in.devmode_ctr = &devmode_ctr;
7193 r.in.secdesc_ctr = &secdesc_ctr;
7194 r.out.handle = &handle;
7196 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7197 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7198 "failed to add printer");
7199 result = ex ? rex.out.result : r.out.result;
7200 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
7201 "unexpected result code");
7203 info1.name = printername;
7204 info1.flags = PRINTER_ATTRIBUTE_SHARED;
7206 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7207 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7208 "failed to add printer");
7209 result = ex ? rex.out.result : r.out.result;
7210 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7211 "unexpected result code");
7213 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7214 better do a real check to see the printer is really there */
7216 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7217 PRINTER_ENUM_NETWORK, 1,
7218 printername,
7219 &found),
7220 "failed to enum printers");
7222 torture_assert(tctx, found, "failed to find newly added printer");
7224 info1.flags = 0;
7226 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7227 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7228 "failed to add printer");
7229 result = ex ? rex.out.result : r.out.result;
7230 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7231 "unexpected result code");
7233 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7234 better do a real check to see the printer has really been removed
7235 from the well known printer list */
7237 found = false;
7239 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7240 PRINTER_ENUM_NETWORK, 1,
7241 printername,
7242 &found),
7243 "failed to enum printers");
7244 #if 0
7245 torture_assert(tctx, !found, "printer still in well known printer list");
7246 #endif
7247 return true;
7250 static bool test_AddPrinter_normal(struct torture_context *tctx,
7251 struct dcerpc_pipe *p,
7252 struct policy_handle *handle_p,
7253 const char *printername,
7254 const char *drivername,
7255 const char *portname,
7256 struct spoolss_DeviceMode *devmode,
7257 bool ex)
7259 WERROR result;
7260 struct spoolss_AddPrinter r;
7261 struct spoolss_AddPrinterEx rex;
7262 struct spoolss_SetPrinterInfoCtr info_ctr;
7263 struct spoolss_SetPrinterInfo2 info2;
7264 struct spoolss_DevmodeContainer devmode_ctr;
7265 struct sec_desc_buf secdesc_ctr;
7266 struct spoolss_UserLevelCtr userlevel_ctr;
7267 struct policy_handle handle;
7268 bool found = false;
7269 bool existing_printer_deleted = false;
7270 struct dcerpc_binding_handle *b = p->binding_handle;
7272 ZERO_STRUCT(devmode_ctr);
7273 ZERO_STRUCT(secdesc_ctr);
7274 ZERO_STRUCT(userlevel_ctr);
7276 torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
7277 ex ? "Ex":"", printername);
7279 devmode_ctr.devmode = devmode;
7281 userlevel_ctr.level = 1;
7283 rex.in.server = NULL;
7284 rex.in.info_ctr = &info_ctr;
7285 rex.in.devmode_ctr = &devmode_ctr;
7286 rex.in.secdesc_ctr = &secdesc_ctr;
7287 rex.in.userlevel_ctr = &userlevel_ctr;
7288 rex.out.handle = &handle;
7290 r.in.server = NULL;
7291 r.in.info_ctr = &info_ctr;
7292 r.in.devmode_ctr = &devmode_ctr;
7293 r.in.secdesc_ctr = &secdesc_ctr;
7294 r.out.handle = &handle;
7296 again:
7298 /* try to add printer to printer list (level 2) */
7300 ZERO_STRUCT(info2);
7302 info_ctr.info.info2 = &info2;
7303 info_ctr.level = 2;
7305 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7306 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7307 "failed to add printer");
7308 result = ex ? rex.out.result : r.out.result;
7309 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
7310 "unexpected result code");
7312 info2.printername = printername;
7314 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7315 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7316 "failed to add printer");
7317 result = ex ? rex.out.result : r.out.result;
7319 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
7320 struct policy_handle printer_handle;
7322 if (existing_printer_deleted) {
7323 torture_fail(tctx, "already deleted printer still existing?");
7326 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
7327 "failed to open printer handle");
7329 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
7330 "failed to delete printer");
7332 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
7333 "failed to close server handle");
7335 existing_printer_deleted = true;
7337 goto again;
7340 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
7341 "unexpected result code");
7343 info2.portname = portname;
7345 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7346 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7347 "failed to add printer");
7348 result = ex ? rex.out.result : r.out.result;
7349 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
7350 "unexpected result code");
7352 info2.drivername = drivername;
7354 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7355 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7356 "failed to add printer");
7357 result = ex ? rex.out.result : r.out.result;
7359 /* w2k8r2 allows to add printer w/o defining printprocessor */
7361 if (!W_ERROR_IS_OK(result)) {
7362 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
7363 "unexpected result code");
7365 info2.printprocessor = "winprint";
7367 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7368 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7369 "failed to add printer");
7370 result = ex ? rex.out.result : r.out.result;
7371 torture_assert_werr_ok(tctx, result,
7372 "failed to add printer");
7375 *handle_p = handle;
7377 /* we are paranoid, really check if the printer is there now */
7379 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7380 PRINTER_ENUM_LOCAL, 1,
7381 printername,
7382 &found),
7383 "failed to enum printers");
7384 torture_assert(tctx, found, "failed to find newly added printer");
7386 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7387 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7388 "failed to add printer");
7389 result = ex ? rex.out.result : r.out.result;
7390 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7391 "unexpected result code");
7393 return true;
7396 static bool test_printer_info(struct torture_context *tctx,
7397 void *private_data)
7399 struct torture_printer_context *t =
7400 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7401 struct dcerpc_pipe *p = t->spoolss_pipe;
7402 struct dcerpc_binding_handle *b = p->binding_handle;
7404 bool ret = true;
7406 if (torture_setting_bool(tctx, "samba3", false)) {
7407 torture_skip(tctx, "skipping printer info cross tests against samba 3");
7410 if (!test_PrinterInfo(tctx, b, &t->handle)) {
7411 ret = false;
7414 if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
7415 ret = false;
7418 return ret;
7421 static bool test_EnumPrinterKey(struct torture_context *tctx,
7422 struct dcerpc_binding_handle *b,
7423 struct policy_handle *handle,
7424 const char *key_name,
7425 const char ***array)
7427 struct spoolss_EnumPrinterKey r;
7428 uint32_t needed = 0;
7429 union spoolss_KeyNames key_buffer;
7430 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7431 uint32_t _ndr_size;
7432 int i;
7434 r.in.handle = handle;
7435 r.in.key_name = key_name;
7436 r.out.key_buffer = &key_buffer;
7437 r.out.needed = &needed;
7438 r.out._ndr_size = &_ndr_size;
7440 for (i=0; i < ARRAY_SIZE(offered); i++) {
7442 if (offered[i] < 0 && needed) {
7443 if (needed <= 4) {
7444 continue;
7446 r.in.offered = needed + offered[i];
7447 } else {
7448 r.in.offered = offered[i];
7451 ZERO_STRUCT(key_buffer);
7453 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
7455 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7456 "failed to call EnumPrinterKey");
7457 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
7459 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7460 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7461 _ndr_size, r.in.offered/2));
7463 r.in.offered = needed;
7464 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7465 "failed to call EnumPrinterKey");
7468 if (offered[i] > 0) {
7469 torture_assert_werr_ok(tctx, r.out.result,
7470 "failed to call EnumPrinterKey");
7473 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7474 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7475 _ndr_size, r.in.offered/2));
7477 torture_assert(tctx, (*r.out.needed <= r.in.offered),
7478 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
7480 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
7481 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
7483 if (key_buffer.string_array) {
7484 uint32_t calc_needed = 0;
7485 int s;
7486 for (s=0; key_buffer.string_array[s]; s++) {
7487 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7489 if (!key_buffer.string_array[0]) {
7490 calc_needed += 2;
7492 calc_needed += 2;
7494 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7495 "EnumPrinterKey unexpected size");
7499 if (array) {
7500 *array = key_buffer.string_array;
7503 return true;
7506 bool test_printer_all_keys(struct torture_context *tctx,
7507 struct dcerpc_binding_handle *b,
7508 struct policy_handle *handle)
7510 const char **key_array = NULL;
7511 int i;
7513 torture_comment(tctx, "Testing Printer Keys\n");
7515 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7516 "failed to call test_EnumPrinterKey");
7518 for (i=0; key_array && key_array[i]; i++) {
7519 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7520 "failed to call test_EnumPrinterKey");
7522 for (i=0; key_array && key_array[i]; i++) {
7523 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7524 "failed to call test_EnumPrinterDataEx");
7527 torture_comment(tctx, "Printer Keys test succeeded\n\n");
7529 return true;
7532 static bool test_openprinter_wrap(struct torture_context *tctx,
7533 void *private_data)
7535 struct torture_printer_context *t =
7536 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7537 struct dcerpc_pipe *p = t->spoolss_pipe;
7538 struct dcerpc_binding_handle *b = p->binding_handle;
7539 const char *printername = t->info2.printername;
7541 return test_openprinter(tctx, b, printername);
7544 static bool test_csetprinter(struct torture_context *tctx,
7545 void *private_data)
7547 struct torture_printer_context *t =
7548 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7549 struct dcerpc_pipe *p = t->spoolss_pipe;
7551 const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7552 const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7553 const char *portname = t->info2.portname;
7555 union spoolss_PrinterInfo info;
7556 struct policy_handle new_handle, new_handle2;
7557 struct dcerpc_binding_handle *b = p->binding_handle;
7559 torture_comment(tctx, "Testing c_setprinter\n");
7561 torture_assert(tctx,
7562 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7563 "failed to get level 0 printer info");
7564 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7565 info.info0.c_setprinter);
7567 /* check if c_setprinter on 1st handle increases after a printer has
7568 * been added */
7570 torture_assert(tctx,
7571 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7572 "failed to add new printer");
7573 torture_assert(tctx,
7574 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7575 "failed to get level 0 printer info");
7576 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7577 info.info0.c_setprinter);
7579 /* check if c_setprinter on new handle increases after a printer has
7580 * been added */
7582 torture_assert(tctx,
7583 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7584 "failed to get level 0 printer info");
7585 torture_comment(tctx, "csetprinter on created handle: %d\n",
7586 info.info0.c_setprinter);
7588 /* open the new printer and check if c_setprinter increases */
7590 torture_assert(tctx,
7591 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7592 "failed to open created printer");
7593 torture_assert(tctx,
7594 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
7595 "failed to get level 0 printer info");
7596 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
7597 info.info0.c_setprinter);
7599 /* cleanup */
7601 torture_assert(tctx,
7602 test_ClosePrinter(tctx, b, &new_handle2),
7603 "failed to close printer");
7604 torture_assert(tctx,
7605 test_DeletePrinter(tctx, b, &new_handle),
7606 "failed to delete new printer");
7608 return true;
7611 static bool compose_local_driver_directory(struct torture_context *tctx,
7612 const char *environment,
7613 const char *local_dir,
7614 const char **path)
7616 char *p;
7618 p = strrchr(local_dir, '/');
7619 if (!p) {
7620 return NULL;
7622 p++;
7624 if (strequal(environment, "Windows x64")) {
7625 if (!strequal(p, "x64")) {
7626 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
7628 } else if (strequal(environment, "Windows NT x86")) {
7629 if (!strequal(p, "i386")) {
7630 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
7632 } else {
7633 torture_assert(tctx, "unknown environment: '%s'\n", environment);
7636 return true;
7639 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
7640 const char *devicename)
7642 struct spoolss_DeviceMode *r;
7644 r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
7645 if (r == NULL) {
7646 return NULL;
7649 r->devicename = talloc_strdup(r, devicename);
7650 r->specversion = DMSPEC_NT4_AND_ABOVE;
7651 r->driverversion = 0x0600;
7652 r->size = 0x00dc;
7653 r->__driverextra_length = 0;
7654 r->fields = DEVMODE_FORMNAME |
7655 DEVMODE_TTOPTION |
7656 DEVMODE_PRINTQUALITY |
7657 DEVMODE_DEFAULTSOURCE |
7658 DEVMODE_COPIES |
7659 DEVMODE_SCALE |
7660 DEVMODE_PAPERSIZE |
7661 DEVMODE_ORIENTATION;
7662 r->orientation = DMORIENT_PORTRAIT;
7663 r->papersize = DMPAPER_LETTER;
7664 r->paperlength = 0;
7665 r->paperwidth = 0;
7666 r->scale = 100;
7667 r->copies = 55;
7668 r->defaultsource = DMBIN_FORMSOURCE;
7669 r->printquality = DMRES_HIGH;
7670 r->color = DMRES_MONOCHROME;
7671 r->duplex = DMDUP_SIMPLEX;
7672 r->yresolution = 0;
7673 r->ttoption = DMTT_SUBDEV;
7674 r->collate = DMCOLLATE_FALSE;
7675 r->formname = talloc_strdup(r, "Letter");
7677 return r;
7680 static bool test_architecture_buffer(struct torture_context *tctx,
7681 void *private_data)
7683 struct test_spoolss_context *ctx =
7684 talloc_get_type_abort(private_data, struct test_spoolss_context);
7686 struct spoolss_OpenPrinterEx r;
7687 struct spoolss_UserLevel1 u1;
7688 struct policy_handle handle;
7689 uint32_t architectures[] = {
7690 PROCESSOR_ARCHITECTURE_INTEL,
7691 PROCESSOR_ARCHITECTURE_IA64,
7692 PROCESSOR_ARCHITECTURE_AMD64
7694 uint32_t needed[3];
7695 int i;
7696 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7697 struct dcerpc_binding_handle *b = p->binding_handle;
7699 for (i=0; i < ARRAY_SIZE(architectures); i++) {
7701 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7703 u1.size = 0;
7704 u1.client = NULL;
7705 u1.user = NULL;
7706 u1.build = 0;
7707 u1.major = 3;
7708 u1.minor = 0;
7709 u1.processor = architectures[i];
7711 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7712 r.in.datatype = NULL;
7713 r.in.devmode_ctr.devmode= NULL;
7714 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7715 r.in.userlevel_ctr.level = 1;
7716 r.in.userlevel_ctr.user_info.level1 = &u1;
7717 r.out.handle = &handle;
7719 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7720 torture_assert_werr_ok(tctx, r.out.result, "");
7723 struct spoolss_EnumPrinters e;
7724 uint32_t count;
7725 union spoolss_PrinterInfo *info;
7727 e.in.flags = PRINTER_ENUM_LOCAL;
7728 e.in.server = NULL;
7729 e.in.level = 2;
7730 e.in.buffer = NULL;
7731 e.in.offered = 0;
7732 e.out.count = &count;
7733 e.out.info = &info;
7734 e.out.needed = &needed[i];
7736 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7737 #if 0
7738 torture_comment(tctx, "needed was %d\n", needed[i]);
7739 #endif
7742 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7745 for (i=1; i < ARRAY_SIZE(architectures); i++) {
7746 if (needed[i-1] != needed[i]) {
7747 torture_fail(tctx,
7748 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7749 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7753 return true;
7756 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
7757 void *private_data)
7759 struct test_spoolss_context *ctx =
7760 talloc_get_type_abort(private_data, struct test_spoolss_context);
7761 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7762 struct dcerpc_binding_handle *b = p->binding_handle;
7764 return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
7767 static bool test_PrintServer_Forms(struct torture_context *tctx,
7768 void *private_data)
7770 struct test_spoolss_context *ctx =
7771 talloc_get_type_abort(private_data, struct test_spoolss_context);
7772 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7773 struct dcerpc_binding_handle *b = p->binding_handle;
7775 return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
7778 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
7779 void *private_data)
7781 struct test_spoolss_context *ctx =
7782 talloc_get_type_abort(private_data, struct test_spoolss_context);
7783 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7784 struct dcerpc_binding_handle *b = p->binding_handle;
7786 return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
7789 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
7791 NTSTATUS status;
7793 status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
7795 torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
7797 torture_assert(tctx,
7798 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
7799 "failed to open printserver");
7800 torture_assert(tctx,
7801 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
7802 "failed to get environment");
7804 return true;
7807 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
7809 struct test_spoolss_context *t;
7811 *data = t = talloc_zero(tctx, struct test_spoolss_context);
7813 return torture_rpc_spoolss_setup_common(tctx, t);
7816 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
7818 test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
7820 return true;
7823 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
7825 struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
7826 bool ret;
7828 ret = torture_rpc_spoolss_teardown_common(tctx, t);
7829 talloc_free(t);
7831 return ret;
7834 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
7836 struct dcerpc_pipe *p;
7837 struct dcerpc_binding_handle *b;
7838 const char *server_name_slash;
7839 const char *driver_name;
7840 const char *printer_name;
7841 const char *port_name;
7843 torture_assert_ntstatus_ok(tctx,
7844 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
7845 "Error connecting to server");
7847 p = t->spoolss_pipe;
7848 b = p->binding_handle;
7849 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7851 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
7852 t->driver.info8.driver_name = TORTURE_DRIVER;
7853 t->driver.info8.driver_path = "pscript5.dll";
7854 t->driver.info8.data_file = "cups6.ppd";
7855 t->driver.info8.config_file = "ps5ui.dll";
7856 t->driver.info8.help_file = "pscript.hlp";
7857 t->driver.info8.default_datatype = "RAW";
7858 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
7859 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
7860 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
7861 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
7862 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
7863 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
7864 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
7865 t->driver.info8.dependent_files->string[5] = "cups6.ini";
7866 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
7867 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
7869 t->driver.local.driver_directory= "/usr/share/cups/drivers";
7871 t->info2.portname = "LPT1:";
7873 printer_name = t->info2.printername;
7874 port_name = t->info2.portname;
7876 torture_assert(tctx,
7877 fillup_printserver_info(tctx, p, &t->driver),
7878 "failed to fillup printserver info");
7880 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
7882 torture_assert(tctx,
7883 compose_local_driver_directory(tctx, t->driver.remote.environment,
7884 t->driver.local.driver_directory,
7885 &t->driver.local.driver_directory),
7886 "failed to compose local driver directory");
7888 t->info2.drivername = "Microsoft XPS Document Writer";
7890 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7891 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7892 t->info2.drivername, t->driver.remote.environment);
7893 t->have_driver = true;
7894 goto try_add;
7897 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
7898 t->info2.drivername, t->driver.remote.environment);
7900 t->info2.drivername = "Microsoft XPS Document Writer v4";
7902 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7903 torture_comment(tctx, "driver '%s' (architecture: %s, version: 4) is present on server\n",
7904 t->info2.drivername, t->driver.remote.environment);
7905 t->have_driver = true;
7906 goto try_add;
7909 torture_comment(tctx, "trying to upload own driver\n");
7911 if (!directory_exist(t->driver.local.driver_directory)) {
7912 torture_warning(tctx, "no local driver is available!");
7913 t->have_driver = false;
7914 goto try_add;
7917 torture_assert(tctx,
7918 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
7919 "failed to upload printer driver");
7921 torture_assert(tctx,
7922 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
7923 "failed to add driver");
7925 t->added_driver = true;
7926 t->have_driver = true;
7928 try_add:
7929 driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7931 if (t->wellknown) {
7932 torture_assert(tctx,
7933 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
7934 "failed to add wellknown printer");
7935 } else {
7936 torture_assert(tctx,
7937 test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
7938 "failed to add printer");
7941 return true;
7944 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
7946 struct torture_printer_context *t;
7948 *data = t = talloc_zero(tctx, struct torture_printer_context);
7950 t->ex = false;
7951 t->wellknown = false;
7952 t->info2.printername = TORTURE_PRINTER;
7953 t->devmode = NULL;
7955 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7958 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
7960 struct torture_printer_context *t;
7962 *data = t = talloc_zero(tctx, struct torture_printer_context);
7964 t->ex = true;
7965 t->wellknown = false;
7966 t->info2.printername = TORTURE_PRINTER_EX;
7967 t->devmode = NULL;
7969 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7972 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
7974 struct torture_printer_context *t;
7976 *data = t = talloc_zero(tctx, struct torture_printer_context);
7978 t->ex = false;
7979 t->wellknown = true;
7980 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
7981 t->devmode = NULL;
7983 /* FIXME */
7984 if (t->wellknown) {
7985 torture_skip(tctx, "skipping AddPrinter level 1");
7988 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7991 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
7993 struct torture_printer_context *t;
7995 *data = t = talloc_zero(tctx, struct torture_printer_context);
7997 t->ex = true;
7998 t->wellknown = true;
7999 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
8000 t->devmode = NULL;
8002 /* FIXME */
8003 if (t->wellknown) {
8004 torture_skip(tctx, "skipping AddPrinterEx level 1");
8007 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8010 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
8012 struct torture_printer_context *t;
8014 *data = t = talloc_zero(tctx, struct torture_printer_context);
8016 t->ex = true;
8017 t->wellknown = false;
8018 t->info2.printername = TORTURE_PRINTER_EX;
8019 t->devmode = torture_devicemode(t, TORTURE_PRINTER_EX);
8021 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8024 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
8026 bool found = false;
8027 struct dcerpc_pipe *p = t->spoolss_pipe;
8028 struct dcerpc_binding_handle *b;
8029 const char *printer_name = t->info2.printername;
8031 if (t->added_driver) {
8032 torture_assert(tctx,
8033 remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
8034 "failed to remove printer driver");
8037 if (p && !t->wellknown) {
8038 b = p->binding_handle;
8040 torture_assert(tctx,
8041 test_DeletePrinter(tctx, b, &t->handle),
8042 "failed to delete printer");
8044 torture_assert(tctx,
8045 test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
8046 printer_name, &found),
8047 "failed to enumerate printers");
8049 torture_assert(tctx, !found, "deleted printer still there");
8052 return true;
8055 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
8057 struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
8058 bool ret;
8060 ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
8061 talloc_free(t);
8063 return ret;
8066 static bool test_print_test(struct torture_context *tctx,
8067 void *private_data)
8069 struct torture_printer_context *t =
8070 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8071 struct dcerpc_pipe *p = t->spoolss_pipe;
8072 struct dcerpc_binding_handle *b = p->binding_handle;
8074 torture_assert(tctx,
8075 test_PausePrinter(tctx, b, &t->handle),
8076 "failed to pause printer");
8078 torture_assert(tctx,
8079 test_DoPrintTest(tctx, b, &t->handle),
8080 "failed to do print test");
8082 torture_assert(tctx,
8083 test_ResumePrinter(tctx, b, &t->handle),
8084 "failed to resume printer");
8086 return true;
8089 static bool test_print_test_extended(struct torture_context *tctx,
8090 void *private_data)
8092 struct torture_printer_context *t =
8093 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8094 struct dcerpc_pipe *p = t->spoolss_pipe;
8095 struct dcerpc_binding_handle *b = p->binding_handle;
8096 bool ret = true;
8098 torture_assert(tctx,
8099 test_PausePrinter(tctx, b, &t->handle),
8100 "failed to pause printer");
8102 ret = test_DoPrintTest_extended(tctx, b, &t->handle);
8103 if (ret == false) {
8104 torture_comment(tctx, "WARNING! failed to do extended print test\n");
8105 if (torture_setting_bool(tctx, "samba3", false)) {
8106 torture_comment(tctx, "non-critical for samba3\n");
8107 ret = true;
8108 tctx->last_result = TORTURE_SKIP;
8112 torture_assert(tctx,
8113 test_ResumePrinter(tctx, b, &t->handle),
8114 "failed to resume printer");
8116 return ret;
8119 static bool test_print_test_properties(struct torture_context *tctx,
8120 void *private_data)
8122 struct torture_printer_context *t =
8123 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8124 struct dcerpc_pipe *p = t->spoolss_pipe;
8125 struct dcerpc_binding_handle *b = p->binding_handle;
8127 if (torture_setting_bool(tctx, "samba3", false)) {
8128 torture_skip(tctx, "skip printer job property tests against samba");
8131 torture_assert(tctx,
8132 test_PausePrinter(tctx, b, &t->handle),
8133 "failed to pause printer");
8135 torture_assert(tctx,
8136 test_DoPrintTest_properties(tctx, b, &t->handle),
8137 "failed to test print job properties");
8139 torture_assert(tctx,
8140 test_ResumePrinter(tctx, b, &t->handle),
8141 "failed to resume printer");
8143 return true;
8146 /* use smbd file IO to spool a print job */
8147 static bool test_print_test_smbd(struct torture_context *tctx,
8148 void *private_data)
8150 struct torture_printer_context *t =
8151 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8152 struct dcerpc_pipe *p = t->spoolss_pipe;
8153 struct dcerpc_binding_handle *b = p->binding_handle;
8154 NTSTATUS status;
8155 uint32_t count;
8156 union spoolss_JobInfo *info = NULL;
8157 int i;
8159 struct smb2_tree *tree;
8160 struct smb2_handle job_h;
8161 struct cli_credentials *credentials = cmdline_credentials;
8162 struct smbcli_options options;
8163 TALLOC_CTX *mem_ctx = talloc_new(tctx);
8165 * Do not test against the dynamically added printers, printing via
8166 * smbd means that a different spoolss process may handle the
8167 * OpenPrinter request to the one that handled the AddPrinter request.
8168 * This currently leads to an ugly race condition where one process
8169 * sees the new printer and one doesn't.
8171 const char *share = TORTURE_PRINTER_STATIC1;
8173 torture_comment(tctx, "Testing smbd job spooling\n");
8174 lpcfg_smbcli_options(tctx->lp_ctx, &options);
8176 status = smb2_connect(mem_ctx,
8177 torture_setting_string(tctx, "host", NULL),
8178 lpcfg_smb_ports(tctx->lp_ctx),
8179 share,
8180 lpcfg_resolve_context(tctx->lp_ctx),
8181 credentials,
8182 &tree,
8183 tctx->ev,
8184 &options,
8185 lpcfg_socket_options(tctx->lp_ctx),
8186 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
8187 if (!NT_STATUS_IS_OK(status)) {
8188 printf("Failed to connect to SMB2 printer %s - %s\n",
8189 share, nt_errstr(status));
8190 return false;
8193 status = torture_smb2_testfile(tree, "smbd_spooler_job", &job_h);
8194 torture_assert_ntstatus_ok(tctx, status, "smbd spool job create");
8196 status = smb2_util_write(tree, job_h, "exciting print job data", 0,
8197 sizeof("exciting print job data"));
8198 torture_assert_ntstatus_ok(tctx, status, "smbd spool job write");
8200 /* check back end spoolss job was created */
8201 torture_assert(tctx,
8202 test_EnumJobs_args(tctx, b, &t->handle, 1, &count, &info),
8203 "EnumJobs level 1 failed");
8205 for (i = 0; i < count; i++) {
8206 if (!strcmp(info[i].info1.document_name, "smbd_spooler_job")) {
8207 break;
8210 torture_assert(tctx, (i != count), "smbd_spooler_job not found");
8212 status = smb2_util_close(tree, job_h);
8213 torture_assert_ntstatus_ok(tctx, status, "smbd spool job close");
8215 /* disconnect from printer share */
8216 talloc_free(mem_ctx);
8218 return true;
8221 static bool test_printer_sd(struct torture_context *tctx,
8222 void *private_data)
8224 struct torture_printer_context *t =
8225 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8226 struct dcerpc_pipe *p = t->spoolss_pipe;
8227 struct dcerpc_binding_handle *b = p->binding_handle;
8229 torture_assert(tctx,
8230 test_PrinterInfo_SD(tctx, b, &t->handle),
8231 "failed to test security descriptors");
8233 return true;
8236 static bool test_printer_dm(struct torture_context *tctx,
8237 void *private_data)
8239 struct torture_printer_context *t =
8240 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8241 struct dcerpc_pipe *p = t->spoolss_pipe;
8243 torture_assert(tctx,
8244 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
8245 "failed to test devicemodes");
8247 return true;
8250 static bool test_printer_info_winreg(struct torture_context *tctx,
8251 void *private_data)
8253 struct torture_printer_context *t =
8254 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8255 struct dcerpc_pipe *p = t->spoolss_pipe;
8257 torture_assert(tctx,
8258 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
8259 "failed to test printer info winreg");
8261 return true;
8264 static bool test_printer_change_id(struct torture_context *tctx,
8265 void *private_data)
8267 struct torture_printer_context *t =
8268 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8269 struct dcerpc_pipe *p = t->spoolss_pipe;
8271 torture_assert(tctx,
8272 test_ChangeID(tctx, p, &t->handle),
8273 "failed to test change id");
8275 return true;
8278 static bool test_printer_keys(struct torture_context *tctx,
8279 void *private_data)
8281 struct torture_printer_context *t =
8282 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8283 struct dcerpc_pipe *p = t->spoolss_pipe;
8284 struct dcerpc_binding_handle *b = p->binding_handle;
8286 torture_assert(tctx,
8287 test_printer_all_keys(tctx, b, &t->handle),
8288 "failed to test printer keys");
8290 return true;
8293 static bool test_printer_data_consistency(struct torture_context *tctx,
8294 void *private_data)
8296 struct torture_printer_context *t =
8297 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8298 struct dcerpc_pipe *p = t->spoolss_pipe;
8300 torture_assert(tctx,
8301 test_EnumPrinterData_consistency(tctx, p, &t->handle),
8302 "failed to test printer data consistency");
8304 return true;
8307 static bool test_printer_data_keys(struct torture_context *tctx,
8308 void *private_data)
8310 struct torture_printer_context *t =
8311 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8312 struct dcerpc_pipe *p = t->spoolss_pipe;
8314 torture_assert(tctx,
8315 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
8316 "failed to test printer data keys");
8318 return true;
8321 static bool test_printer_data_values(struct torture_context *tctx,
8322 void *private_data)
8324 struct torture_printer_context *t =
8325 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8326 struct dcerpc_pipe *p = t->spoolss_pipe;
8328 torture_assert(tctx,
8329 test_SetPrinterDataEx_values(tctx, p, &t->handle),
8330 "failed to test printer data values");
8332 return true;
8335 static bool test_printer_data_set(struct torture_context *tctx,
8336 void *private_data)
8338 struct torture_printer_context *t =
8339 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8340 struct dcerpc_pipe *p = t->spoolss_pipe;
8342 torture_assert(tctx,
8343 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
8344 "failed to test printer data set");
8346 return true;
8349 static bool test_printer_data_winreg(struct torture_context *tctx,
8350 void *private_data)
8352 struct torture_printer_context *t =
8353 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8354 struct dcerpc_pipe *p = t->spoolss_pipe;
8356 torture_assert(tctx,
8357 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
8358 "failed to test printer data winreg");
8360 return true;
8363 static bool test_printer_data_dsspooler(struct torture_context *tctx,
8364 void *private_data)
8366 struct torture_printer_context *t =
8367 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8368 struct dcerpc_pipe *p = t->spoolss_pipe;
8370 torture_assert(tctx,
8371 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
8372 "failed to test printer data winreg dsspooler");
8374 return true;
8377 static bool test_printer_ic(struct torture_context *tctx,
8378 void *private_data)
8380 struct torture_printer_context *t =
8381 talloc_get_type_abort(private_data,
8382 struct torture_printer_context);
8383 struct dcerpc_pipe *p = t->spoolss_pipe;
8384 struct dcerpc_binding_handle *b = p->binding_handle;
8385 struct policy_handle gdi_handle;
8387 if (torture_setting_bool(tctx, "samba3", false)) {
8388 torture_skip(tctx, "skip printer information context tests against samba");
8392 struct spoolss_CreatePrinterIC r;
8393 struct spoolss_DevmodeContainer devmode_ctr;
8395 ZERO_STRUCT(devmode_ctr);
8397 r.in.handle = &t->handle;
8398 r.in.devmode_ctr = &devmode_ctr;
8399 r.out.gdi_handle = &gdi_handle;
8401 torture_assert_ntstatus_ok(tctx,
8402 dcerpc_spoolss_CreatePrinterIC_r(b, tctx, &r),
8403 "CreatePrinterIC failed");
8404 torture_assert_werr_ok(tctx, r.out.result,
8405 "CreatePrinterIC failed");
8409 struct spoolss_PlayGDIScriptOnPrinterIC r;
8410 DATA_BLOB in,out;
8411 int i;
8412 uint32_t num_fonts = 0;
8414 in = data_blob_string_const("");
8416 r.in.gdi_handle = &gdi_handle;
8417 r.in.pIn = in.data;
8418 r.in.cIn = in.length;
8419 r.in.ul = 0;
8421 for (i = 0; i < 4; i++) {
8423 out = data_blob_talloc_zero(tctx, i);
8425 r.in.cOut = out.length;
8426 r.out.pOut = out.data;
8428 torture_assert_ntstatus_ok(tctx,
8429 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8430 "PlayGDIScriptOnPrinterIC failed");
8431 torture_assert_werr_equal(tctx, r.out.result, WERR_NOMEM,
8432 "PlayGDIScriptOnPrinterIC failed");
8435 out = data_blob_talloc_zero(tctx, 4);
8437 r.in.cOut = out.length;
8438 r.out.pOut = out.data;
8440 torture_assert_ntstatus_ok(tctx,
8441 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8442 "PlayGDIScriptOnPrinterIC failed");
8443 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
8444 "PlayGDIScriptOnPrinterIC failed");
8446 /* now we should have the required length, so retry with a
8447 * buffer which is large enough to carry all font ids */
8449 num_fonts = IVAL(r.out.pOut, 0);
8451 torture_comment(tctx, "PlayGDIScriptOnPrinterIC gave font count of %d\n", num_fonts);
8453 out = data_blob_talloc_zero(tctx,
8454 num_fonts * sizeof(struct UNIVERSAL_FONT_ID) + 4);
8456 r.in.cOut = out.length;
8457 r.out.pOut = out.data;
8459 torture_assert_ntstatus_ok(tctx,
8460 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8461 "PlayGDIScriptOnPrinterIC failed");
8462 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
8463 "PlayGDIScriptOnPrinterIC failed");
8468 struct spoolss_DeletePrinterIC r;
8470 r.in.gdi_handle = &gdi_handle;
8471 r.out.gdi_handle = &gdi_handle;
8473 torture_assert_ntstatus_ok(tctx,
8474 dcerpc_spoolss_DeletePrinterIC_r(b, tctx, &r),
8475 "DeletePrinterIC failed");
8476 torture_assert_werr_ok(tctx, r.out.result,
8477 "DeletePrinterIC failed");
8481 return true;
8484 static bool test_printer_bidi(struct torture_context *tctx,
8485 void *private_data)
8487 struct torture_printer_context *t =
8488 talloc_get_type_abort(private_data,
8489 struct torture_printer_context);
8490 struct dcerpc_pipe *p = t->spoolss_pipe;
8491 struct dcerpc_binding_handle *b = p->binding_handle;
8492 struct spoolss_RpcSendRecvBidiData r;
8493 struct RPC_BIDI_REQUEST_CONTAINER bidi_req;
8494 struct RPC_BIDI_RESPONSE_CONTAINER *bidi_rep = NULL;
8496 if (torture_setting_bool(tctx, "samba3", false)) {
8497 torture_skip(tctx, "skip printer bidirectional tests against samba");
8500 ZERO_STRUCT(bidi_req);
8502 r.in.hPrinter = t->handle;
8503 r.in.pAction = "foobar";
8504 r.in.pReqData = &bidi_req;
8505 r.out.ppRespData = &bidi_rep;
8507 torture_assert_ntstatus_ok(tctx,
8508 dcerpc_spoolss_RpcSendRecvBidiData_r(b, tctx, &r),
8509 "RpcSendRecvBidiData failed");
8510 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
8511 "RpcSendRecvBidiData failed");
8513 if (!(t->info2.attributes & PRINTER_ATTRIBUTE_ENABLE_BIDI)) {
8514 torture_skip(tctx, "skipping further tests as printer is not BIDI enabled");
8517 r.in.pAction = BIDI_ACTION_ENUM_SCHEMA;
8519 torture_assert_ntstatus_ok(tctx,
8520 dcerpc_spoolss_RpcSendRecvBidiData_r(b, tctx, &r),
8521 "RpcSendRecvBidiData failed");
8522 torture_assert_werr_ok(tctx, r.out.result,
8523 "RpcSendRecvBidiData failed");
8525 return true;
8528 static bool test_printer_set_publish(struct torture_context *tctx,
8529 struct dcerpc_binding_handle *b,
8530 struct policy_handle *handle)
8532 union spoolss_PrinterInfo info;
8533 struct spoolss_SetPrinterInfo7 info7;
8534 struct spoolss_SetPrinterInfoCtr info_ctr;
8535 struct spoolss_DevmodeContainer devmode_ctr;
8536 struct sec_desc_buf secdesc_ctr;
8538 info7.guid = "";
8539 info7.action = DSPRINT_PUBLISH;
8541 ZERO_STRUCT(info_ctr);
8542 ZERO_STRUCT(devmode_ctr);
8543 ZERO_STRUCT(secdesc_ctr);
8544 info_ctr.level = 7;
8545 info_ctr.info.info7 = &info7;
8547 torture_assert(tctx,
8548 test_SetPrinter(tctx, b, handle, &info_ctr,
8549 &devmode_ctr, &secdesc_ctr, 0), "");
8551 torture_assert(tctx,
8552 test_GetPrinter_level(tctx, b, handle, 2, &info),
8553 "");
8554 torture_assert(tctx,
8555 (info.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED),
8556 "info2 publish flag not set");
8557 torture_assert(tctx,
8558 test_GetPrinter_level(tctx, b, handle, 7, &info),
8559 "");
8560 if (info.info7.action & DSPRINT_PENDING) {
8561 torture_comment(tctx, "publish is pending\n");
8562 torture_assert_int_equal(tctx,
8563 info.info7.action,
8564 (DSPRINT_PENDING | DSPRINT_PUBLISH),
8565 "info7 publish flag not set");
8566 } else {
8567 struct GUID guid;
8568 torture_assert_int_equal(tctx,
8569 info.info7.action,
8570 DSPRINT_PUBLISH,
8571 "info7 publish flag not set");
8572 torture_assert_ntstatus_ok(tctx,
8573 GUID_from_string(info.info7.guid,
8574 &guid),
8575 "invalid published printer GUID");
8578 return true;
8581 static bool test_printer_set_unpublish(struct torture_context *tctx,
8582 struct dcerpc_binding_handle *b,
8583 struct policy_handle *handle)
8585 union spoolss_PrinterInfo info;
8586 struct spoolss_SetPrinterInfo7 info7;
8587 struct spoolss_SetPrinterInfoCtr info_ctr;
8588 struct spoolss_DevmodeContainer devmode_ctr;
8589 struct sec_desc_buf secdesc_ctr;
8591 info7.action = DSPRINT_UNPUBLISH;
8592 info7.guid = "";
8594 ZERO_STRUCT(info_ctr);
8595 ZERO_STRUCT(devmode_ctr);
8596 ZERO_STRUCT(secdesc_ctr);
8597 info_ctr.level = 7;
8598 info_ctr.info.info7 = &info7;
8600 torture_assert(tctx,
8601 test_SetPrinter(tctx, b, handle, &info_ctr,
8602 &devmode_ctr, &secdesc_ctr, 0), "");
8604 torture_assert(tctx,
8605 test_GetPrinter_level(tctx, b, handle, 2, &info),
8606 "");
8607 torture_assert(tctx,
8608 !(info.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED),
8609 "info2 publish flag still set");
8610 torture_assert(tctx,
8611 test_GetPrinter_level(tctx, b, handle, 7, &info),
8612 "");
8614 if (info.info7.action & DSPRINT_PENDING) {
8615 struct GUID guid;
8616 torture_comment(tctx, "unpublish is pending\n");
8617 torture_assert_int_equal(tctx,
8618 info.info7.action,
8619 (DSPRINT_PENDING | DSPRINT_UNPUBLISH),
8620 "info7 unpublish flag not set");
8621 torture_assert_ntstatus_ok(tctx,
8622 GUID_from_string(info.info7.guid,
8623 &guid),
8624 "invalid printer GUID");
8625 } else {
8626 torture_assert_int_equal(tctx,
8627 info.info7.action, DSPRINT_UNPUBLISH,
8628 "info7 unpublish flag not set");
8631 return true;
8634 static bool test_printer_publish_toggle(struct torture_context *tctx,
8635 void *private_data)
8637 struct torture_printer_context *t =
8638 talloc_get_type_abort(private_data,
8639 struct torture_printer_context);
8640 struct dcerpc_pipe *p = t->spoolss_pipe;
8641 struct dcerpc_binding_handle *b = p->binding_handle;
8642 struct policy_handle *handle = &t->handle;
8643 union spoolss_PrinterInfo info7;
8644 union spoolss_PrinterInfo info2;
8646 /* check publish status via level 7 and level 2 */
8647 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 7, &info7),
8648 "");
8649 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info2),
8650 "");
8652 if (info2.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
8653 torture_assert_int_equal(tctx,
8654 info7.info7.action, DSPRINT_PUBLISH,
8655 "info7 publish flag not set");
8656 torture_assert(tctx, test_printer_set_unpublish(tctx, b, handle), "");
8657 torture_assert(tctx, test_printer_set_publish(tctx, b, handle), "");
8658 } else {
8659 torture_assert_int_equal(tctx,
8660 info7.info7.action, DSPRINT_UNPUBLISH,
8661 "info7 unpublish flag not set");
8662 torture_assert(tctx, test_printer_set_publish(tctx, b, handle), "");
8663 torture_assert(tctx, test_printer_set_unpublish(tctx, b, handle), "");
8666 return true;
8669 static bool test_driver_info_winreg(struct torture_context *tctx,
8670 void *private_data)
8672 struct torture_printer_context *t =
8673 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8674 struct dcerpc_pipe *p = t->spoolss_pipe;
8675 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
8677 if (!t->have_driver) {
8678 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
8681 torture_assert(tctx,
8682 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
8683 "failed to test driver info winreg");
8685 return true;
8688 void torture_tcase_printer(struct torture_tcase *tcase)
8690 torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
8691 torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
8692 torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
8693 torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
8694 torture_tcase_add_simple_test(tcase, "print_test_smbd", test_print_test_smbd);
8695 torture_tcase_add_simple_test(tcase, "print_test_properties", test_print_test_properties);
8696 torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
8697 torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
8698 torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
8699 torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
8700 torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
8701 torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
8702 torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
8703 torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
8704 torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
8705 torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
8706 torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
8707 torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
8708 torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
8709 torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
8710 torture_tcase_add_simple_test(tcase, "printer_ic", test_printer_ic);
8711 torture_tcase_add_simple_test(tcase, "bidi", test_printer_bidi);
8712 torture_tcase_add_simple_test(tcase, "publish_toggle",
8713 test_printer_publish_toggle);
8716 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
8718 struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
8719 struct torture_tcase *tcase;
8721 tcase = torture_suite_add_tcase(suite, "addprinter");
8723 torture_tcase_set_fixture(tcase,
8724 torture_rpc_spoolss_printer_setup,
8725 torture_rpc_spoolss_printer_teardown);
8727 torture_tcase_printer(tcase);
8729 tcase = torture_suite_add_tcase(suite, "addprinterex");
8731 torture_tcase_set_fixture(tcase,
8732 torture_rpc_spoolss_printerex_setup,
8733 torture_rpc_spoolss_printer_teardown);
8735 torture_tcase_printer(tcase);
8737 tcase = torture_suite_add_tcase(suite, "addprinterwkn");
8739 torture_tcase_set_fixture(tcase,
8740 torture_rpc_spoolss_printerwkn_setup,
8741 torture_rpc_spoolss_printer_teardown);
8743 tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
8745 torture_tcase_set_fixture(tcase,
8746 torture_rpc_spoolss_printerexwkn_setup,
8747 torture_rpc_spoolss_printer_teardown);
8749 #if 0
8750 /* test is not correct */
8751 tcase = torture_suite_add_tcase(suite, "addprinterdm");
8753 torture_tcase_set_fixture(tcase,
8754 torture_rpc_spoolss_printerdm_setup,
8755 torture_rpc_spoolss_printer_teardown);
8757 torture_tcase_printer(tcase);
8758 #endif
8759 return suite;
8762 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
8764 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
8765 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
8767 torture_tcase_set_fixture(tcase,
8768 torture_rpc_spoolss_setup,
8769 torture_rpc_spoolss_teardown);
8771 torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
8772 torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
8773 torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
8774 torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
8775 torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
8776 torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
8777 torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
8778 torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
8779 torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
8780 torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
8781 torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
8782 torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
8783 torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
8784 torture_tcase_add_simple_test(tcase, "add_processor", test_add_print_processor);
8785 torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
8786 torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
8787 torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
8788 torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
8789 torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
8790 torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
8791 torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
8793 torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
8795 return suite;
8798 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
8799 struct dcerpc_binding_handle *b,
8800 const char *server,
8801 const char *environment,
8802 const char **dir_p)
8804 struct spoolss_GetPrinterDriverDirectory r;
8805 uint32_t needed;
8807 r.in.server = server;
8808 r.in.environment = environment;
8809 r.in.level = 1;
8810 r.in.buffer = NULL;
8811 r.in.offered = 0;
8812 r.out.needed = &needed;
8814 torture_assert_ntstatus_ok(tctx,
8815 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8816 "failed to query driver directory");
8818 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
8819 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
8820 r.in.buffer = &blob;
8821 r.in.offered = needed;
8823 torture_assert_ntstatus_ok(tctx,
8824 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8825 "failed to query driver directory");
8828 torture_assert_werr_ok(tctx, r.out.result,
8829 "failed to query driver directory");
8831 if (dir_p) {
8832 *dir_p = r.out.info->info1.directory_name;
8835 return true;
8838 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8840 if (info_ctr == NULL) {
8841 return NULL;
8844 switch (info_ctr->level) {
8845 case 1:
8846 return info_ctr->info.info1->driver_name;
8847 case 2:
8848 return info_ctr->info.info2->driver_name;
8849 case 3:
8850 return info_ctr->info.info3->driver_name;
8851 case 4:
8852 return info_ctr->info.info4->driver_name;
8853 case 6:
8854 return info_ctr->info.info6->driver_name;
8855 case 8:
8856 return info_ctr->info.info8->driver_name;
8857 default:
8858 return NULL;
8862 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8864 if (info_ctr == NULL) {
8865 return NULL;
8868 switch (info_ctr->level) {
8869 case 2:
8870 return info_ctr->info.info2->architecture;
8871 case 3:
8872 return info_ctr->info.info3->architecture;
8873 case 4:
8874 return info_ctr->info.info4->architecture;
8875 case 6:
8876 return info_ctr->info.info6->architecture;
8877 case 8:
8878 return info_ctr->info.info8->architecture;
8879 default:
8880 return NULL;
8885 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
8886 struct dcerpc_binding_handle *b,
8887 const char *servername,
8888 struct spoolss_AddDriverInfoCtr *info_ctr,
8889 WERROR expected_result)
8891 struct spoolss_AddPrinterDriver r;
8892 const char *drivername = get_driver_from_info(info_ctr);
8893 const char *environment = get_environment_from_info(info_ctr);
8895 r.in.servername = servername;
8896 r.in.info_ctr = info_ctr;
8898 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
8899 drivername, info_ctr->level, environment);
8901 torture_assert_ntstatus_ok(tctx,
8902 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
8903 "spoolss_AddPrinterDriver failed");
8904 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8905 "spoolss_AddPrinterDriver failed with unexpected result");
8907 return true;
8911 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
8912 struct dcerpc_binding_handle *b,
8913 const char *servername,
8914 struct spoolss_AddDriverInfoCtr *info_ctr,
8915 uint32_t flags,
8916 WERROR expected_result)
8918 struct spoolss_AddPrinterDriverEx r;
8919 const char *drivername = get_driver_from_info(info_ctr);
8920 const char *environment = get_environment_from_info(info_ctr);
8922 r.in.servername = servername;
8923 r.in.info_ctr = info_ctr;
8924 r.in.flags = flags;
8926 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
8927 drivername, info_ctr->level, environment);
8929 torture_assert_ntstatus_ok(tctx,
8930 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
8931 "AddPrinterDriverEx failed");
8932 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8933 "AddPrinterDriverEx failed with unexpected result");
8935 return true;
8938 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
8939 if (path && strlen(path)) {\
8940 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
8943 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
8944 struct dcerpc_binding_handle *b,
8945 const char *server_name,
8946 struct spoolss_AddDriverInfo8 *r,
8947 uint32_t flags,
8948 bool ex,
8949 const char *remote_driver_dir)
8951 struct spoolss_AddDriverInfoCtr info_ctr;
8952 struct spoolss_AddDriverInfo1 info1;
8954 ZERO_STRUCT(info1);
8956 info_ctr.level = 1;
8957 info_ctr.info.info1 = &info1;
8959 if (ex) {
8960 torture_assert(tctx,
8961 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8962 "failed to test AddPrinterDriverEx level 1");
8963 } else {
8964 torture_assert(tctx,
8965 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8966 "failed to test AddPrinterDriver level 1");
8969 info1.driver_name = r->driver_name;
8971 if (ex) {
8972 torture_assert(tctx,
8973 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8974 "failed to test AddPrinterDriverEx level 1");
8975 } else {
8976 torture_assert(tctx,
8977 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8978 "failed to test AddPrinterDriver level 1");
8981 return true;
8984 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
8985 struct dcerpc_binding_handle *b,
8986 const char *server_name,
8987 struct spoolss_AddDriverInfo8 *r,
8988 uint32_t flags,
8989 bool ex,
8990 const char *remote_driver_dir)
8992 struct spoolss_AddDriverInfoCtr info_ctr;
8993 struct spoolss_AddDriverInfo2 info2;
8994 union spoolss_DriverInfo info;
8996 ZERO_STRUCT(info2);
8998 info_ctr.level = 2;
8999 info_ctr.info.info2 = &info2;
9001 if (ex) {
9002 torture_assert(tctx,
9003 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9004 "failed to test AddPrinterDriverEx level 2");
9005 } else {
9006 torture_assert(tctx,
9007 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9008 "failed to test AddPrinterDriver level 2");
9011 info2.driver_name = r->driver_name;
9013 if (ex) {
9014 torture_assert(tctx,
9015 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9016 "failed to test AddPrinterDriverEx level 2");
9017 } else {
9018 torture_assert(tctx,
9019 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9020 "failed to test AddPrinterDriver level 2");
9023 info2.version = r->version;
9025 if (ex) {
9026 torture_assert(tctx,
9027 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9028 "failed to test AddPrinterDriverEx level 2");
9029 } else {
9030 torture_assert(tctx,
9031 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9032 "failed to test AddPrinterDriver level 2");
9035 info2.architecture = r->architecture;
9037 if (ex) {
9038 torture_assert(tctx,
9039 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9040 "failed to test AddPrinterDriverEx level 2");
9041 } else {
9042 torture_assert(tctx,
9043 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9044 "failed to test AddPrinterDriver level 2");
9047 info2.driver_path = r->driver_path;
9049 if (ex) {
9050 torture_assert(tctx,
9051 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9052 "failed to test AddPrinterDriverEx level 2");
9053 } else {
9054 torture_assert(tctx,
9055 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9056 "failed to test AddPrinterDriver level 2");
9059 info2.data_file = r->data_file;
9061 if (ex) {
9062 torture_assert(tctx,
9063 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9064 "failed to test AddPrinterDriverEx level 2");
9065 } else {
9066 torture_assert(tctx,
9067 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9068 "failed to test AddPrinterDriver level 2");
9071 info2.config_file = r->config_file;
9073 if (ex) {
9074 torture_assert(tctx,
9075 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
9076 "failed to test AddPrinterDriverEx");
9079 if (ex) {
9080 torture_assert(tctx,
9081 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9082 "failed to test AddPrinterDriverEx level 2");
9083 } else {
9084 torture_assert(tctx,
9085 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
9086 "failed to test AddPrinterDriver level 2");
9089 torture_assert(tctx,
9090 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
9091 "failed to find added printer driver");
9093 if (remote_driver_dir) {
9094 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
9095 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
9096 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
9099 return true;
9102 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
9103 struct dcerpc_binding_handle *b,
9104 const char *server_name,
9105 struct spoolss_AddDriverInfo8 *r,
9106 uint32_t flags,
9107 bool ex,
9108 const char *remote_driver_dir)
9110 struct spoolss_AddDriverInfoCtr info_ctr;
9111 struct spoolss_AddDriverInfo3 info3;
9112 union spoolss_DriverInfo info;
9114 info3.driver_name = r->driver_name;
9115 info3.version = r->version;
9116 info3.architecture = r->architecture;
9117 info3.driver_path = r->driver_path;
9118 info3.data_file = r->data_file;
9119 info3.config_file = r->config_file;
9120 info3.help_file = r->help_file;
9121 info3.monitor_name = r->monitor_name;
9122 info3.default_datatype = r->default_datatype;
9123 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
9124 info3.dependent_files = r->dependent_files;
9126 info_ctr.level = 3;
9127 info_ctr.info.info3 = &info3;
9129 if (ex) {
9130 torture_assert(tctx,
9131 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9132 "failed to test AddPrinterDriverEx level 3");
9133 } else {
9134 torture_assert(tctx,
9135 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
9136 "failed to test AddPrinterDriver level 3");
9139 torture_assert(tctx,
9140 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
9141 "failed to find added printer driver");
9143 if (remote_driver_dir) {
9144 int i;
9145 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
9146 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
9147 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
9148 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
9149 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
9150 ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
9154 return true;
9157 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
9158 struct dcerpc_binding_handle *b,
9159 const char *server_name,
9160 struct spoolss_AddDriverInfo8 *r,
9161 uint32_t flags,
9162 bool ex,
9163 const char *remote_driver_dir)
9165 struct spoolss_AddDriverInfoCtr info_ctr;
9166 struct spoolss_AddDriverInfo4 info4;
9167 union spoolss_DriverInfo info;
9169 info4.version = r->version;
9170 info4.driver_name = r->driver_name;
9171 info4.architecture = r->architecture;
9172 info4.driver_path = r->driver_path;
9173 info4.data_file = r->data_file;
9174 info4.config_file = r->config_file;
9175 info4.help_file = r->help_file;
9176 info4.monitor_name = r->monitor_name;
9177 info4.default_datatype = r->default_datatype;
9178 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
9179 info4.dependent_files = r->dependent_files;
9180 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
9181 info4.previous_names = r->previous_names;
9183 info_ctr.level = 4;
9184 info_ctr.info.info4 = &info4;
9186 if (ex) {
9187 torture_assert(tctx,
9188 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9189 "failed to test AddPrinterDriverEx level 4");
9190 } else {
9191 torture_assert(tctx,
9192 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
9193 "failed to test AddPrinterDriver level 4");
9196 torture_assert(tctx,
9197 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
9198 "failed to find added printer driver");
9200 if (remote_driver_dir) {
9201 int i;
9202 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
9203 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
9204 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
9205 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
9206 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
9207 ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
9211 return true;
9214 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
9215 struct dcerpc_binding_handle *b,
9216 const char *server_name,
9217 struct spoolss_AddDriverInfo8 *r,
9218 uint32_t flags,
9219 bool ex,
9220 const char *remote_driver_dir)
9222 struct spoolss_AddDriverInfoCtr info_ctr;
9223 struct spoolss_AddDriverInfo6 info6;
9224 union spoolss_DriverInfo info;
9226 info6.version = r->version;
9227 info6.driver_name = r->driver_name;
9228 info6.architecture = r->architecture;
9229 info6.driver_path = r->driver_path;
9230 info6.data_file = r->data_file;
9231 info6.config_file = r->config_file;
9232 info6.help_file = r->help_file;
9233 info6.monitor_name = r->monitor_name;
9234 info6.default_datatype = r->default_datatype;
9235 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
9236 info6.dependent_files = r->dependent_files;
9237 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
9238 info6.previous_names = r->previous_names;
9239 info6.driver_date = r->driver_date;
9240 info6.driver_version = r->driver_version;
9241 info6.manufacturer_name = r->manufacturer_name;
9242 info6.manufacturer_url = r->manufacturer_url;
9243 info6.hardware_id = r->hardware_id;
9244 info6.provider = r->provider;
9246 info_ctr.level = 6;
9247 info_ctr.info.info6 = &info6;
9249 if (ex) {
9250 torture_assert(tctx,
9251 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9252 "failed to test AddPrinterDriverEx level 6");
9253 } else {
9254 torture_assert(tctx,
9255 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9256 "failed to test AddPrinterDriver level 6");
9259 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9261 if (!ex) {
9262 return true;
9265 torture_assert(tctx,
9266 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
9267 "failed to find added printer driver");
9269 if (remote_driver_dir) {
9270 int i;
9271 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
9272 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
9273 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
9274 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
9275 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
9276 ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
9280 torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
9281 torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
9283 return true;
9286 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
9287 struct dcerpc_binding_handle *b,
9288 const char *server_name,
9289 struct spoolss_AddDriverInfo8 *r,
9290 uint32_t flags,
9291 bool ex,
9292 const char *remote_driver_dir)
9294 struct spoolss_AddDriverInfoCtr info_ctr;
9295 union spoolss_DriverInfo info;
9297 info_ctr.level = 8;
9298 info_ctr.info.info8 = r;
9300 if (ex) {
9301 torture_assert(tctx,
9302 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9303 "failed to test AddPrinterDriverEx level 8");
9304 } else {
9305 torture_assert(tctx,
9306 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9307 "failed to test AddPrinterDriver level 8");
9310 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9312 if (!ex) {
9313 return true;
9316 torture_assert(tctx,
9317 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
9318 "failed to find added printer driver");
9320 if (remote_driver_dir) {
9321 int i;
9322 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
9323 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
9324 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
9325 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
9326 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
9327 ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
9331 torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
9332 torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
9334 return true;
9337 #undef ASSERT_DRIVER_PATH
9339 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
9340 struct dcerpc_binding_handle *b,
9341 const char *server,
9342 const char *driver,
9343 const char *environment,
9344 WERROR expected_result)
9346 struct spoolss_DeletePrinterDriver r;
9348 r.in.server = server;
9349 r.in.architecture = environment;
9350 r.in.driver = driver;
9352 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
9354 torture_assert_ntstatus_ok(tctx,
9355 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
9356 "DeletePrinterDriver failed");
9357 torture_assert_werr_equal(tctx, r.out.result, expected_result,
9358 "DeletePrinterDriver failed with unexpected result");
9360 return true;
9363 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
9364 struct dcerpc_binding_handle *b,
9365 const char *server,
9366 const char *driver,
9367 const char *environment,
9368 uint32_t delete_flags,
9369 uint32_t version,
9370 WERROR expected_result)
9372 struct spoolss_DeletePrinterDriverEx r;
9374 r.in.server = server;
9375 r.in.architecture = environment;
9376 r.in.driver = driver;
9377 r.in.delete_flags = delete_flags;
9378 r.in.version = version;
9380 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
9382 torture_assert_ntstatus_ok(tctx,
9383 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
9384 "DeletePrinterDriverEx failed");
9385 torture_assert_werr_equal(tctx, r.out.result, expected_result,
9386 "DeletePrinterDriverEx failed with unexpected result");
9388 return true;
9391 static bool test_DeletePrinterDriver(struct torture_context *tctx,
9392 struct dcerpc_binding_handle *b,
9393 const char *server_name,
9394 const char *driver,
9395 const char *environment)
9397 torture_assert(tctx,
9398 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
9399 "failed to delete driver");
9401 torture_assert(tctx,
9402 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
9403 "failed to delete driver");
9405 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
9406 torture_fail(tctx, "deleted driver still enumerated");
9409 torture_assert(tctx,
9410 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
9411 "2nd delete failed");
9413 return true;
9416 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
9417 struct dcerpc_binding_handle *b,
9418 const char *server_name,
9419 const char *driver,
9420 const char *environment,
9421 uint32_t delete_flags,
9422 uint32_t version)
9424 torture_assert(tctx,
9425 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
9426 "failed to delete driver");
9428 torture_assert(tctx,
9429 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
9430 "failed to delete driver");
9432 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
9433 torture_fail(tctx, "deleted driver still enumerated");
9436 torture_assert(tctx,
9437 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
9438 "2nd delete failed");
9440 return true;
9443 static bool test_PrinterDriver_args(struct torture_context *tctx,
9444 struct dcerpc_binding_handle *b,
9445 const char *server_name,
9446 uint32_t level,
9447 struct spoolss_AddDriverInfo8 *r,
9448 uint32_t add_flags,
9449 uint32_t delete_flags,
9450 uint32_t delete_version,
9451 bool ex,
9452 const char *remote_driver_dir)
9454 bool ret = true;
9456 switch (level) {
9457 case 1:
9458 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9459 break;
9460 case 2:
9461 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9462 break;
9463 case 3:
9464 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9465 break;
9466 case 4:
9467 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9468 break;
9469 case 6:
9470 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9471 break;
9472 case 8:
9473 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9474 break;
9475 default:
9476 return false;
9479 if (ret == false) {
9480 return ret;
9483 if (level == 1) {
9484 return ret;
9487 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9489 if (!ex && (level == 6 || level == 8)) {
9490 return ret;
9494 struct dcerpc_pipe *p2;
9495 struct policy_handle hive_handle;
9496 struct dcerpc_binding_handle *b2;
9498 torture_assert_ntstatus_ok(tctx,
9499 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
9500 "could not open winreg pipe");
9501 b2 = p2->binding_handle;
9503 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
9505 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
9507 test_winreg_CloseKey(tctx, b2, &hive_handle);
9509 talloc_free(p2);
9512 if (ex) {
9513 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
9514 } else {
9515 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
9519 static bool fillup_printserver_info(struct torture_context *tctx,
9520 struct dcerpc_pipe *p,
9521 struct torture_driver_context *d)
9523 struct policy_handle server_handle;
9524 struct dcerpc_binding_handle *b = p->binding_handle;
9525 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9527 torture_assert(tctx,
9528 test_OpenPrinter_server(tctx, p, &server_handle),
9529 "failed to open printserver");
9530 torture_assert(tctx,
9531 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
9532 "failed to get environment");
9533 torture_assert(tctx,
9534 test_ClosePrinter(tctx, b, &server_handle),
9535 "failed to close printserver");
9537 torture_assert(tctx,
9538 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
9539 d->local.environment ? d->local.environment : d->remote.environment,
9540 &d->remote.driver_directory),
9541 "failed to get driver directory");
9543 return true;
9546 static const char *driver_directory_dir(const char *driver_directory)
9548 char *p;
9550 p = strrchr(driver_directory, '\\');
9551 if (p) {
9552 return p+1;
9555 return NULL;
9558 static const char *driver_directory_share(struct torture_context *tctx,
9559 const char *driver_directory)
9561 const char *p;
9562 char *tok;
9564 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
9565 driver_directory += 2;
9568 p = talloc_strdup(tctx, driver_directory);
9570 torture_assert(tctx,
9571 next_token_talloc(tctx, &p, &tok, "\\"),
9572 "cannot explode uri");
9573 torture_assert(tctx,
9574 next_token_talloc(tctx, &p, &tok, "\\"),
9575 "cannot explode uri");
9577 return tok;
9580 static bool upload_printer_driver_file(struct torture_context *tctx,
9581 struct smbcli_state *cli,
9582 struct torture_driver_context *d,
9583 const char *file_name)
9585 XFILE *f;
9586 int fnum;
9587 uint8_t *buf;
9588 int maxwrite = 64512;
9589 off_t nread = 0;
9590 size_t start = 0;
9591 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
9592 const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
9593 const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
9595 if (!file_name || strlen(file_name) == 0) {
9596 return true;
9599 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
9601 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
9602 if (fnum == -1) {
9603 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
9606 f = x_fopen(local_name, O_RDONLY, 0);
9607 if (f == NULL) {
9608 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
9611 buf = talloc_array(tctx, uint8_t, maxwrite);
9612 if (!buf) {
9613 x_fclose(f);
9614 return false;
9617 while (!x_feof(f)) {
9618 int n = maxwrite;
9619 int ret;
9621 if ((n = x_fread(buf, 1, n, f)) < 1) {
9622 if((n == 0) && x_feof(f))
9623 break; /* Empty local file. */
9625 torture_warning(tctx,
9626 "failed to read file: %s\n", strerror(errno));
9627 break;
9630 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
9632 if (n != ret) {
9633 torture_warning(tctx,
9634 "failed to write file: %s\n", smbcli_errstr(cli->tree));
9635 break;
9638 nread += n;
9641 x_fclose(f);
9643 torture_assert_ntstatus_ok(tctx,
9644 smbcli_close(cli->tree, fnum),
9645 "failed to close file");
9647 return true;
9650 static bool connect_printer_driver_share(struct torture_context *tctx,
9651 const char *server_name,
9652 const char *share_name,
9653 struct smbcli_state **cli)
9655 struct smbcli_options smb_options;
9656 struct smbcli_session_options smb_session_options;
9658 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
9659 share_name, server_name);
9661 lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
9662 lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
9664 torture_assert_ntstatus_ok(tctx,
9665 smbcli_full_connection(tctx, cli, server_name,
9666 lpcfg_smb_ports(tctx->lp_ctx),
9667 share_name, NULL,
9668 lpcfg_socket_options(tctx->lp_ctx),
9669 cmdline_credentials,
9670 lpcfg_resolve_context(tctx->lp_ctx),
9671 tctx->ev,
9672 &smb_options,
9673 &smb_session_options,
9674 lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
9675 "failed to open driver share");
9677 return true;
9680 static bool upload_printer_driver(struct torture_context *tctx,
9681 const char *server_name,
9682 struct torture_driver_context *d)
9684 struct smbcli_state *cli;
9685 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9686 int i;
9688 torture_assert(tctx,
9689 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9690 "failed to connect to driver share");
9692 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
9693 server_name, share_name);
9695 torture_assert(tctx,
9696 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
9697 "failed to upload driver_path");
9698 torture_assert(tctx,
9699 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
9700 "failed to upload data_file");
9701 torture_assert(tctx,
9702 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
9703 "failed to upload config_file");
9704 torture_assert(tctx,
9705 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
9706 "failed to upload help_file");
9707 if (d->info8.dependent_files) {
9708 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9709 torture_assert(tctx,
9710 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9711 "failed to upload dependent_files");
9715 talloc_free(cli);
9717 return true;
9720 static bool check_printer_driver_file(struct torture_context *tctx,
9721 struct smbcli_state *cli,
9722 struct torture_driver_context *d,
9723 const char *file_name)
9725 const char *remote_arch_dir = driver_directory_dir(d->remote.driver_directory);
9726 const char *remote_name = talloc_asprintf(tctx, "%s\\%d\\%s",
9727 remote_arch_dir,
9728 d->info8.version,
9729 file_name);
9730 int fnum;
9732 torture_assert(tctx, (file_name && strlen(file_name) != 0), "invalid filename");
9734 torture_comment(tctx, "checking for driver file at %s\n", remote_name);
9736 fnum = smbcli_open(cli->tree, remote_name, O_RDONLY, DENY_NONE);
9737 if (fnum == -1) {
9738 return false;
9741 torture_assert_ntstatus_ok(tctx,
9742 smbcli_close(cli->tree, fnum),
9743 "failed to close driver file");
9745 return true;
9748 static bool check_printer_driver_files(struct torture_context *tctx,
9749 const char *server_name,
9750 struct torture_driver_context *d,
9751 bool expect_exist)
9753 struct smbcli_state *cli;
9754 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9755 int i;
9757 torture_assert(tctx,
9758 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9759 "failed to connect to driver share");
9761 torture_comment(tctx, "checking %sexistent driver files at \\\\%s\\%s\n",
9762 (expect_exist ? "": "non-"),
9763 server_name, share_name);
9765 if (d->info8.driver_path && d->info8.driver_path[0]) {
9766 torture_assert(tctx,
9767 check_printer_driver_file(tctx, cli, d, d->info8.driver_path) == expect_exist,
9768 "failed driver_path check");
9770 if (d->info8.data_file && d->info8.data_file[0]) {
9771 torture_assert(tctx,
9772 check_printer_driver_file(tctx, cli, d, d->info8.data_file) == expect_exist,
9773 "failed data_file check");
9775 if (d->info8.config_file && d->info8.config_file[0]) {
9776 torture_assert(tctx,
9777 check_printer_driver_file(tctx, cli, d, d->info8.config_file) == expect_exist,
9778 "failed config_file check");
9780 if (d->info8.help_file && d->info8.help_file[0]) {
9781 torture_assert(tctx,
9782 check_printer_driver_file(tctx, cli, d, d->info8.help_file) == expect_exist,
9783 "failed help_file check");
9785 if (d->info8.dependent_files) {
9786 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9787 torture_assert(tctx,
9788 check_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]) == expect_exist,
9789 "failed dependent_files check");
9793 talloc_free(cli);
9795 return true;
9798 static bool remove_printer_driver_file(struct torture_context *tctx,
9799 struct smbcli_state *cli,
9800 struct torture_driver_context *d,
9801 const char *file_name)
9803 const char *remote_name;
9804 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
9806 if (!file_name || strlen(file_name) == 0) {
9807 return true;
9810 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
9812 torture_comment(tctx, "Removing %s\n", remote_name);
9814 torture_assert_ntstatus_ok(tctx,
9815 smbcli_unlink(cli->tree, remote_name),
9816 "failed to unlink");
9818 return true;
9821 static bool remove_printer_driver(struct torture_context *tctx,
9822 const char *server_name,
9823 struct torture_driver_context *d)
9825 struct smbcli_state *cli;
9826 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9827 int i;
9829 torture_assert(tctx,
9830 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9831 "failed to connect to driver share");
9833 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
9834 server_name, share_name);
9836 torture_assert(tctx,
9837 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
9838 "failed to remove driver_path");
9839 torture_assert(tctx,
9840 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
9841 "failed to remove data_file");
9842 if (!strequal(d->info8.config_file, d->info8.driver_path)) {
9843 torture_assert(tctx,
9844 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
9845 "failed to remove config_file");
9847 torture_assert(tctx,
9848 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
9849 "failed to remove help_file");
9850 if (d->info8.dependent_files) {
9851 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9852 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
9853 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
9854 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
9855 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
9856 continue;
9858 torture_assert(tctx,
9859 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9860 "failed to remove dependent_files");
9864 talloc_free(cli);
9866 return true;
9870 static bool test_add_driver_arg(struct torture_context *tctx,
9871 struct dcerpc_pipe *p,
9872 struct torture_driver_context *d)
9874 bool ret = true;
9875 struct dcerpc_binding_handle *b = p->binding_handle;
9876 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9877 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
9878 int i;
9879 struct spoolss_AddDriverInfo8 info8;
9880 uint32_t add_flags = APD_COPY_NEW_FILES;
9881 uint32_t delete_flags = 0;
9883 ZERO_STRUCT(info8);
9885 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
9886 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
9888 torture_assert(tctx,
9889 fillup_printserver_info(tctx, p, d),
9890 "failed to fillup printserver info");
9892 if (!directory_exist(d->local.driver_directory)) {
9893 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9896 torture_assert(tctx,
9897 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9898 "failed to upload printer driver");
9900 info8 = d->info8;
9901 if (d->info8.dependent_files) {
9902 info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
9903 if (d->info8.dependent_files->string) {
9904 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9906 info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
9907 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9908 info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
9912 info8.architecture = d->local.environment;
9914 for (i=0; i < ARRAY_SIZE(levels); i++) {
9916 if (torture_setting_bool(tctx, "samba3", false)) {
9917 switch (levels[i]) {
9918 case 2:
9919 case 4:
9920 case 8:
9921 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9922 continue;
9923 default:
9924 break;
9927 if (torture_setting_bool(tctx, "w2k3", false)) {
9928 switch (levels[i]) {
9929 case 8:
9930 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9931 continue;
9932 default:
9933 break;
9937 torture_comment(tctx,
9938 "Testing PrinterDriver%s '%s' add & delete level %d\n",
9939 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9941 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);
9944 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
9945 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
9946 if (d->info8.config_file) {
9947 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
9949 if (d->info8.help_file) {
9950 info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
9952 if (d->info8.dependent_files && d->info8.dependent_files->string) {
9953 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9954 info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
9958 for (i=0; i < ARRAY_SIZE(levels); i++) {
9960 if (torture_setting_bool(tctx, "samba3", false)) {
9961 switch (levels[i]) {
9962 case 2:
9963 case 4:
9964 case 8:
9965 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9966 continue;
9967 default:
9968 break;
9971 if (torture_setting_bool(tctx, "w2k3", false)) {
9972 switch (levels[i]) {
9973 case 8:
9974 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9975 continue;
9976 default:
9977 break;
9981 torture_comment(tctx,
9982 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
9983 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9985 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);
9988 torture_assert(tctx,
9989 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9990 "failed to remove printer driver");
9992 torture_comment(tctx, "\n");
9994 return ret;
9997 static bool test_add_driver_ex_64(struct torture_context *tctx,
9998 struct dcerpc_pipe *p)
10000 struct torture_driver_context *d;
10002 d = talloc_zero(tctx, struct torture_driver_context);
10004 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10005 d->info8.driver_name = TORTURE_DRIVER_EX;
10006 d->info8.architecture = NULL;
10007 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10008 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10009 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10010 d->local.environment = talloc_strdup(d, "Windows x64");
10011 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
10012 d->ex = true;
10014 return test_add_driver_arg(tctx, p, d);
10017 static bool test_add_driver_ex_32(struct torture_context *tctx,
10018 struct dcerpc_pipe *p)
10020 struct torture_driver_context *d;
10022 d = talloc_zero(tctx, struct torture_driver_context);
10024 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10025 d->info8.driver_name = TORTURE_DRIVER_EX;
10026 d->info8.architecture = NULL;
10027 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10028 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10029 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10030 d->local.environment = talloc_strdup(d, "Windows NT x86");
10031 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10032 d->ex = true;
10034 return test_add_driver_arg(tctx, p, d);
10037 static bool test_add_driver_64(struct torture_context *tctx,
10038 struct dcerpc_pipe *p)
10040 struct torture_driver_context *d;
10042 d = talloc_zero(tctx, struct torture_driver_context);
10044 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10045 d->info8.driver_name = TORTURE_DRIVER;
10046 d->info8.architecture = NULL;
10047 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10048 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10049 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10050 d->local.environment = talloc_strdup(d, "Windows x64");
10051 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
10052 d->ex = false;
10054 return test_add_driver_arg(tctx, p, d);
10057 static bool test_add_driver_32(struct torture_context *tctx,
10058 struct dcerpc_pipe *p)
10060 struct torture_driver_context *d;
10062 d = talloc_zero(tctx, struct torture_driver_context);
10064 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10065 d->info8.driver_name = TORTURE_DRIVER;
10066 d->info8.architecture = NULL;
10067 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10068 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10069 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10070 d->local.environment = talloc_strdup(d, "Windows NT x86");
10071 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10072 d->ex = false;
10074 return test_add_driver_arg(tctx, p, d);
10077 static bool test_add_driver_adobe(struct torture_context *tctx,
10078 struct dcerpc_pipe *p)
10080 struct torture_driver_context *d;
10082 if (!torture_setting_bool(tctx, "samba3", false)) {
10083 torture_skip(tctx, "skipping adobe test which only works against samba3");
10086 d = talloc_zero(tctx, struct torture_driver_context);
10088 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
10089 d->info8.driver_name = TORTURE_DRIVER_ADOBE;
10090 d->info8.architecture = NULL;
10091 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
10092 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
10093 d->info8.config_file = talloc_strdup(d, "ADOBEPS4.DRV");
10094 #if 0
10095 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
10096 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
10097 #endif
10098 d->local.environment = talloc_strdup(d, "Windows 4.0");
10099 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
10100 d->ex = false;
10102 return test_add_driver_arg(tctx, p, d);
10105 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
10106 struct dcerpc_pipe *p)
10108 struct torture_driver_context *d;
10109 struct spoolss_StringArray *a;
10111 if (!torture_setting_bool(tctx, "samba3", false)) {
10112 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
10115 d = talloc_zero(tctx, struct torture_driver_context);
10117 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
10118 d->info8.driver_name = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
10119 d->info8.architecture = NULL;
10120 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
10121 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
10122 d->info8.config_file = NULL;
10123 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
10124 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
10125 d->info8.default_datatype = talloc_strdup(d, "RAW");
10127 a = talloc_zero(d, struct spoolss_StringArray);
10128 a->string = talloc_zero_array(a, const char *, 7);
10129 a->string[0] = talloc_strdup(a->string, "ADOBEPS4.DRV");
10130 a->string[1] = talloc_strdup(a->string, "DEFPRTR2.PPD");
10131 a->string[2] = talloc_strdup(a->string, "ADOBEPS4.HLP");
10132 a->string[3] = talloc_strdup(a->string, "PSMON.DLL");
10133 a->string[4] = talloc_strdup(a->string, "ADFONTS.MFM");
10134 a->string[5] = talloc_strdup(a->string, "ICONLIB.DLL");
10136 d->info8.dependent_files = a;
10137 d->local.environment = talloc_strdup(d, "Windows 4.0");
10138 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
10139 d->ex = false;
10141 return test_add_driver_arg(tctx, p, d);
10144 static bool test_add_driver_timestamps(struct torture_context *tctx,
10145 struct dcerpc_pipe *p)
10147 struct torture_driver_context *d;
10148 struct timeval t = timeval_current();
10150 d = talloc_zero(tctx, struct torture_driver_context);
10152 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10153 d->info8.driver_name = TORTURE_DRIVER_TIMESTAMPS;
10154 d->info8.architecture = NULL;
10155 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10156 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10157 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10158 d->info8.driver_date = timeval_to_nttime(&t);
10159 d->local.environment = talloc_strdup(d, "Windows NT x86");
10160 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10161 d->ex = true;
10163 torture_assert(tctx,
10164 test_add_driver_arg(tctx, p, d),
10165 "");
10167 unix_to_nt_time(&d->info8.driver_date, 1);
10169 torture_assert(tctx,
10170 test_add_driver_arg(tctx, p, d),
10171 "");
10173 return true;
10176 static bool test_multiple_drivers(struct torture_context *tctx,
10177 struct dcerpc_pipe *p)
10179 struct torture_driver_context *d;
10180 struct dcerpc_binding_handle *b = p->binding_handle;
10181 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10182 int i;
10183 struct spoolss_AddDriverInfo8 info8;
10184 uint32_t add_flags = APD_COPY_NEW_FILES;
10185 uint32_t delete_flags = 0;
10187 d = talloc_zero(tctx, struct torture_driver_context);
10189 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10190 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10191 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10192 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10193 d->local.environment = talloc_strdup(d, "Windows NT x86");
10194 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10195 d->ex = true;
10197 torture_assert(tctx,
10198 fillup_printserver_info(tctx, p, d),
10199 "failed to fillup printserver info");
10201 if (!directory_exist(d->local.driver_directory)) {
10202 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10205 torture_assert(tctx,
10206 upload_printer_driver(tctx, dcerpc_server_name(p), d),
10207 "failed to upload printer driver");
10209 info8 = d->info8;
10210 info8.architecture = d->local.environment;
10212 for (i=0; i < 3; i++) {
10213 info8.driver_name = talloc_asprintf(d, "torture_test_driver_%d", i);
10215 torture_assert(tctx,
10216 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &info8, add_flags, true, NULL),
10217 "failed to add driver");
10220 torture_assert(tctx,
10221 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_0", info8.architecture, delete_flags, info8.version),
10222 "failed to delete driver");
10224 torture_assert(tctx,
10225 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_1", NULL),
10226 "torture_test_driver_1 no longer on the server");
10228 torture_assert(tctx,
10229 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
10230 "torture_test_driver_2 no longer on the server");
10232 torture_assert(tctx,
10233 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_1", info8.architecture, delete_flags, info8.version),
10234 "failed to delete driver");
10236 torture_assert(tctx,
10237 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
10238 "torture_test_driver_2 no longer on the server");
10240 torture_assert(tctx,
10241 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_2", info8.architecture, delete_flags, info8.version),
10242 "failed to delete driver");
10244 torture_assert(tctx,
10245 remove_printer_driver(tctx, dcerpc_server_name(p), d),
10246 "failed to remove printer driver");
10248 return true;
10251 static bool test_del_driver_all_files(struct torture_context *tctx,
10252 struct dcerpc_pipe *p)
10254 struct torture_driver_context *d;
10255 struct spoolss_StringArray *a;
10256 uint32_t add_flags = APD_COPY_NEW_FILES;
10257 uint32_t delete_flags = DPD_DELETE_ALL_FILES;
10258 struct dcerpc_binding_handle *b = p->binding_handle;
10259 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10261 d = talloc_zero(tctx, struct torture_driver_context);
10263 d->ex = true;
10264 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10265 d->info8.driver_name = TORTURE_DRIVER_DELETER;
10266 d->info8.architecture = NULL;
10267 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10268 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10269 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10270 d->info8.help_file = talloc_strdup(d, "pscript.hlp");
10271 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
10272 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
10274 a = talloc_zero(d, struct spoolss_StringArray);
10275 a->string = talloc_zero_array(a, const char *, 3);
10276 a->string[0] = talloc_strdup(a->string, "cups6.inf");
10277 a->string[1] = talloc_strdup(a->string, "cups6.ini");
10279 d->info8.dependent_files = a;
10280 d->info8.architecture = d->local.environment;
10282 torture_assert(tctx,
10283 fillup_printserver_info(tctx, p, d),
10284 "failed to fillup printserver info");
10286 if (!directory_exist(d->local.driver_directory)) {
10287 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10290 torture_assert(tctx,
10291 upload_printer_driver(tctx, dcerpc_server_name(p), d),
10292 "failed to upload printer driver");
10294 torture_assert(tctx,
10295 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d->info8, add_flags, true, NULL),
10296 "failed to add driver");
10298 torture_assert(tctx,
10299 test_DeletePrinterDriverEx(tctx, b, server_name_slash,
10300 d->info8.driver_name,
10301 d->local.environment,
10302 delete_flags,
10303 d->info8.version),
10304 "failed to delete driver");
10306 torture_assert(tctx,
10307 check_printer_driver_files(tctx, dcerpc_server_name(p), d, false),
10308 "printer driver file check failed");
10310 talloc_free(d);
10311 return true;
10314 static bool test_del_driver_unused_files(struct torture_context *tctx,
10315 struct dcerpc_pipe *p)
10317 struct torture_driver_context *d1;
10318 struct torture_driver_context *d2;
10319 uint32_t add_flags = APD_COPY_NEW_FILES;
10320 struct dcerpc_binding_handle *b = p->binding_handle;
10321 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10323 d1 = talloc_zero(tctx, struct torture_driver_context);
10324 d1->ex = true;
10325 d1->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10326 d1->info8.driver_name = TORTURE_DRIVER_DELETER;
10327 d1->info8.architecture = NULL;
10328 d1->info8.driver_path = talloc_strdup(d1, "pscript5.dll");
10329 d1->info8.data_file = talloc_strdup(d1, "cups6.ppd");
10330 d1->info8.config_file = talloc_strdup(d1, "cupsui6.dll");
10331 d1->info8.help_file = talloc_strdup(d1, "pscript.hlp");
10332 d1->local.environment = talloc_strdup(d1, SPOOLSS_ARCHITECTURE_x64);
10333 d1->local.driver_directory = talloc_strdup(d1, "/usr/share/cups/drivers/x64");
10334 d1->info8.architecture = d1->local.environment;
10336 d2 = talloc_zero(tctx, struct torture_driver_context);
10337 d2->ex = true;
10338 d2->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10339 d2->info8.driver_name = TORTURE_DRIVER_DELETERIN;
10340 d2->info8.architecture = NULL;
10341 d2->info8.driver_path = talloc_strdup(d2, "pscript5.dll"); /* overlapping */
10342 d2->info8.data_file = talloc_strdup(d2, "cupsps6.dll");
10343 d2->info8.config_file = talloc_strdup(d2, "cups6.ini");
10344 d2->info8.help_file = talloc_strdup(d2, "pscript.hlp"); /* overlapping */
10345 d2->local.environment = talloc_strdup(d2, SPOOLSS_ARCHITECTURE_x64);
10346 d2->local.driver_directory = talloc_strdup(d2, "/usr/share/cups/drivers/x64");
10347 d2->info8.architecture = d2->local.environment;
10349 torture_assert(tctx,
10350 fillup_printserver_info(tctx, p, d1),
10351 "failed to fillup printserver info");
10352 torture_assert(tctx,
10353 fillup_printserver_info(tctx, p, d2),
10354 "failed to fillup printserver info");
10356 if (!directory_exist(d1->local.driver_directory)) {
10357 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10360 torture_assert(tctx,
10361 upload_printer_driver(tctx, dcerpc_server_name(p), d1),
10362 "failed to upload printer driver");
10363 torture_assert(tctx,
10364 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d1->info8, add_flags, true, NULL),
10365 "failed to add driver");
10367 torture_assert(tctx,
10368 upload_printer_driver(tctx, dcerpc_server_name(p), d2),
10369 "failed to upload printer driver");
10370 torture_assert(tctx,
10371 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d2->info8, add_flags, true, NULL),
10372 "failed to add driver");
10374 /* some files are in use by a separate driver, should fail */
10375 torture_assert(tctx,
10376 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10377 d1->info8.driver_name,
10378 d1->local.environment,
10379 DPD_DELETE_ALL_FILES,
10380 d1->info8.version,
10381 WERR_PRINTER_DRIVER_IN_USE),
10382 "invalid delete driver response");
10384 /* should only delete files not in use by other driver */
10385 torture_assert(tctx,
10386 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10387 d1->info8.driver_name,
10388 d1->local.environment,
10389 DPD_DELETE_UNUSED_FILES,
10390 d1->info8.version,
10391 WERR_OK),
10392 "failed to delete driver (unused files)");
10394 /* check non-overlapping were deleted */
10395 d1->info8.driver_path = NULL;
10396 d1->info8.help_file = NULL;
10397 torture_assert(tctx,
10398 check_printer_driver_files(tctx, dcerpc_server_name(p), d1, false),
10399 "printer driver file check failed");
10400 /* d2 files should be uneffected */
10401 torture_assert(tctx,
10402 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, true),
10403 "printer driver file check failed");
10405 torture_assert(tctx,
10406 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10407 d2->info8.driver_name,
10408 d2->local.environment,
10409 DPD_DELETE_ALL_FILES,
10410 d2->info8.version,
10411 WERR_OK),
10412 "failed to delete driver");
10414 torture_assert(tctx,
10415 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, false),
10416 "printer driver file check failed");
10418 talloc_free(d1);
10419 talloc_free(d2);
10420 return true;
10423 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
10425 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
10427 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
10428 "driver", &ndr_table_spoolss);
10429 torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
10430 torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
10432 torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
10433 torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
10435 torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
10437 torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
10439 torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
10441 torture_rpc_tcase_add_test(tcase, "multiple_drivers", test_multiple_drivers);
10443 torture_rpc_tcase_add_test(tcase, "del_driver_all_files", test_del_driver_all_files);
10445 torture_rpc_tcase_add_test(tcase, "del_driver_unused_files", test_del_driver_unused_files);
10447 return suite;