param: Rename variable used for lp_dnsdomain szRealm_lower
[Samba.git] / source4 / torture / rpc / spoolss.c
blobe6458878d5b65e2a70551aeb20b197ee31318039
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[7][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 uint32_t status_list[] = {
1443 /* these do not stick
1444 PRINTER_STATUS_PAUSED,
1445 PRINTER_STATUS_ERROR,
1446 PRINTER_STATUS_PENDING_DELETION, */
1447 PRINTER_STATUS_PAPER_JAM,
1448 PRINTER_STATUS_PAPER_OUT,
1449 PRINTER_STATUS_MANUAL_FEED,
1450 PRINTER_STATUS_PAPER_PROBLEM,
1451 PRINTER_STATUS_OFFLINE,
1452 PRINTER_STATUS_IO_ACTIVE,
1453 PRINTER_STATUS_BUSY,
1454 PRINTER_STATUS_PRINTING,
1455 PRINTER_STATUS_OUTPUT_BIN_FULL,
1456 PRINTER_STATUS_NOT_AVAILABLE,
1457 PRINTER_STATUS_WAITING,
1458 PRINTER_STATUS_PROCESSING,
1459 PRINTER_STATUS_INITIALIZING,
1460 PRINTER_STATUS_WARMING_UP,
1461 PRINTER_STATUS_TONER_LOW,
1462 PRINTER_STATUS_NO_TONER,
1463 PRINTER_STATUS_PAGE_PUNT,
1464 PRINTER_STATUS_USER_INTERVENTION,
1465 PRINTER_STATUS_OUT_OF_MEMORY,
1466 PRINTER_STATUS_DOOR_OPEN,
1467 PRINTER_STATUS_SERVER_UNKNOWN,
1468 PRINTER_STATUS_POWER_SAVE,
1469 /* these do not stick
1470 0x02000000,
1471 0x04000000,
1472 0x08000000,
1473 0x10000000,
1474 0x20000000,
1475 0x40000000,
1476 0x80000000 */
1478 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1479 uint32_t attribute_list[] = {
1480 PRINTER_ATTRIBUTE_QUEUED,
1481 /* fails with WERR_INVALID_DATATYPE:
1482 PRINTER_ATTRIBUTE_DIRECT, */
1483 /* does not stick
1484 PRINTER_ATTRIBUTE_DEFAULT, */
1485 PRINTER_ATTRIBUTE_SHARED,
1486 /* does not stick
1487 PRINTER_ATTRIBUTE_NETWORK, */
1488 PRINTER_ATTRIBUTE_HIDDEN,
1489 PRINTER_ATTRIBUTE_LOCAL,
1490 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1491 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1492 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1493 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1494 /* does not stick
1495 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1496 /* fails with WERR_INVALID_DATATYPE:
1497 PRINTER_ATTRIBUTE_RAW_ONLY, */
1498 /* these do not stick
1499 PRINTER_ATTRIBUTE_PUBLISHED,
1500 PRINTER_ATTRIBUTE_FAX,
1501 PRINTER_ATTRIBUTE_TS,
1502 0x00010000,
1503 0x00020000,
1504 0x00040000,
1505 0x00080000,
1506 0x00100000,
1507 0x00200000,
1508 0x00400000,
1509 0x00800000,
1510 0x01000000,
1511 0x02000000,
1512 0x04000000,
1513 0x08000000,
1514 0x10000000,
1515 0x20000000,
1516 0x40000000,
1517 0x80000000 */
1520 torture_skip(tctx, "Printer Info test is currently broken, skipping");
1523 ZERO_STRUCT(devmode_ctr);
1524 ZERO_STRUCT(secdesc_ctr);
1526 s.in.handle = handle;
1527 s.in.command = 0;
1528 s.in.info_ctr = &info_ctr;
1529 s.in.devmode_ctr = &devmode_ctr;
1530 s.in.secdesc_ctr = &secdesc_ctr;
1532 q.in.handle = handle;
1533 q.out.info = &info;
1534 q0 = q;
1536 #define TESTGETCALL(call, r) \
1537 r.in.buffer = NULL; \
1538 r.in.offered = 0;\
1539 r.out.needed = &needed; \
1540 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1541 if (!NT_STATUS_IS_OK(status)) { \
1542 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1543 r.in.level, nt_errstr(status), __location__); \
1544 ret = false; \
1545 break; \
1547 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1548 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1549 r.in.buffer = &blob; \
1550 r.in.offered = needed; \
1552 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1553 if (!NT_STATUS_IS_OK(status)) { \
1554 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1555 r.in.level, nt_errstr(status), __location__); \
1556 ret = false; \
1557 break; \
1559 if (!W_ERROR_IS_OK(r.out.result)) { \
1560 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1561 r.in.level, win_errstr(r.out.result), __location__); \
1562 ret = false; \
1563 break; \
1567 #define TESTSETCALL_EXP(call, r, err) \
1568 clear_info2(&info_ctr);\
1569 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1570 if (!NT_STATUS_IS_OK(status)) { \
1571 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1572 r.in.info_ctr->level, nt_errstr(status), __location__); \
1573 ret = false; \
1574 break; \
1576 if (!W_ERROR_IS_OK(err)) { \
1577 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1578 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1579 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1580 ret = false; \
1582 break; \
1584 if (!W_ERROR_IS_OK(r.out.result)) { \
1585 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1586 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1587 ret = false; \
1588 break; \
1591 #define TESTSETCALL(call, r) \
1592 TESTSETCALL_EXP(call, r, WERR_OK)
1594 #define STRING_EQUAL(s1, s2, field) \
1595 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1596 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1597 #field, s2, __location__); \
1598 ret = false; \
1599 break; \
1602 #define MEM_EQUAL(s1, s2, length, field) \
1603 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1604 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1605 #field, (const char *)s2, __location__); \
1606 ret = false; \
1607 break; \
1610 #define INT_EQUAL(i1, i2, field) \
1611 if (i1 != i2) { \
1612 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1613 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1614 ret = false; \
1615 break; \
1618 #define SD_EQUAL(sd1, sd2, field) \
1619 if (!security_descriptor_equal(sd1, sd2)) { \
1620 torture_comment(tctx, "Failed to set %s (%s)\n", \
1621 #field, __location__); \
1622 ret = false; \
1623 break; \
1626 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1627 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1628 q.in.level = lvl1; \
1629 TESTGETCALL(GetPrinter, q) \
1630 info_ctr.level = lvl1; \
1631 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1632 info_ctr.info.info ## lvl1->field1 = value;\
1633 TESTSETCALL_EXP(SetPrinter, s, err) \
1634 info_ctr.info.info ## lvl1->field1 = ""; \
1635 TESTGETCALL(GetPrinter, q) \
1636 info_ctr.info.info ## lvl1->field1 = value; \
1637 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1638 q.in.level = lvl2; \
1639 TESTGETCALL(GetPrinter, q) \
1640 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1641 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1642 } while (0)
1644 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1645 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1646 } while (0);
1648 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1649 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1650 q.in.level = lvl1; \
1651 TESTGETCALL(GetPrinter, q) \
1652 info_ctr.level = lvl1; \
1653 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1654 info_ctr.info.info ## lvl1->field1 = value; \
1655 TESTSETCALL(SetPrinter, s) \
1656 info_ctr.info.info ## lvl1->field1 = 0; \
1657 TESTGETCALL(GetPrinter, q) \
1658 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1659 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1660 q.in.level = lvl2; \
1661 TESTGETCALL(GetPrinter, q) \
1662 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1663 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1664 } while (0)
1666 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1667 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1668 } while (0)
1670 q0.in.level = 0;
1671 do { TESTGETCALL(GetPrinter, q0) } while (0);
1673 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1674 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1676 /* level 0 printername does not stick */
1677 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1678 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1679 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1680 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1681 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1682 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1683 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1684 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1685 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1686 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1687 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1688 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1689 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1690 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1691 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1693 /* servername can be set but does not stick
1694 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1695 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1696 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1699 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1700 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1701 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1702 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1703 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1705 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1706 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1707 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1708 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1709 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1710 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1711 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1712 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1713 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1714 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1716 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1717 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1718 attribute_list[i],
1719 (attribute_list[i] | default_attribute)
1720 ); */
1721 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1722 attribute_list[i],
1723 (attribute_list[i] | default_attribute)
1725 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1726 attribute_list[i],
1727 (attribute_list[i] | default_attribute)
1729 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1730 attribute_list[i],
1731 (attribute_list[i] | default_attribute)
1733 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1734 attribute_list[i],
1735 (attribute_list[i] | default_attribute)
1736 ); */
1737 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1738 attribute_list[i],
1739 (attribute_list[i] | default_attribute)
1741 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1742 attribute_list[i],
1743 (attribute_list[i] | default_attribute)
1745 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1746 attribute_list[i],
1747 (attribute_list[i] | default_attribute)
1749 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1750 attribute_list[i],
1751 (attribute_list[i] | default_attribute)
1752 ); */
1753 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1754 attribute_list[i],
1755 (attribute_list[i] | default_attribute)
1757 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1758 attribute_list[i],
1759 (attribute_list[i] | default_attribute)
1761 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1762 attribute_list[i],
1763 (attribute_list[i] | default_attribute)
1767 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1768 /* level 2 sets do not stick
1769 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1770 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1771 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1772 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1773 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1774 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1777 /* priorities need to be between 0 and 99
1778 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1779 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1780 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1781 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1782 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1783 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1784 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1785 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1786 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1788 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1789 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1791 /* does not stick
1792 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1793 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1795 /* does not stick
1796 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1797 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1799 /* FIXME: gd also test devmode and secdesc behavior */
1802 /* verify composition of level 1 description field */
1803 const char *description;
1804 const char *tmp;
1806 q0.in.level = 1;
1807 do { TESTGETCALL(GetPrinter, q0) } while (0);
1809 description = talloc_strdup(tctx, q0.out.info->info1.description);
1811 q0.in.level = 2;
1812 do { TESTGETCALL(GetPrinter, q0) } while (0);
1814 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1815 q0.out.info->info2.printername,
1816 q0.out.info->info2.drivername,
1817 q0.out.info->info2.location);
1819 do { STRING_EQUAL(description, tmp, "description")} while (0);
1822 return ret;
1825 static bool test_security_descriptor_equal(struct torture_context *tctx,
1826 const struct security_descriptor *sd1,
1827 const struct security_descriptor *sd2)
1829 if (sd1 == sd2) {
1830 return true;
1833 if (!sd1 || !sd2) {
1834 torture_comment(tctx, "%s\n", __location__);
1835 return false;
1838 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1839 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1841 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1842 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1844 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1845 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1846 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1847 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1848 return false;
1850 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1851 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1852 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1853 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1854 return false;
1857 return true;
1860 static bool test_sd_set_level(struct torture_context *tctx,
1861 struct dcerpc_binding_handle *b,
1862 struct policy_handle *handle,
1863 uint32_t level,
1864 struct security_descriptor *sd)
1866 struct spoolss_SetPrinterInfoCtr info_ctr;
1867 struct spoolss_DevmodeContainer devmode_ctr;
1868 struct sec_desc_buf secdesc_ctr;
1869 union spoolss_SetPrinterInfo sinfo;
1871 ZERO_STRUCT(devmode_ctr);
1872 ZERO_STRUCT(secdesc_ctr);
1874 switch (level) {
1875 case 2: {
1876 union spoolss_PrinterInfo info;
1877 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1878 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1880 info_ctr.level = 2;
1881 info_ctr.info = sinfo;
1883 break;
1885 case 3: {
1886 struct spoolss_SetPrinterInfo3 info3;
1888 info3.sec_desc_ptr = NULL;
1890 info_ctr.level = 3;
1891 info_ctr.info.info3 = &info3;
1893 break;
1895 default:
1896 return false;
1899 secdesc_ctr.sd = sd;
1901 torture_assert(tctx,
1902 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1904 return true;
1907 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1908 struct dcerpc_binding_handle *b,
1909 struct policy_handle *handle)
1911 union spoolss_PrinterInfo info;
1912 struct security_descriptor *sd1, *sd2;
1913 int i;
1915 /* just compare level 2 and level 3 */
1917 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1919 sd1 = info.info2.secdesc;
1921 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1923 sd2 = info.info3.secdesc;
1925 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1926 "SD level 2 != SD level 3");
1929 /* query level 2, set level 2, query level 2 */
1931 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1933 sd1 = info.info2.secdesc;
1935 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1937 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1939 sd2 = info.info2.secdesc;
1940 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1941 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1942 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1945 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1946 "SD level 2 != SD level 2 after SD has been set via level 2");
1949 /* query level 2, set level 3, query level 2 */
1951 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1953 sd1 = info.info2.secdesc;
1955 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1957 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1959 sd2 = info.info2.secdesc;
1961 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1962 "SD level 2 != SD level 2 after SD has been set via level 3");
1964 /* set modified sd level 3, query level 2 */
1966 for (i=0; i < 93; i++) {
1967 struct security_ace a;
1968 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1969 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1970 a.flags = 0;
1971 a.size = 0; /* autogenerated */
1972 a.access_mask = 0;
1973 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1974 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1977 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1979 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1980 sd2 = info.info2.secdesc;
1982 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1983 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1984 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1987 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1988 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1991 return true;
1995 * wrapper call that saves original sd, runs tests, and restores sd
1998 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1999 struct dcerpc_binding_handle *b,
2000 struct policy_handle *handle)
2002 union spoolss_PrinterInfo info;
2003 struct security_descriptor *sd;
2004 bool ret = true;
2006 torture_comment(tctx, "Testing Printer Security Descriptors\n");
2008 /* save original sd */
2010 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
2011 "failed to get initial security descriptor");
2013 sd = security_descriptor_copy(tctx, info.info2.secdesc);
2015 /* run tests */
2017 ret = test_PrinterInfo_SDs(tctx, b, handle);
2019 /* restore original sd */
2021 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
2022 "failed to restore initial security descriptor");
2024 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
2025 ret ? "succeeded" : "failed");
2028 return ret;
2031 static bool test_devmode_set_level(struct torture_context *tctx,
2032 struct dcerpc_binding_handle *b,
2033 struct policy_handle *handle,
2034 uint32_t level,
2035 struct spoolss_DeviceMode *devmode)
2037 struct spoolss_SetPrinterInfoCtr info_ctr;
2038 struct spoolss_DevmodeContainer devmode_ctr;
2039 struct sec_desc_buf secdesc_ctr;
2040 union spoolss_SetPrinterInfo sinfo;
2042 ZERO_STRUCT(devmode_ctr);
2043 ZERO_STRUCT(secdesc_ctr);
2045 switch (level) {
2046 case 2: {
2047 union spoolss_PrinterInfo info;
2048 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2049 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
2051 info_ctr.level = 2;
2052 info_ctr.info = sinfo;
2054 break;
2056 case 8: {
2057 struct spoolss_SetPrinterInfo8 info8;
2059 info8.devmode_ptr = NULL;
2061 info_ctr.level = 8;
2062 info_ctr.info.info8 = &info8;
2064 break;
2066 default:
2067 return false;
2070 devmode_ctr.devmode = devmode;
2072 torture_assert(tctx,
2073 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
2075 return true;
2079 static bool test_devicemode_equal(struct torture_context *tctx,
2080 const struct spoolss_DeviceMode *d1,
2081 const struct spoolss_DeviceMode *d2)
2083 if (d1 == d2) {
2084 return true;
2087 if (!d1 || !d2) {
2088 torture_comment(tctx, "%s\n", __location__);
2089 return false;
2091 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
2092 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
2093 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
2094 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
2095 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
2096 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
2097 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
2098 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
2099 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
2100 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
2101 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
2102 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
2103 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
2104 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2105 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2106 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2107 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2108 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2109 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2110 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2111 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2112 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2113 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2114 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2115 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2116 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2117 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2118 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2119 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2120 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2121 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2122 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2123 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2124 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2125 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2127 return true;
2130 static bool test_devicemode_full(struct torture_context *tctx,
2131 struct dcerpc_binding_handle *b,
2132 struct policy_handle *handle)
2134 struct spoolss_SetPrinter s;
2135 struct spoolss_GetPrinter q;
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;
2188 #if 0
2189 const char *devicename;/* [charset(UTF16)] */
2190 enum spoolss_DeviceModeSpecVersion specversion;
2191 uint16_t driverversion;
2192 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2193 uint32_t fields;
2194 #endif
2195 TEST_DEVMODE_INT_EXP(8, size, 8, size, __LINE__, WERR_INVALID_PARAM);
2196 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0, WERR_INVALID_PARAM);
2197 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0xffff, WERR_INVALID_PARAM);
2198 TEST_DEVMODE_INT_EXP(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), (devmode_ctr.devmode->__driverextra_length > 0 ) ? WERR_INVALID_PARAM : WERR_OK);
2199 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2201 devmode_ctr.devmode->driverextra_data = data_blob_string_const("foobar");
2202 torture_assert(tctx,
2203 test_devmode_set_level(tctx, b, handle, 8, devmode_ctr.devmode),
2204 "failed to set devmode");
2206 TEST_DEVMODE_INT_EXP(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), (devmode_ctr.devmode->__driverextra_length > 0 ) ? WERR_INVALID_PARAM : WERR_OK);
2207 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2209 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
2210 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
2211 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
2212 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
2213 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
2214 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
2215 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
2216 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
2217 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
2218 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
2219 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
2220 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
2221 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
2222 #if 0
2223 const char *formname;/* [charset(UTF16)] */
2224 #endif
2225 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
2226 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
2227 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
2228 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
2229 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
2230 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
2231 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
2232 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
2233 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
2234 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
2235 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
2236 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
2237 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
2238 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
2240 return ret;
2243 static bool call_OpenPrinterEx(struct torture_context *tctx,
2244 struct dcerpc_pipe *p,
2245 const char *name,
2246 struct spoolss_DeviceMode *devmode,
2247 struct policy_handle *handle);
2249 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2250 struct dcerpc_pipe *p,
2251 struct policy_handle *handle,
2252 const char *name)
2254 union spoolss_PrinterInfo info;
2255 struct spoolss_DeviceMode *devmode;
2256 struct spoolss_DeviceMode *devmode2;
2257 struct policy_handle handle_devmode;
2258 struct dcerpc_binding_handle *b = p->binding_handle;
2260 /* simply compare level8 and level2 devmode */
2262 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2264 devmode = info.info8.devmode;
2266 if (devmode && devmode->size == 0) {
2267 torture_fail(tctx,
2268 "devmode of zero size!");
2271 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2273 devmode2 = info.info2.devmode;
2275 if (devmode2 && devmode2->size == 0) {
2276 torture_fail(tctx,
2277 "devmode of zero size!");
2280 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2281 "DM level 8 != DM level 2");
2284 /* set devicemode level 8 and see if it persists */
2286 devmode->copies = 93;
2287 devmode->formname = talloc_strdup(tctx, "Legal");
2289 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2291 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2293 devmode2 = info.info8.devmode;
2295 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2296 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2298 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2300 devmode2 = info.info2.devmode;
2302 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2303 "modified DM level 8 != DM level 2");
2306 /* set devicemode level 2 and see if it persists */
2308 devmode->copies = 39;
2309 devmode->formname = talloc_strdup(tctx, "Executive");
2311 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2313 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2315 devmode2 = info.info8.devmode;
2317 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2318 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2320 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2322 devmode2 = info.info2.devmode;
2324 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2325 "modified DM level 8 != DM level 2");
2328 /* check every single bit in public part of devicemode */
2330 torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2331 "failed to set every single devicemode component");
2334 /* change formname upon open and see if it persists in getprinter calls */
2336 devmode->formname = talloc_strdup(tctx, "A4");
2337 devmode->copies = 42;
2339 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2340 "failed to open printer handle");
2342 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2344 devmode2 = info.info8.devmode;
2346 if (strequal(devmode->devicename, devmode2->devicename)) {
2347 torture_warning(tctx, "devicenames are the same\n");
2348 } else {
2349 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2350 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2353 if (strequal(devmode->formname, devmode2->formname)) {
2354 torture_warning(tctx, "formname are the same\n");
2355 } else {
2356 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2357 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2360 if (devmode->copies == devmode2->copies) {
2361 torture_warning(tctx, "copies are the same\n");
2362 } else {
2363 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2364 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2367 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2369 devmode2 = info.info2.devmode;
2371 if (strequal(devmode->devicename, devmode2->devicename)) {
2372 torture_warning(tctx, "devicenames are the same\n");
2373 } else {
2374 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2375 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2378 if (strequal(devmode->formname, devmode2->formname)) {
2379 torture_warning(tctx, "formname is the same\n");
2380 } else {
2381 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2382 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2385 if (devmode->copies == devmode2->copies) {
2386 torture_warning(tctx, "copies are the same\n");
2387 } else {
2388 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2389 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2392 test_ClosePrinter(tctx, b, &handle_devmode);
2394 return true;
2398 * wrapper call that saves original devmode, runs tests, and restores devmode
2401 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2402 struct dcerpc_pipe *p,
2403 struct policy_handle *handle,
2404 const char *name,
2405 struct spoolss_DeviceMode *addprinter_devmode)
2407 union spoolss_PrinterInfo info;
2408 struct spoolss_DeviceMode *devmode;
2409 bool ret = true;
2410 struct dcerpc_binding_handle *b = p->binding_handle;
2412 torture_comment(tctx, "Testing Printer Devicemodes\n");
2414 /* save original devmode */
2416 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2417 "failed to get initial global devicemode");
2419 devmode = info.info8.devmode;
2421 if (devmode && devmode->size == 0) {
2422 torture_fail(tctx,
2423 "devmode of zero size!");
2426 if (addprinter_devmode) {
2427 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
2428 torture_warning(tctx, "current global DM is != DM provided in addprinter");
2432 /* run tests */
2434 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2436 /* restore original devmode */
2438 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2439 "failed to restore initial global device mode");
2441 torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2442 ret ? "succeeded" : "failed");
2445 return ret;
2448 bool test_ClosePrinter(struct torture_context *tctx,
2449 struct dcerpc_binding_handle *b,
2450 struct policy_handle *handle)
2452 NTSTATUS status;
2453 struct spoolss_ClosePrinter r;
2455 r.in.handle = handle;
2456 r.out.handle = handle;
2458 torture_comment(tctx, "Testing ClosePrinter\n");
2460 status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2461 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2462 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2464 return true;
2467 static bool test_GetForm_args(struct torture_context *tctx,
2468 struct dcerpc_binding_handle *b,
2469 struct policy_handle *handle,
2470 const char *form_name,
2471 uint32_t level,
2472 union spoolss_FormInfo *info_p)
2474 NTSTATUS status;
2475 struct spoolss_GetForm r;
2476 uint32_t needed;
2478 r.in.handle = handle;
2479 r.in.form_name = form_name;
2480 r.in.level = level;
2481 r.in.buffer = NULL;
2482 r.in.offered = 0;
2483 r.out.needed = &needed;
2485 torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2487 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2488 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2490 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2491 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2492 r.in.buffer = &blob;
2493 r.in.offered = needed;
2494 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2495 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2497 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2499 torture_assert(tctx, r.out.info, "No form info returned");
2502 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2504 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
2506 if (info_p) {
2507 *info_p = *r.out.info;
2510 return true;
2513 static bool test_GetForm(struct torture_context *tctx,
2514 struct dcerpc_binding_handle *b,
2515 struct policy_handle *handle,
2516 const char *form_name,
2517 uint32_t level)
2519 return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2522 static bool test_EnumForms(struct torture_context *tctx,
2523 struct dcerpc_binding_handle *b,
2524 struct policy_handle *handle,
2525 bool print_server,
2526 uint32_t level,
2527 uint32_t *count_p,
2528 union spoolss_FormInfo **info_p)
2530 struct spoolss_EnumForms r;
2531 uint32_t needed;
2532 uint32_t count;
2533 union spoolss_FormInfo *info;
2535 r.in.handle = handle;
2536 r.in.level = level;
2537 r.in.buffer = NULL;
2538 r.in.offered = 0;
2539 r.out.needed = &needed;
2540 r.out.count = &count;
2541 r.out.info = &info;
2543 torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2545 torture_assert_ntstatus_ok(tctx,
2546 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2547 "EnumForms failed");
2549 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2550 torture_skip(tctx, "EnumForms level 2 not supported");
2553 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2554 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2557 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2558 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2559 r.in.buffer = &blob;
2560 r.in.offered = needed;
2562 torture_assert_ntstatus_ok(tctx,
2563 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2564 "EnumForms failed");
2566 torture_assert(tctx, info, "No forms returned");
2569 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2571 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
2573 if (info_p) {
2574 *info_p = info;
2576 if (count_p) {
2577 *count_p = count;
2580 return true;
2583 static bool test_EnumForms_all(struct torture_context *tctx,
2584 struct dcerpc_binding_handle *b,
2585 struct policy_handle *handle,
2586 bool print_server)
2588 uint32_t levels[] = { 1, 2 };
2589 int i, j;
2591 for (i=0; i<ARRAY_SIZE(levels); i++) {
2593 uint32_t count = 0;
2594 union spoolss_FormInfo *info = NULL;
2596 torture_assert(tctx,
2597 test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2598 "failed to enum forms");
2600 for (j = 0; j < count; j++) {
2601 if (!print_server) {
2602 torture_assert(tctx,
2603 test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2604 "failed to get form");
2609 return true;
2612 static bool test_EnumForms_find_one(struct torture_context *tctx,
2613 struct dcerpc_binding_handle *b,
2614 struct policy_handle *handle,
2615 bool print_server,
2616 const char *form_name)
2618 union spoolss_FormInfo *info;
2619 uint32_t count;
2620 bool found = false;
2621 int i;
2623 torture_assert(tctx,
2624 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2625 "failed to enumerate forms");
2627 for (i=0; i<count; i++) {
2628 if (strequal(form_name, info[i].info1.form_name)) {
2629 found = true;
2630 break;
2634 return found;
2637 static bool test_DeleteForm(struct torture_context *tctx,
2638 struct dcerpc_binding_handle *b,
2639 struct policy_handle *handle,
2640 const char *form_name,
2641 WERROR expected_result)
2643 struct spoolss_DeleteForm r;
2645 r.in.handle = handle;
2646 r.in.form_name = form_name;
2648 torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2650 torture_assert_ntstatus_ok(tctx,
2651 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2652 "DeleteForm failed");
2653 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2654 "DeleteForm gave unexpected result");
2655 if (W_ERROR_IS_OK(r.out.result)) {
2656 torture_assert_ntstatus_ok(tctx,
2657 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2658 "2nd DeleteForm failed");
2659 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2660 "2nd DeleteForm failed");
2663 return true;
2666 static bool test_AddForm(struct torture_context *tctx,
2667 struct dcerpc_binding_handle *b,
2668 struct policy_handle *handle,
2669 uint32_t level,
2670 union spoolss_AddFormInfo *info,
2671 WERROR expected_result)
2673 struct spoolss_AddForm r;
2674 struct spoolss_AddFormInfoCtr info_ctr;
2676 info_ctr.level = level;
2677 info_ctr.info = *info;
2679 if (level != 1) {
2680 torture_skip(tctx, "only level 1 supported");
2683 r.in.handle = handle;
2684 r.in.info_ctr = &info_ctr;
2686 torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2687 r.in.info_ctr->info.info1->form_name, level,
2688 r.in.info_ctr->info.info1->flags);
2690 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2691 "AddForm failed");
2692 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2693 "AddForm gave unexpected result");
2695 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2696 "2nd AddForm failed");
2697 if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2698 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2699 "2nd AddForm gave unexpected result");
2700 } else {
2701 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2702 "2nd AddForm gave unexpected result");
2705 return true;
2708 static bool test_SetForm(struct torture_context *tctx,
2709 struct dcerpc_binding_handle *b,
2710 struct policy_handle *handle,
2711 const char *form_name,
2712 uint32_t level,
2713 union spoolss_AddFormInfo *info)
2715 struct spoolss_SetForm r;
2716 struct spoolss_AddFormInfoCtr info_ctr;
2718 info_ctr.level = level;
2719 info_ctr.info = *info;
2721 r.in.handle = handle;
2722 r.in.form_name = form_name;
2723 r.in.info_ctr = &info_ctr;
2725 torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2726 form_name, level);
2728 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2729 "SetForm failed");
2731 torture_assert_werr_ok(tctx, r.out.result,
2732 "SetForm failed");
2734 return true;
2737 static bool test_GetForm_winreg(struct torture_context *tctx,
2738 struct dcerpc_binding_handle *b,
2739 struct policy_handle *handle,
2740 const char *key_name,
2741 const char *form_name,
2742 enum winreg_Type *w_type,
2743 uint32_t *w_size,
2744 uint32_t *w_length,
2745 uint8_t **w_data);
2747 static bool test_Forms_args(struct torture_context *tctx,
2748 struct dcerpc_binding_handle *b,
2749 struct policy_handle *handle,
2750 bool print_server,
2751 const char *printer_name,
2752 struct dcerpc_binding_handle *winreg_handle,
2753 struct policy_handle *hive_handle,
2754 const char *form_name,
2755 struct spoolss_AddFormInfo1 *info1,
2756 WERROR expected_add_result,
2757 WERROR expected_delete_result)
2759 union spoolss_FormInfo info;
2760 union spoolss_AddFormInfo add_info;
2762 enum winreg_Type w_type;
2763 uint32_t w_size;
2764 uint32_t w_length;
2765 uint8_t *w_data;
2767 add_info.info1 = info1;
2769 torture_assert(tctx,
2770 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2771 "failed to add form");
2773 if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2775 struct spoolss_FormInfo1 i1;
2777 torture_assert(tctx,
2778 test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2779 "failed to get form via winreg");
2781 i1.size.width = IVAL(w_data, 0);
2782 i1.size.height = IVAL(w_data, 4);
2783 i1.area.left = IVAL(w_data, 8);
2784 i1.area.top = IVAL(w_data, 12);
2785 i1.area.right = IVAL(w_data, 16);
2786 i1.area.bottom = IVAL(w_data, 20);
2787 /* skip index here */
2788 i1.flags = IVAL(w_data, 28);
2790 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2791 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2792 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2793 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
2794 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
2795 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
2796 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
2797 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
2798 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2799 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
2802 if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2803 torture_assert(tctx,
2804 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2805 "failed to get added form");
2807 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2808 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2809 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2810 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2811 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2812 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2813 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2815 if (winreg_handle && hive_handle) {
2817 struct spoolss_FormInfo1 i1;
2819 i1.size.width = IVAL(w_data, 0);
2820 i1.size.height = IVAL(w_data, 4);
2821 i1.area.left = IVAL(w_data, 8);
2822 i1.area.top = IVAL(w_data, 12);
2823 i1.area.right = IVAL(w_data, 16);
2824 i1.area.bottom = IVAL(w_data, 20);
2825 /* skip index here */
2826 i1.flags = IVAL(w_data, 28);
2828 torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
2829 torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
2830 torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
2831 torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
2832 torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
2833 torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
2834 torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
2837 add_info.info1->size.width = 1234;
2839 torture_assert(tctx,
2840 test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2841 "failed to set form");
2842 torture_assert(tctx,
2843 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2844 "failed to get setted form");
2846 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2849 if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2850 torture_assert(tctx,
2851 test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2852 "Newly added form not found in enum call");
2855 torture_assert(tctx,
2856 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2857 "failed to delete form");
2859 return true;
2862 static bool test_Forms(struct torture_context *tctx,
2863 struct dcerpc_binding_handle *b,
2864 struct policy_handle *handle,
2865 bool print_server,
2866 const char *printer_name,
2867 struct dcerpc_binding_handle *winreg_handle,
2868 struct policy_handle *hive_handle)
2870 const struct spoolss_FormSize size = {
2871 .width = 50,
2872 .height = 25
2874 const struct spoolss_FormArea area = {
2875 .left = 5,
2876 .top = 10,
2877 .right = 45,
2878 .bottom = 15
2880 int i;
2882 struct {
2883 struct spoolss_AddFormInfo1 info1;
2884 WERROR expected_add_result;
2885 WERROR expected_delete_result;
2886 } forms[] = {
2888 .info1 = {
2889 .flags = SPOOLSS_FORM_USER,
2890 .form_name = "testform_user",
2891 .size = size,
2892 .area = area,
2894 .expected_add_result = WERR_OK,
2895 .expected_delete_result = WERR_OK
2898 weird, we can add a builtin form but we can never remove it
2899 again - gd
2902 .info1 = {
2903 .flags = SPOOLSS_FORM_BUILTIN,
2904 .form_name = "testform_builtin",
2905 .size = size,
2906 .area = area,
2908 .expected_add_result = WERR_OK,
2909 .expected_delete_result = WERR_INVALID_PARAM,
2913 .info1 = {
2914 .flags = SPOOLSS_FORM_PRINTER,
2915 .form_name = "testform_printer",
2916 .size = size,
2917 .area = area,
2919 .expected_add_result = WERR_OK,
2920 .expected_delete_result = WERR_OK
2923 .info1 = {
2924 .flags = SPOOLSS_FORM_USER,
2925 .form_name = "Letter",
2926 .size = size,
2927 .area = area,
2929 .expected_add_result = WERR_FILE_EXISTS,
2930 .expected_delete_result = WERR_INVALID_PARAM
2933 .info1 = {
2934 .flags = SPOOLSS_FORM_BUILTIN,
2935 .form_name = "Letter",
2936 .size = size,
2937 .area = area,
2939 .expected_add_result = WERR_FILE_EXISTS,
2940 .expected_delete_result = WERR_INVALID_PARAM
2943 .info1 = {
2944 .flags = SPOOLSS_FORM_PRINTER,
2945 .form_name = "Letter",
2946 .size = size,
2947 .area = area,
2949 .expected_add_result = WERR_FILE_EXISTS,
2950 .expected_delete_result = WERR_INVALID_PARAM
2953 .info1 = {
2954 .flags = 12345,
2955 .form_name = "invalid_flags",
2956 .size = size,
2957 .area = area,
2959 .expected_add_result = WERR_INVALID_PARAM,
2960 .expected_delete_result = WERR_INVALID_FORM_NAME
2965 for (i=0; i < ARRAY_SIZE(forms); i++) {
2966 torture_assert(tctx,
2967 test_Forms_args(tctx, b, handle, print_server, printer_name,
2968 winreg_handle, hive_handle,
2969 forms[i].info1.form_name,
2970 &forms[i].info1,
2971 forms[i].expected_add_result,
2972 forms[i].expected_delete_result),
2973 talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2976 return true;
2979 static bool test_EnumPorts_old(struct torture_context *tctx,
2980 void *private_data)
2982 struct test_spoolss_context *ctx =
2983 talloc_get_type_abort(private_data, struct test_spoolss_context);
2985 NTSTATUS status;
2986 struct spoolss_EnumPorts r;
2987 uint32_t needed;
2988 uint32_t count;
2989 union spoolss_PortInfo *info;
2990 struct dcerpc_pipe *p = ctx->spoolss_pipe;
2991 struct dcerpc_binding_handle *b = p->binding_handle;
2993 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2994 dcerpc_server_name(p));
2995 r.in.level = 2;
2996 r.in.buffer = NULL;
2997 r.in.offered = 0;
2998 r.out.needed = &needed;
2999 r.out.count = &count;
3000 r.out.info = &info;
3002 torture_comment(tctx, "Testing EnumPorts\n");
3004 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3006 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3008 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3009 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3010 r.in.buffer = &blob;
3011 r.in.offered = needed;
3013 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3014 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3015 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3017 torture_assert(tctx, info, "No ports returned");
3020 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3022 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
3024 return true;
3027 static bool test_AddPort(struct torture_context *tctx,
3028 void *private_data)
3030 struct test_spoolss_context *ctx =
3031 talloc_get_type_abort(private_data, struct test_spoolss_context);
3033 NTSTATUS status;
3034 struct spoolss_AddPort r;
3035 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3036 struct dcerpc_binding_handle *b = p->binding_handle;
3038 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
3039 dcerpc_server_name(p));
3040 r.in.unknown = 0;
3041 r.in.monitor_name = "foo";
3043 torture_comment(tctx, "Testing AddPort\n");
3045 status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
3047 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
3049 /* win2k3 returns WERR_NOT_SUPPORTED */
3051 #if 0
3053 if (!W_ERROR_IS_OK(r.out.result)) {
3054 printf("AddPort failed - %s\n", win_errstr(r.out.result));
3055 return false;
3058 #endif
3060 return true;
3063 static bool test_GetJob_args(struct torture_context *tctx,
3064 struct dcerpc_binding_handle *b,
3065 struct policy_handle *handle,
3066 uint32_t job_id,
3067 uint32_t level,
3068 union spoolss_JobInfo *info_p)
3070 NTSTATUS status;
3071 struct spoolss_GetJob r;
3072 union spoolss_JobInfo info;
3073 uint32_t needed;
3075 r.in.handle = handle;
3076 r.in.job_id = job_id;
3077 r.in.level = level;
3078 r.in.buffer = NULL;
3079 r.in.offered = 0;
3080 r.out.needed = &needed;
3081 r.out.info = &info;
3083 torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
3085 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3086 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3087 if (level == 0) {
3088 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
3091 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3092 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3093 r.in.buffer = &blob;
3094 r.in.offered = needed;
3096 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3097 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3100 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
3101 torture_assert(tctx, r.out.info, "No job info returned");
3103 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
3105 if (info_p) {
3106 *info_p = *r.out.info;
3109 return true;
3112 #if 0
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;
3129 #endif
3131 static bool test_SetJob(struct torture_context *tctx,
3132 struct dcerpc_binding_handle *b,
3133 struct policy_handle *handle,
3134 uint32_t job_id,
3135 struct spoolss_JobInfoContainer *ctr,
3136 enum spoolss_JobControl command)
3138 NTSTATUS status;
3139 struct spoolss_SetJob r;
3141 r.in.handle = handle;
3142 r.in.job_id = job_id;
3143 r.in.ctr = ctr;
3144 r.in.command = command;
3146 switch (command) {
3147 case SPOOLSS_JOB_CONTROL_PAUSE:
3148 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3149 break;
3150 case SPOOLSS_JOB_CONTROL_RESUME:
3151 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3152 break;
3153 case SPOOLSS_JOB_CONTROL_CANCEL:
3154 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3155 break;
3156 case SPOOLSS_JOB_CONTROL_RESTART:
3157 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3158 break;
3159 case SPOOLSS_JOB_CONTROL_DELETE:
3160 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3161 break;
3162 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3163 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3164 break;
3165 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3166 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3167 break;
3168 case SPOOLSS_JOB_CONTROL_RETAIN:
3169 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3170 break;
3171 case SPOOLSS_JOB_CONTROL_RELEASE:
3172 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3173 break;
3174 default:
3175 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3176 break;
3179 status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3180 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3181 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3183 return true;
3186 static bool test_AddJob(struct torture_context *tctx,
3187 struct dcerpc_binding_handle *b,
3188 struct policy_handle *handle)
3190 NTSTATUS status;
3191 struct spoolss_AddJob r;
3192 uint32_t needed;
3194 r.in.level = 0;
3195 r.in.handle = handle;
3196 r.in.offered = 0;
3197 r.out.needed = &needed;
3198 r.in.buffer = r.out.buffer = NULL;
3200 torture_comment(tctx, "Testing AddJob\n");
3202 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3203 torture_assert_ntstatus_ok(tctx, status, "AddJob failed");
3204 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3206 r.in.level = 1;
3208 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3209 torture_assert_ntstatus_ok(tctx, status, "AddJob failed");
3210 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3212 return true;
3216 static bool test_EnumJobs_args(struct torture_context *tctx,
3217 struct dcerpc_binding_handle *b,
3218 struct policy_handle *handle,
3219 uint32_t level,
3220 uint32_t *count_p,
3221 union spoolss_JobInfo **info_p)
3223 NTSTATUS status;
3224 struct spoolss_EnumJobs r;
3225 uint32_t needed;
3226 uint32_t count;
3227 union spoolss_JobInfo *info;
3229 r.in.handle = handle;
3230 r.in.firstjob = 0;
3231 r.in.numjobs = 0xffffffff;
3232 r.in.level = level;
3233 r.in.buffer = NULL;
3234 r.in.offered = 0;
3235 r.out.needed = &needed;
3236 r.out.count = &count;
3237 r.out.info = &info;
3239 torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3241 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3243 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3245 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3246 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3247 r.in.buffer = &blob;
3248 r.in.offered = needed;
3250 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3252 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3253 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3254 torture_assert(tctx, info, "No jobs returned");
3256 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3258 } else {
3259 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3262 if (count_p) {
3263 *count_p = count;
3265 if (info_p) {
3266 *info_p = info;
3269 return true;
3272 static bool test_JobPropertiesEnum(struct torture_context *tctx,
3273 struct dcerpc_binding_handle *b,
3274 struct policy_handle *handle,
3275 uint32_t job_id)
3277 struct spoolss_RpcEnumJobNamedProperties r;
3278 uint32_t pcProperties = 0;
3279 struct RPC_PrintNamedProperty *ppProperties = NULL;
3281 r.in.hPrinter = handle;
3282 r.in.JobId = job_id;
3283 r.out.pcProperties = &pcProperties;
3284 r.out.ppProperties = &ppProperties;
3286 torture_comment(tctx, "Testing RpcEnumJobNamedProperties(%d)\n", job_id);
3288 torture_assert_ntstatus_ok(tctx,
3289 dcerpc_spoolss_RpcEnumJobNamedProperties_r(b, tctx, &r),
3290 "spoolss_RpcEnumJobNamedProperties failed");
3291 torture_assert_werr_ok(tctx, r.out.result,
3292 "spoolss_RpcEnumJobNamedProperties failed");
3294 return true;
3297 static bool test_JobPropertySet(struct torture_context *tctx,
3298 struct dcerpc_binding_handle *b,
3299 struct policy_handle *handle,
3300 uint32_t job_id,
3301 struct RPC_PrintNamedProperty *property)
3303 struct spoolss_RpcSetJobNamedProperty r;
3305 r.in.hPrinter = handle;
3306 r.in.JobId = job_id;
3307 r.in.pProperty = property;
3309 torture_comment(tctx, "Testing RpcSetJobNamedProperty(%d) %s - %d\n",
3310 job_id, property->propertyName,
3311 property->propertyValue.ePropertyType);
3313 torture_assert_ntstatus_ok(tctx,
3314 dcerpc_spoolss_RpcSetJobNamedProperty_r(b, tctx, &r),
3315 "spoolss_RpcSetJobNamedProperty failed");
3316 torture_assert_werr_ok(tctx, r.out.result,
3317 "spoolss_RpcSetJobNamedProperty failed");
3319 return true;
3322 static bool test_JobPropertyGetValue(struct torture_context *tctx,
3323 struct dcerpc_binding_handle *b,
3324 struct policy_handle *handle,
3325 uint32_t job_id,
3326 const char *property_name,
3327 struct RPC_PrintPropertyValue *value)
3329 struct spoolss_RpcGetJobNamedPropertyValue r;
3331 r.in.hPrinter = handle;
3332 r.in.JobId = job_id;
3333 r.in.pszName = property_name;
3334 r.out.pValue = value;
3336 torture_comment(tctx, "Testing RpcGetJobNamedPropertyValue(%d) %s\n",
3337 job_id, property_name);
3339 torture_assert_ntstatus_ok(tctx,
3340 dcerpc_spoolss_RpcGetJobNamedPropertyValue_r(b, tctx, &r),
3341 "spoolss_RpcGetJobNamedPropertyValue failed");
3342 torture_assert_werr_ok(tctx, r.out.result,
3343 "spoolss_RpcGetJobNamedPropertyValue failed");
3345 return true;
3348 static bool test_JobPropertyDelete(struct torture_context *tctx,
3349 struct dcerpc_binding_handle *b,
3350 struct policy_handle *handle,
3351 uint32_t job_id,
3352 const char *property_name)
3354 struct spoolss_RpcDeleteJobNamedProperty r;
3356 r.in.hPrinter = handle;
3357 r.in.JobId = job_id;
3358 r.in.pszName = property_name;
3360 torture_comment(tctx, "Testing RpcDeleteJobNamedProperty(%d) %s\n",
3361 job_id, property_name);
3363 torture_assert_ntstatus_ok(tctx,
3364 dcerpc_spoolss_RpcDeleteJobNamedProperty_r(b, tctx, &r),
3365 "spoolss_RpcDeleteJobNamedProperty failed");
3366 torture_assert_werr_ok(tctx, r.out.result,
3367 "spoolss_RpcDeleteJobNamedProperty failed");
3369 return true;
3372 static bool test_DoPrintTest_add_one_job_common(struct torture_context *tctx,
3373 struct dcerpc_binding_handle *b,
3374 struct policy_handle *handle,
3375 const char *document_name,
3376 const char *datatype,
3377 uint32_t *job_id)
3379 NTSTATUS status;
3380 struct spoolss_StartDocPrinter s;
3381 struct spoolss_DocumentInfoCtr info_ctr;
3382 struct spoolss_DocumentInfo1 info1;
3383 struct spoolss_StartPagePrinter sp;
3384 struct spoolss_WritePrinter w;
3385 struct spoolss_EndPagePrinter ep;
3386 struct spoolss_EndDocPrinter e;
3387 int i;
3388 uint32_t num_written;
3390 torture_comment(tctx, "Testing StartDocPrinter\n");
3392 s.in.handle = handle;
3393 s.in.info_ctr = &info_ctr;
3394 s.out.job_id = job_id;
3396 info1.document_name = document_name;
3397 info1.output_file = NULL;
3398 info1.datatype = datatype;
3400 info_ctr.level = 1;
3401 info_ctr.info.info1 = &info1;
3403 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3404 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3405 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3407 for (i=1; i < 4; i++) {
3408 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3410 sp.in.handle = handle;
3412 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3413 torture_assert_ntstatus_ok(tctx, status,
3414 "dcerpc_spoolss_StartPagePrinter failed");
3415 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3417 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3419 w.in.handle = handle;
3420 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3421 w.out.num_written = &num_written;
3423 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3424 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3425 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3427 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3429 ep.in.handle = handle;
3431 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3432 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3433 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3436 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3438 e.in.handle = handle;
3440 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3441 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3442 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3444 return true;
3447 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3448 struct dcerpc_binding_handle *b,
3449 struct policy_handle *handle,
3450 const char *document_name,
3451 uint32_t *job_id)
3453 test_DoPrintTest_add_one_job_common(tctx, b, handle, document_name, "RAW", job_id);
3455 return true;
3458 static bool test_DoPrintTest_add_one_job_v4(struct torture_context *tctx,
3459 struct dcerpc_binding_handle *b,
3460 struct policy_handle *handle,
3461 const char *document_name,
3462 uint32_t *job_id)
3464 test_DoPrintTest_add_one_job_common(tctx, b, handle, document_name, "XPS_PASS", job_id);
3466 return true;
3470 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3471 struct dcerpc_binding_handle *b,
3472 struct policy_handle *handle,
3473 uint32_t num_jobs,
3474 uint32_t *job_ids)
3476 uint32_t count;
3477 union spoolss_JobInfo *info = NULL;
3478 int i;
3480 torture_assert(tctx,
3481 test_AddJob(tctx, b, handle),
3482 "AddJob failed");
3484 torture_assert(tctx,
3485 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3486 "EnumJobs level 1 failed");
3488 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3490 for (i=0; i < num_jobs; i++) {
3491 union spoolss_JobInfo ginfo;
3492 const char *document_name;
3493 const char *new_document_name = "any_other_docname";
3494 struct spoolss_JobInfoContainer ctr;
3495 struct spoolss_SetJobInfo1 info1;
3497 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3499 torture_assert(tctx,
3500 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3501 "failed to call test_GetJob");
3503 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3505 document_name = ginfo.info1.document_name;
3507 info1.job_id = ginfo.info1.job_id;
3508 info1.printer_name = ginfo.info1.printer_name;
3509 info1.server_name = ginfo.info1.server_name;
3510 info1.user_name = ginfo.info1.user_name;
3511 info1.document_name = new_document_name;
3512 info1.data_type = ginfo.info1.data_type;
3513 info1.text_status = ginfo.info1.text_status;
3514 info1.status = ginfo.info1.status;
3515 info1.priority = ginfo.info1.priority;
3516 info1.position = ginfo.info1.position;
3517 info1.total_pages = ginfo.info1.total_pages;
3518 info1.pages_printed = ginfo.info1.pages_printed;
3519 info1.submitted = ginfo.info1.submitted;
3521 ctr.level = 1;
3522 ctr.info.info1 = &info1;
3524 torture_assert(tctx,
3525 test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3526 "failed to call test_SetJob level 1");
3528 torture_assert(tctx,
3529 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3530 "failed to call test_GetJob");
3532 if (strequal(ginfo.info1.document_name, document_name)) {
3533 torture_warning(tctx,
3534 "document_name did *NOT* change from '%s' to '%s'\n",
3535 document_name, new_document_name);
3539 for (i=0; i < num_jobs; i++) {
3540 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3541 torture_warning(tctx, "failed to pause printjob\n");
3543 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3544 torture_warning(tctx, "failed to resume printjob\n");
3548 return true;
3551 static bool test_DoPrintTest(struct torture_context *tctx,
3552 struct dcerpc_binding_handle *b,
3553 struct policy_handle *handle)
3555 bool ret = true;
3556 uint32_t num_jobs = 8;
3557 uint32_t *job_ids;
3558 int i;
3560 torture_comment(tctx, "Testing real print operations\n");
3562 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3564 for (i=0; i < num_jobs; i++) {
3565 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3568 for (i=0; i < num_jobs; i++) {
3569 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3572 for (i=0; i < num_jobs; i++) {
3573 ret &= test_DoPrintTest_add_one_job_v4(tctx, b, handle, "TorturePrintJob v4", &job_ids[i]);
3576 for (i=0; i < num_jobs; i++) {
3577 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3580 if (ret == true) {
3581 torture_comment(tctx, "real print operations test succeeded\n\n");
3584 return ret;
3587 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3588 struct dcerpc_binding_handle *b,
3589 struct policy_handle *handle)
3591 bool ret = true;
3592 uint32_t num_jobs = 8;
3593 uint32_t *job_ids;
3594 int i;
3595 torture_comment(tctx, "Testing real print operations (extended)\n");
3597 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3599 for (i=0; i < num_jobs; i++) {
3600 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3603 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3605 for (i=0; i < num_jobs; i++) {
3606 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3609 if (ret == true) {
3610 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3613 return ret;
3616 static bool test_JobPrintProperties_equal(struct torture_context *tctx,
3617 struct RPC_PrintPropertyValue *got,
3618 struct RPC_PrintNamedProperty *exp)
3620 torture_assert_int_equal(tctx,
3621 got->ePropertyType,
3622 exp->propertyValue.ePropertyType,
3623 "ePropertyType");
3625 switch (exp->propertyValue.ePropertyType) {
3626 case kRpcPropertyTypeString:
3627 torture_assert_str_equal(tctx,
3628 got->value.propertyString,
3629 exp->propertyValue.value.propertyString,
3630 "propertyString");
3631 break;
3632 case kRpcPropertyTypeInt32:
3633 torture_assert_int_equal(tctx,
3634 got->value.propertyInt32,
3635 exp->propertyValue.value.propertyInt32,
3636 "propertyInt32");
3637 break;
3638 case kRpcPropertyTypeInt64:
3639 torture_assert_u64_equal(tctx,
3640 got->value.propertyInt64,
3641 exp->propertyValue.value.propertyInt64,
3642 "propertyInt64");
3643 break;
3644 case kRpcPropertyTypeByte:
3645 torture_assert_int_equal(tctx,
3646 got->value.propertyByte,
3647 exp->propertyValue.value.propertyByte,
3648 "propertyByte");
3649 break;
3650 case kRpcPropertyTypeBuffer:
3651 torture_assert_int_equal(tctx,
3652 got->value.propertyBlob.cbBuf,
3653 exp->propertyValue.value.propertyBlob.cbBuf,
3654 "propertyBlob.cbBuf");
3655 torture_assert_mem_equal(tctx,
3656 got->value.propertyBlob.pBuf,
3657 exp->propertyValue.value.propertyBlob.pBuf,
3658 exp->propertyValue.value.propertyBlob.cbBuf,
3659 "propertyBlob.pBuf");
3661 break;
3665 return true;
3668 static bool test_JobPrintProperties(struct torture_context *tctx,
3669 struct dcerpc_binding_handle *b,
3670 struct policy_handle *handle,
3671 uint32_t job_id)
3673 struct RPC_PrintNamedProperty in;
3674 struct RPC_PrintPropertyValue out;
3675 int i;
3676 DATA_BLOB blob = data_blob_string_const("blob");
3677 struct {
3678 const char *property_name;
3679 enum RPC_EPrintPropertyType type;
3680 union RPC_PrintPropertyValueUnion value;
3681 WERROR expected_result;
3682 } tests[] = {
3684 .property_name = "torture_property_string",
3685 .type = kRpcPropertyTypeString,
3686 .value.propertyString = "torture_property_value_string",
3688 .property_name = "torture_property_int32",
3689 .type = kRpcPropertyTypeInt32,
3690 .value.propertyInt32 = 42,
3692 .property_name = "torture_property_int64",
3693 .type = kRpcPropertyTypeInt64,
3694 .value.propertyInt64 = 0xaffe,
3696 .property_name = "torture_property_byte",
3697 .type = kRpcPropertyTypeByte,
3698 .value.propertyByte = 0xab,
3700 .property_name = "torture_property_buffer",
3701 .type = kRpcPropertyTypeBuffer,
3702 .value.propertyBlob.cbBuf = blob.length,
3703 .value.propertyBlob.pBuf = blob.data,
3707 torture_assert(tctx,
3708 test_JobPropertiesEnum(tctx, b, handle, job_id),
3709 "failed to enum properties");
3711 for (i=0; i <ARRAY_SIZE(tests); i++) {
3713 in.propertyName = tests[i].property_name;
3714 in.propertyValue.ePropertyType = tests[i].type;
3715 in.propertyValue.value = tests[i].value;
3717 torture_assert(tctx,
3718 test_JobPropertySet(tctx, b, handle, job_id, &in),
3719 "failed to set property");
3721 torture_assert(tctx,
3722 test_JobPropertyGetValue(tctx, b, handle, job_id, in.propertyName, &out),
3723 "failed to get property");
3725 torture_assert(tctx,
3726 test_JobPrintProperties_equal(tctx, &out, &in),
3727 "property unequal");
3729 torture_assert(tctx,
3730 test_JobPropertiesEnum(tctx, b, handle, job_id),
3731 "failed to enum properties");
3733 torture_assert(tctx,
3734 test_JobPropertyDelete(tctx, b, handle, job_id, in.propertyName),
3735 "failed to delete job property");
3738 torture_assert(tctx,
3739 test_JobPropertiesEnum(tctx, b, handle, job_id),
3740 "failed to enum properties");
3742 return true;
3745 static bool test_DoPrintTest_properties(struct torture_context *tctx,
3746 struct dcerpc_binding_handle *b,
3747 struct policy_handle *handle)
3749 uint32_t num_jobs = 8;
3750 uint32_t *job_ids;
3751 int i;
3752 torture_comment(tctx, "Testing real print operations (properties)\n");
3754 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3756 for (i=0; i < num_jobs; i++) {
3757 torture_assert(tctx,
3758 test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]),
3759 "failed to create print job");
3762 for (i=0; i < num_jobs; i++) {
3763 torture_assert(tctx,
3764 test_JobPrintProperties(tctx, b, handle, job_ids[i]),
3765 "failed to test job properties");
3769 for (i=0; i < num_jobs; i++) {
3770 torture_assert(tctx,
3771 test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE),
3772 "failed to delete printjob");
3775 torture_comment(tctx, "real print operations (properties) test succeeded\n\n");
3777 return true;
3780 static bool test_PausePrinter(struct torture_context *tctx,
3781 struct dcerpc_binding_handle *b,
3782 struct policy_handle *handle)
3784 NTSTATUS status;
3785 struct spoolss_SetPrinter r;
3786 struct spoolss_SetPrinterInfoCtr info_ctr;
3787 struct spoolss_DevmodeContainer devmode_ctr;
3788 struct sec_desc_buf secdesc_ctr;
3790 info_ctr.level = 0;
3791 info_ctr.info.info0 = NULL;
3793 ZERO_STRUCT(devmode_ctr);
3794 ZERO_STRUCT(secdesc_ctr);
3796 r.in.handle = handle;
3797 r.in.info_ctr = &info_ctr;
3798 r.in.devmode_ctr = &devmode_ctr;
3799 r.in.secdesc_ctr = &secdesc_ctr;
3800 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3802 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3804 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3806 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3808 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3810 return true;
3813 static bool test_ResumePrinter(struct torture_context *tctx,
3814 struct dcerpc_binding_handle *b,
3815 struct policy_handle *handle)
3817 NTSTATUS status;
3818 struct spoolss_SetPrinter r;
3819 struct spoolss_SetPrinterInfoCtr info_ctr;
3820 struct spoolss_DevmodeContainer devmode_ctr;
3821 struct sec_desc_buf secdesc_ctr;
3823 info_ctr.level = 0;
3824 info_ctr.info.info0 = NULL;
3826 ZERO_STRUCT(devmode_ctr);
3827 ZERO_STRUCT(secdesc_ctr);
3829 r.in.handle = handle;
3830 r.in.info_ctr = &info_ctr;
3831 r.in.devmode_ctr = &devmode_ctr;
3832 r.in.secdesc_ctr = &secdesc_ctr;
3833 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3835 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3837 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3839 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3841 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3843 return true;
3846 static bool test_GetPrinterData_checktype(struct torture_context *tctx,
3847 struct dcerpc_binding_handle *b,
3848 struct policy_handle *handle,
3849 const char *value_name,
3850 enum winreg_Type *expected_type,
3851 enum winreg_Type *type_p,
3852 uint8_t **data_p,
3853 uint32_t *needed_p)
3855 NTSTATUS status;
3856 struct spoolss_GetPrinterData r;
3857 uint32_t needed;
3858 enum winreg_Type type;
3859 union spoolss_PrinterData data;
3861 r.in.handle = handle;
3862 r.in.value_name = value_name;
3863 r.in.offered = 0;
3864 r.out.needed = &needed;
3865 r.out.type = &type;
3866 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3868 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3870 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3871 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3873 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3874 if (expected_type) {
3875 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3877 r.in.offered = needed;
3878 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3879 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3880 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3883 torture_assert_werr_ok(tctx, r.out.result,
3884 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3886 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3888 if (type_p) {
3889 *type_p = type;
3892 if (data_p) {
3893 *data_p = r.out.data;
3896 if (needed_p) {
3897 *needed_p = needed;
3900 return true;
3903 static bool test_GetPrinterData(struct torture_context *tctx,
3904 struct dcerpc_binding_handle *b,
3905 struct policy_handle *handle,
3906 const char *value_name,
3907 enum winreg_Type *type_p,
3908 uint8_t **data_p,
3909 uint32_t *needed_p)
3911 return test_GetPrinterData_checktype(tctx, b, handle, value_name,
3912 NULL, type_p, data_p, needed_p);
3915 static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
3916 struct dcerpc_pipe *p,
3917 struct policy_handle *handle,
3918 const char *key_name,
3919 const char *value_name,
3920 enum winreg_Type *expected_type,
3921 enum winreg_Type *type_p,
3922 uint8_t **data_p,
3923 uint32_t *needed_p)
3925 NTSTATUS status;
3926 struct spoolss_GetPrinterDataEx r;
3927 enum winreg_Type type;
3928 uint32_t needed;
3929 union spoolss_PrinterData data;
3930 struct dcerpc_binding_handle *b = p->binding_handle;
3932 r.in.handle = handle;
3933 r.in.key_name = key_name;
3934 r.in.value_name = value_name;
3935 r.in.offered = 0;
3936 r.out.type = &type;
3937 r.out.needed = &needed;
3938 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3940 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3941 r.in.key_name, r.in.value_name);
3943 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3944 if (!NT_STATUS_IS_OK(status)) {
3945 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3946 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3948 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3951 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3952 if (expected_type) {
3953 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3955 r.in.offered = needed;
3956 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3957 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3958 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3961 torture_assert_werr_ok(tctx, r.out.result,
3962 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3964 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3966 if (type_p) {
3967 *type_p = type;
3970 if (data_p) {
3971 *data_p = r.out.data;
3974 if (needed_p) {
3975 *needed_p = needed;
3978 return true;
3981 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3982 struct dcerpc_pipe *p,
3983 struct policy_handle *handle,
3984 const char *key_name,
3985 const char *value_name,
3986 enum winreg_Type *type_p,
3987 uint8_t **data_p,
3988 uint32_t *needed_p)
3990 return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
3991 NULL, type_p, data_p, needed_p);
3994 static bool test_get_environment(struct torture_context *tctx,
3995 struct dcerpc_binding_handle *b,
3996 struct policy_handle *handle,
3997 const char **architecture)
3999 DATA_BLOB blob;
4000 enum winreg_Type type;
4001 uint8_t *data;
4002 uint32_t needed;
4004 torture_assert(tctx,
4005 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
4006 "failed to get Architecture");
4008 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
4010 blob = data_blob_const(data, needed);
4011 *architecture = reg_val_data_string(tctx, REG_SZ, blob);
4013 return true;
4016 static bool test_GetPrinterData_list(struct torture_context *tctx,
4017 void *private_data)
4019 struct test_spoolss_context *ctx =
4020 talloc_get_type_abort(private_data, struct test_spoolss_context);
4021 struct dcerpc_pipe *p = ctx->spoolss_pipe;
4022 struct dcerpc_binding_handle *b = p->binding_handle;
4023 const char *list[] = {
4024 "W3SvcInstalled",
4025 "BeepEnabled",
4026 "EventLog",
4027 /* "NetPopup", not on w2k8 */
4028 /* "NetPopupToComputer", not on w2k8 */
4029 "MajorVersion",
4030 "MinorVersion",
4031 "DefaultSpoolDirectory",
4032 "Architecture",
4033 "DsPresent",
4034 "OSVersion",
4035 /* "OSVersionEx", not on s3 */
4036 "DNSMachineName"
4038 int i;
4040 for (i=0; i < ARRAY_SIZE(list); i++) {
4041 enum winreg_Type type, type_ex;
4042 uint8_t *data, *data_ex;
4043 uint32_t needed, needed_ex;
4045 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
4046 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
4047 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
4048 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
4049 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
4050 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
4051 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
4054 return true;
4057 static bool test_EnumPrinterData(struct torture_context *tctx,
4058 struct dcerpc_pipe *p,
4059 struct policy_handle *handle,
4060 uint32_t enum_index,
4061 uint32_t value_offered,
4062 uint32_t data_offered,
4063 enum winreg_Type *type_p,
4064 uint32_t *value_needed_p,
4065 uint32_t *data_needed_p,
4066 const char **value_name_p,
4067 uint8_t **data_p,
4068 WERROR *result_p)
4070 struct spoolss_EnumPrinterData r;
4071 uint32_t data_needed;
4072 uint32_t value_needed;
4073 enum winreg_Type type;
4074 struct dcerpc_binding_handle *b = p->binding_handle;
4076 r.in.handle = handle;
4077 r.in.enum_index = enum_index;
4078 r.in.value_offered = value_offered;
4079 r.in.data_offered = data_offered;
4080 r.out.data_needed = &data_needed;
4081 r.out.value_needed = &value_needed;
4082 r.out.type = &type;
4083 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
4084 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
4086 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
4088 torture_assert_ntstatus_ok(tctx,
4089 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
4090 "EnumPrinterData failed");
4092 if (type_p) {
4093 *type_p = type;
4095 if (value_needed_p) {
4096 *value_needed_p = value_needed;
4098 if (data_needed_p) {
4099 *data_needed_p = data_needed;
4101 if (value_name_p) {
4102 *value_name_p = r.out.value_name;
4104 if (data_p) {
4105 *data_p = r.out.data;
4107 if (result_p) {
4108 *result_p = r.out.result;
4111 return true;
4115 static bool test_EnumPrinterData_all(struct torture_context *tctx,
4116 struct dcerpc_pipe *p,
4117 struct policy_handle *handle)
4119 uint32_t enum_index = 0;
4120 enum winreg_Type type;
4121 uint32_t value_needed;
4122 uint32_t data_needed;
4123 uint8_t *data;
4124 const char *value_name;
4125 WERROR result;
4127 torture_comment(tctx, "Testing EnumPrinterData\n");
4129 do {
4130 torture_assert(tctx,
4131 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
4132 &type, &value_needed, &data_needed,
4133 &value_name, &data, &result),
4134 "EnumPrinterData failed");
4136 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
4137 break;
4140 torture_assert(tctx,
4141 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
4142 &type, &value_needed, &data_needed,
4143 &value_name, &data, &result),
4144 "EnumPrinterData failed");
4146 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
4147 break;
4150 enum_index++;
4152 } while (W_ERROR_IS_OK(result));
4154 torture_comment(tctx, "EnumPrinterData test succeeded\n");
4156 return true;
4159 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
4160 struct dcerpc_binding_handle *b,
4161 struct policy_handle *handle,
4162 const char *key_name,
4163 uint32_t *count_p,
4164 struct spoolss_PrinterEnumValues **info_p)
4166 struct spoolss_EnumPrinterDataEx r;
4167 struct spoolss_PrinterEnumValues *info;
4168 uint32_t needed;
4169 uint32_t count;
4171 r.in.handle = handle;
4172 r.in.key_name = key_name;
4173 r.in.offered = 0;
4174 r.out.needed = &needed;
4175 r.out.count = &count;
4176 r.out.info = &info;
4178 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
4180 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
4181 "EnumPrinterDataEx failed");
4182 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4183 r.in.offered = needed;
4184 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
4185 "EnumPrinterDataEx failed");
4188 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
4190 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
4192 if (count_p) {
4193 *count_p = count;
4195 if (info_p) {
4196 *info_p = info;
4199 return true;
4202 static bool test_SetPrinterData(struct torture_context *tctx,
4203 struct dcerpc_binding_handle *b,
4204 struct policy_handle *handle,
4205 const char *value_name,
4206 enum winreg_Type type,
4207 uint8_t *data,
4208 uint32_t offered);
4209 static bool test_DeletePrinterData(struct torture_context *tctx,
4210 struct dcerpc_binding_handle *b,
4211 struct policy_handle *handle,
4212 const char *value_name);
4214 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
4215 struct dcerpc_pipe *p,
4216 struct policy_handle *handle)
4218 uint32_t count;
4219 struct spoolss_PrinterEnumValues *info;
4220 int i;
4221 uint32_t value_needed, data_needed;
4222 uint32_t value_offered, data_offered;
4223 WERROR result;
4224 struct dcerpc_binding_handle *b = p->binding_handle;
4226 enum winreg_Type type;
4227 DATA_BLOB blob;
4229 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
4231 torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
4232 type = REG_SZ;
4234 torture_assert(tctx,
4235 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
4236 "SetPrinterData failed");
4238 blob = data_blob_string_const("torture_data2");
4240 torture_assert(tctx,
4241 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
4242 "SetPrinterData failed");
4244 blob = data_blob_talloc(tctx, NULL, 4);
4245 SIVAL(blob.data, 0, 0x11223344);
4247 torture_assert(tctx,
4248 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
4249 "SetPrinterData failed");
4251 torture_assert(tctx,
4252 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
4253 "failed to call EnumPrinterDataEx");
4255 /* get the max sizes for value and data */
4257 torture_assert(tctx,
4258 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
4259 NULL, &value_needed, &data_needed,
4260 NULL, NULL, &result),
4261 "EnumPrinterData failed");
4262 torture_assert_werr_ok(tctx, result, "unexpected result");
4264 /* check if the reply from the EnumPrinterData really matches max values */
4266 for (i=0; i < count; i++) {
4267 if (info[i].value_name_len > value_needed) {
4268 torture_fail(tctx,
4269 talloc_asprintf(tctx,
4270 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
4271 info[i].value_name_len, value_needed));
4273 if (info[i].data_length > data_needed) {
4274 torture_fail(tctx,
4275 talloc_asprintf(tctx,
4276 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
4277 info[i].data_length, data_needed));
4281 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
4282 * sort or not sort the replies by value name, we should be able to do
4283 * the following entry comparison */
4285 data_offered = data_needed;
4286 value_offered = value_needed;
4288 for (i=0; i < count; i++) {
4290 const char *value_name;
4291 uint8_t *data;
4293 torture_assert(tctx,
4294 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
4295 &type, &value_needed, &data_needed,
4296 &value_name, &data, &result),
4297 "EnumPrinterData failed");
4299 if (i -1 == count) {
4300 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
4301 "unexpected result");
4302 break;
4303 } else {
4304 torture_assert_werr_ok(tctx, result, "unexpected result");
4307 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
4308 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
4309 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
4310 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
4311 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
4314 torture_assert(tctx,
4315 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
4316 "DeletePrinterData failed");
4317 torture_assert(tctx,
4318 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
4319 "DeletePrinterData failed");
4320 torture_assert(tctx,
4321 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
4322 "DeletePrinterData failed");
4324 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4326 return true;
4329 static bool test_DeletePrinterData(struct torture_context *tctx,
4330 struct dcerpc_binding_handle *b,
4331 struct policy_handle *handle,
4332 const char *value_name)
4334 NTSTATUS status;
4335 struct spoolss_DeletePrinterData r;
4337 r.in.handle = handle;
4338 r.in.value_name = value_name;
4340 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
4341 r.in.value_name);
4343 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
4345 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
4346 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
4348 return true;
4351 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
4352 struct dcerpc_binding_handle *b,
4353 struct policy_handle *handle,
4354 const char *key_name,
4355 const char *value_name)
4357 struct spoolss_DeletePrinterDataEx r;
4359 r.in.handle = handle;
4360 r.in.key_name = key_name;
4361 r.in.value_name = value_name;
4363 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
4364 r.in.key_name, r.in.value_name);
4366 torture_assert_ntstatus_ok(tctx,
4367 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
4368 "DeletePrinterDataEx failed");
4369 torture_assert_werr_ok(tctx, r.out.result,
4370 "DeletePrinterDataEx failed");
4372 return true;
4375 static bool test_DeletePrinterKey(struct torture_context *tctx,
4376 struct dcerpc_binding_handle *b,
4377 struct policy_handle *handle,
4378 const char *key_name)
4380 struct spoolss_DeletePrinterKey r;
4382 r.in.handle = handle;
4383 r.in.key_name = key_name;
4385 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
4387 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
4388 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
4389 return true;
4392 torture_assert_ntstatus_ok(tctx,
4393 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
4394 "DeletePrinterKey failed");
4395 torture_assert_werr_ok(tctx, r.out.result,
4396 "DeletePrinterKey failed");
4398 return true;
4401 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4402 struct dcerpc_binding_handle *b,
4403 struct policy_handle *handle)
4405 struct winreg_OpenHKLM r;
4407 r.in.system_name = NULL;
4408 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4409 r.out.handle = handle;
4411 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4413 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4414 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4416 return true;
4419 static void init_winreg_String(struct winreg_String *name, const char *s)
4421 name->name = s;
4422 if (s) {
4423 name->name_len = 2 * (strlen_m(s) + 1);
4424 name->name_size = name->name_len;
4425 } else {
4426 name->name_len = 0;
4427 name->name_size = 0;
4431 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4432 struct dcerpc_binding_handle *b,
4433 struct policy_handle *hive_handle,
4434 const char *keyname,
4435 uint32_t options,
4436 struct policy_handle *key_handle)
4438 struct winreg_OpenKey r;
4440 r.in.parent_handle = hive_handle;
4441 init_winreg_String(&r.in.keyname, keyname);
4442 r.in.options = options;
4443 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4444 r.out.handle = key_handle;
4446 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4448 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4449 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4451 return true;
4454 static bool test_winreg_OpenKey(struct torture_context *tctx,
4455 struct dcerpc_binding_handle *b,
4456 struct policy_handle *hive_handle,
4457 const char *keyname,
4458 struct policy_handle *key_handle)
4460 return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4461 REG_OPTION_NON_VOLATILE, key_handle);
4464 static bool test_winreg_CloseKey(struct torture_context *tctx,
4465 struct dcerpc_binding_handle *b,
4466 struct policy_handle *handle)
4468 struct winreg_CloseKey r;
4470 r.in.handle = handle;
4471 r.out.handle = handle;
4473 torture_comment(tctx, "Testing winreg_CloseKey\n");
4475 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4476 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4478 return true;
4481 bool test_winreg_QueryValue(struct torture_context *tctx,
4482 struct dcerpc_binding_handle *b,
4483 struct policy_handle *handle,
4484 const char *value_name,
4485 enum winreg_Type *type_p,
4486 uint32_t *data_size_p,
4487 uint32_t *data_length_p,
4488 uint8_t **data_p)
4490 struct winreg_QueryValue r;
4491 enum winreg_Type type = REG_NONE;
4492 uint32_t data_size = 0;
4493 uint32_t data_length = 0;
4494 struct winreg_String valuename;
4495 uint8_t *data = NULL;
4497 init_winreg_String(&valuename, value_name);
4499 data = talloc_zero_array(tctx, uint8_t, 0);
4501 r.in.handle = handle;
4502 r.in.value_name = &valuename;
4503 r.in.type = &type;
4504 r.in.data_size = &data_size;
4505 r.in.data_length = &data_length;
4506 r.in.data = data;
4507 r.out.type = &type;
4508 r.out.data = data;
4509 r.out.data_size = &data_size;
4510 r.out.data_length = &data_length;
4512 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4514 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4515 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4516 *r.in.data_size = *r.out.data_size;
4517 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4518 r.in.data = data;
4519 r.out.data = data;
4520 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4522 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4524 if (type_p) {
4525 *type_p = *r.out.type;
4527 if (data_size_p) {
4528 *data_size_p = *r.out.data_size;
4530 if (data_length_p) {
4531 *data_length_p = *r.out.data_length;
4533 if (data_p) {
4534 *data_p = r.out.data;
4537 return true;
4540 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4541 struct dcerpc_binding_handle *b,
4542 struct policy_handle *handle,
4543 const char *printer_name,
4544 const char *key_name,
4545 const char *value_name,
4546 enum winreg_Type *w_type,
4547 uint32_t *w_size,
4548 uint32_t *w_length,
4549 uint8_t **w_data)
4551 const char *printer_key;
4552 struct policy_handle key_handle;
4554 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4555 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4557 torture_assert(tctx,
4558 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4560 torture_assert(tctx,
4561 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4563 torture_assert(tctx,
4564 test_winreg_CloseKey(tctx, b, &key_handle), "");
4566 return true;
4569 static bool test_GetForm_winreg(struct torture_context *tctx,
4570 struct dcerpc_binding_handle *b,
4571 struct policy_handle *handle,
4572 const char *key_name,
4573 const char *form_name,
4574 enum winreg_Type *w_type,
4575 uint32_t *w_size,
4576 uint32_t *w_length,
4577 uint8_t **w_data)
4579 struct policy_handle key_handle;
4581 torture_assert(tctx,
4582 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4584 torture_assert(tctx,
4585 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4587 torture_assert(tctx,
4588 test_winreg_CloseKey(tctx, b, &key_handle), "");
4590 return true;
4593 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4594 struct dcerpc_binding_handle *b,
4595 struct policy_handle *handle,
4596 const char *symlink_keyname,
4597 const char *symlink_destination)
4599 /* check if the first key is a symlink to the second key */
4601 enum winreg_Type w_type;
4602 uint32_t w_size;
4603 uint32_t w_length;
4604 uint8_t *w_data;
4605 struct policy_handle key_handle;
4606 DATA_BLOB blob;
4607 const char *str;
4609 if (torture_setting_bool(tctx, "samba3", false)) {
4610 torture_skip(tctx, "skip winreg symlink test against samba");
4613 torture_assert(tctx,
4614 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4615 "failed to open key link");
4617 torture_assert(tctx,
4618 test_winreg_QueryValue(tctx, b, &key_handle,
4619 "SymbolicLinkValue",
4620 &w_type, &w_size, &w_length, &w_data),
4621 "failed to query for 'SymbolicLinkValue' attribute");
4623 torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4625 blob = data_blob(w_data, w_size);
4626 str = reg_val_data_string(tctx, REG_SZ, blob);
4628 torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4630 torture_assert(tctx,
4631 test_winreg_CloseKey(tctx, b, &key_handle),
4632 "failed to close key link");
4634 return true;
4637 static const char *strip_unc(const char *unc)
4639 char *name;
4641 if (!unc) {
4642 return NULL;
4645 if (unc[0] == '\\' && unc[1] == '\\') {
4646 unc +=2;
4649 name = strchr(unc, '\\');
4650 if (name) {
4651 return name+1;
4654 return unc;
4657 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4658 struct dcerpc_binding_handle *b,
4659 struct policy_handle *handle,
4660 const char *printer_name,
4661 struct dcerpc_binding_handle *winreg_handle,
4662 struct policy_handle *hive_handle)
4664 union spoolss_PrinterInfo info;
4665 const char *keys[] = {
4666 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4667 TOP_LEVEL_PRINT_PRINTERS_KEY
4669 int i;
4670 const char *printername, *sharename;
4672 torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4674 torture_assert(tctx,
4675 test_GetPrinter_level(tctx, b, handle, 2, &info),
4676 "failed to get printer info level 2");
4678 printername = strip_unc(info.info2.printername);
4679 sharename = strip_unc(info.info2.sharename);
4681 #define test_sz(wname, iname) \
4682 do {\
4683 DATA_BLOB blob;\
4684 const char *str;\
4685 enum winreg_Type w_type;\
4686 uint32_t w_size;\
4687 uint32_t w_length;\
4688 uint8_t *w_data;\
4689 torture_assert(tctx,\
4690 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4691 &w_type, &w_size, &w_length, &w_data),\
4692 "failed to query winreg");\
4693 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4694 blob = data_blob(w_data, w_size);\
4695 str = reg_val_data_string(tctx, REG_SZ, blob);\
4696 if (w_size == 2 && iname == NULL) {\
4697 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4698 } else {\
4699 torture_assert_str_equal(tctx, str, iname,\
4700 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4702 } while(0);
4704 #define test_dword(wname, iname) \
4705 do {\
4706 uint32_t value;\
4707 enum winreg_Type w_type;\
4708 uint32_t w_size;\
4709 uint32_t w_length;\
4710 uint8_t *w_data;\
4711 torture_assert(tctx,\
4712 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4713 &w_type, &w_size, &w_length, &w_data),\
4714 "failed to query winreg");\
4715 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4716 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4717 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4718 value = IVAL(w_data, 0);\
4719 torture_assert_int_equal(tctx, value, iname,\
4720 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4721 } while(0);
4723 #define test_binary(wname, iname) \
4724 do {\
4725 enum winreg_Type w_type;\
4726 uint32_t w_size;\
4727 uint32_t w_length;\
4728 uint8_t *w_data;\
4729 torture_assert(tctx,\
4730 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4731 &w_type, &w_size, &w_length, &w_data),\
4732 "failed to query winreg");\
4733 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4734 torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4735 torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4736 "binary unequal");\
4737 } while(0);
4740 #define test_dm(wname, iname) \
4741 do {\
4742 DATA_BLOB blob;\
4743 struct spoolss_DeviceMode dm;\
4744 enum ndr_err_code ndr_err;\
4745 enum winreg_Type w_type;\
4746 uint32_t w_size;\
4747 uint32_t w_length;\
4748 uint8_t *w_data;\
4749 torture_assert(tctx,\
4750 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4751 &w_type, &w_size, &w_length, &w_data),\
4752 "failed to query winreg");\
4753 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4754 blob = data_blob(w_data, w_size);\
4755 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4756 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4757 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4758 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4759 "dm unequal");\
4760 } while(0);
4762 #define test_sd(wname, iname) \
4763 do {\
4764 DATA_BLOB blob;\
4765 struct security_descriptor sd;\
4766 enum ndr_err_code ndr_err;\
4767 enum winreg_Type w_type;\
4768 uint32_t w_size;\
4769 uint32_t w_length;\
4770 uint8_t *w_data;\
4771 torture_assert(tctx,\
4772 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4773 &w_type, &w_size, &w_length, &w_data),\
4774 "failed to query winreg");\
4775 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4776 blob = data_blob(w_data, w_size);\
4777 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4778 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4779 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4780 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4781 "sd unequal");\
4782 } while(0);
4784 #define test_multi_sz(wname, iname) \
4785 do {\
4786 DATA_BLOB blob;\
4787 const char **array;\
4788 enum winreg_Type w_type;\
4789 uint32_t w_size;\
4790 uint32_t w_length;\
4791 uint8_t *w_data;\
4792 int i;\
4793 torture_assert(tctx,\
4794 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4795 &w_type, &w_size, &w_length, &w_data),\
4796 "failed to query winreg");\
4797 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4798 blob = data_blob(w_data, w_size);\
4799 torture_assert(tctx, \
4800 pull_reg_multi_sz(tctx, &blob, &array),\
4801 "failed to pull multi sz");\
4802 for (i=0; array[i] != NULL; i++) {\
4803 torture_assert_str_equal(tctx, array[i], iname[i],\
4804 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4806 } while(0);
4808 if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4809 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4810 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4812 torture_warning(tctx, "failed to check for winreg symlink");
4815 for (i=0; i < ARRAY_SIZE(keys); i++) {
4817 const char *printer_key;
4818 struct policy_handle key_handle;
4820 printer_key = talloc_asprintf(tctx, "%s\\%s",
4821 keys[i], printer_name);
4823 torture_assert(tctx,
4824 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4826 test_sz("Name", printername);
4827 test_sz("Share Name", sharename);
4828 test_sz("Port", info.info2.portname);
4829 test_sz("Printer Driver", info.info2.drivername);
4830 test_sz("Description", info.info2.comment);
4831 test_sz("Location", info.info2.location);
4832 test_sz("Separator File", info.info2.sepfile);
4833 test_sz("Print Processor", info.info2.printprocessor);
4834 test_sz("Datatype", info.info2.datatype);
4835 test_sz("Parameters", info.info2.parameters);
4836 /* winreg: 0, spoolss not */
4837 /* test_dword("Attributes", info.info2.attributes); */
4838 test_dword("Priority", info.info2.priority);
4839 test_dword("Default Priority", info.info2.defaultpriority);
4840 /* winreg: 60, spoolss: 0 */
4841 /* test_dword("StartTime", info.info2.starttime); */
4842 /* test_dword("UntilTime", info.info2.untiltime); */
4843 /* winreg != spoolss */
4844 /* test_dword("Status", info.info2.status); */
4845 test_dm("Default DevMode", info.info2.devmode);
4846 test_sd("Security", info.info2.secdesc);
4848 torture_assert(tctx,
4849 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4852 #undef test_dm
4853 #undef test_sd
4855 torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4857 return true;
4860 static bool test_PrintProcessors(struct torture_context *tctx,
4861 struct dcerpc_binding_handle *b,
4862 const char *environment,
4863 struct dcerpc_binding_handle *winreg_handle,
4864 struct policy_handle *hive_handle)
4866 union spoolss_PrintProcessorInfo *info;
4867 uint32_t count;
4868 int i;
4870 torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4872 torture_assert(tctx,
4873 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
4874 "failed to enum print processors level 1");
4876 for (i=0; i < count; i++) {
4878 const char *processor_key;
4879 struct policy_handle key_handle;
4881 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4882 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4883 environment,
4884 info[i].info1.print_processor_name);
4886 torture_assert(tctx,
4887 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4889 /* nothing to check in there so far */
4891 torture_assert(tctx,
4892 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4895 torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4897 return true;
4900 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4901 struct dcerpc_binding_handle *b,
4902 struct policy_handle *handle,
4903 const char *driver_name,
4904 const char *architecture,
4905 uint32_t level,
4906 uint32_t client_major_version,
4907 uint32_t client_minor_version,
4908 union spoolss_DriverInfo *info_p,
4909 WERROR *result);
4911 static const char *strip_path(const char *path)
4913 char *p;
4915 if (path == NULL) {
4916 return NULL;
4919 p = strrchr(path, '\\');
4920 if (p) {
4921 return p+1;
4924 return path;
4927 static const char **strip_paths(const char **path_array)
4929 int i;
4931 if (path_array == NULL) {
4932 return NULL;
4935 for (i=0; path_array[i] != NULL; i++) {
4936 path_array[i] = strip_path(path_array[i]);
4939 return path_array;
4942 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4944 time_t t;
4945 struct tm *tm;
4947 if (nt == 0) {
4948 return talloc_strdup(mem_ctx, "01/01/1601");
4951 t = nt_time_to_unix(nt);
4952 tm = localtime(&t);
4954 return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4955 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4958 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4960 return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4961 (unsigned)((v >> 48) & 0xFFFF),
4962 (unsigned)((v >> 32) & 0xFFFF),
4963 (unsigned)((v >> 16) & 0xFFFF),
4964 (unsigned)(v & 0xFFFF));
4967 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4968 struct dcerpc_binding_handle *b,
4969 struct policy_handle *handle,
4970 const char *printer_name,
4971 const char *driver_name,
4972 const char *environment,
4973 enum spoolss_DriverOSVersion version,
4974 struct dcerpc_binding_handle *winreg_handle,
4975 struct policy_handle *hive_handle,
4976 const char *server_name_slash)
4978 WERROR result = WERR_OK;
4979 union spoolss_DriverInfo info;
4980 const char *driver_key;
4981 struct policy_handle key_handle;
4983 const char *driver_path;
4984 const char *data_file;
4985 const char *config_file;
4986 const char *help_file;
4987 const char **dependent_files;
4989 const char *driver_date;
4990 const char *inbox_driver_date;
4992 const char *driver_version;
4993 const char *inbox_driver_version;
4995 ZERO_STRUCT(key_handle);
4997 torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4999 driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
5000 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
5001 environment,
5002 version,
5003 driver_name);
5005 torture_assert(tctx,
5006 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
5007 "failed to open driver key");
5009 if (torture_setting_bool(tctx, "samba3", false) ||
5010 torture_setting_bool(tctx, "w2k3", false)) {
5011 goto try_level6;
5014 if (handle) {
5015 torture_assert(tctx,
5016 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
5017 "failed to get driver info level 8");
5018 } else {
5019 torture_assert(tctx,
5020 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
5021 "failed to get driver info level 8");
5024 if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
5025 goto try_level6;
5028 driver_path = strip_path(info.info8.driver_path);
5029 data_file = strip_path(info.info8.data_file);
5030 config_file = strip_path(info.info8.config_file);
5031 help_file = strip_path(info.info8.help_file);
5032 dependent_files = strip_paths(info.info8.dependent_files);
5034 driver_date = driver_winreg_date(tctx, info.info8.driver_date);
5035 inbox_driver_date = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
5037 driver_version = driver_winreg_version(tctx, info.info8.driver_version);
5038 inbox_driver_version = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
5040 test_sz("Configuration File", config_file);
5041 test_sz("Data File", data_file);
5042 test_sz("Datatype", info.info8.default_datatype);
5043 test_sz("Driver", driver_path);
5044 test_sz("DriverDate", driver_date);
5045 test_sz("DriverVersion", driver_version);
5046 test_sz("HardwareID", info.info8.hardware_id);
5047 test_sz("Help File", help_file);
5048 test_sz("InfPath", info.info8.inf_path);
5049 test_sz("Manufacturer", info.info8.manufacturer_name);
5050 test_sz("MinInboxDriverVerDate", inbox_driver_date);
5051 test_sz("MinInboxDriverVerVersion", inbox_driver_version);
5052 test_sz("Monitor", info.info8.monitor_name);
5053 test_sz("OEM URL", info.info8.manufacturer_url);
5054 test_sz("Print Processor", info.info8.print_processor);
5055 test_sz("Provider", info.info8.provider);
5056 test_sz("VendorSetup", info.info8.vendor_setup);
5057 test_multi_sz("ColorProfiles", info.info8.color_profiles);
5058 test_multi_sz("Dependent Files", dependent_files);
5059 test_multi_sz("CoreDependencies", info.info8.core_driver_dependencies);
5060 test_multi_sz("Previous Names", info.info8.previous_names);
5061 /* test_dword("Attributes", ?); */
5062 test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
5063 test_dword("Version", info.info8.version);
5064 /* test_dword("TempDir", ?); */
5066 try_level6:
5068 if (handle) {
5069 torture_assert(tctx,
5070 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
5071 "failed to get driver info level 6");
5072 } else {
5073 torture_assert(tctx,
5074 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
5075 "failed to get driver info level 6");
5078 driver_path = strip_path(info.info6.driver_path);
5079 data_file = strip_path(info.info6.data_file);
5080 config_file = strip_path(info.info6.config_file);
5081 help_file = strip_path(info.info6.help_file);
5082 dependent_files = strip_paths(info.info6.dependent_files);
5084 driver_date = driver_winreg_date(tctx, info.info6.driver_date);
5086 driver_version = driver_winreg_version(tctx, info.info6.driver_version);
5088 test_sz("Configuration File", config_file);
5089 test_sz("Data File", data_file);
5090 test_sz("Datatype", info.info6.default_datatype);
5091 test_sz("Driver", driver_path);
5092 if (torture_setting_bool(tctx, "w2k3", false)) {
5093 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
5094 push_nttime(blob.data, 0, info.info6.driver_date);
5095 test_binary("DriverDate", blob);
5096 SBVAL(blob.data, 0, info.info6.driver_version);
5097 test_binary("DriverVersion", blob);
5098 } else {
5099 test_sz("DriverDate", driver_date);
5100 test_sz("DriverVersion", driver_version);
5102 test_sz("HardwareID", info.info6.hardware_id);
5103 test_sz("Help File", help_file);
5104 test_sz("Manufacturer", info.info6.manufacturer_name);
5105 test_sz("Monitor", info.info6.monitor_name);
5106 test_sz("OEM URL", info.info6.manufacturer_url);
5107 test_sz("Provider", info.info6.provider);
5108 test_multi_sz("Dependent Files", dependent_files);
5109 test_multi_sz("Previous Names", info.info6.previous_names);
5110 /* test_dword("Attributes", ?); */
5111 test_dword("Version", info.info6.version);
5112 /* test_dword("TempDir", ?); */
5114 if (handle) {
5115 torture_assert(tctx,
5116 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
5117 "failed to get driver info level 3");
5118 } else {
5119 torture_assert(tctx,
5120 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
5121 "failed to get driver info level 3");
5124 driver_path = strip_path(info.info3.driver_path);
5125 data_file = strip_path(info.info3.data_file);
5126 config_file = strip_path(info.info3.config_file);
5127 help_file = strip_path(info.info3.help_file);
5128 dependent_files = strip_paths(info.info3.dependent_files);
5130 test_sz("Configuration File", config_file);
5131 test_sz("Data File", data_file);
5132 test_sz("Datatype", info.info3.default_datatype);
5133 test_sz("Driver", driver_path);
5134 test_sz("Help File", help_file);
5135 test_sz("Monitor", info.info3.monitor_name);
5136 test_multi_sz("Dependent Files", dependent_files);
5137 /* test_dword("Attributes", ?); */
5138 test_dword("Version", info.info3.version);
5139 /* test_dword("TempDir", ?); */
5142 torture_assert(tctx,
5143 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
5145 torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
5147 return true;
5150 #undef test_sz
5151 #undef test_dword
5153 static bool test_SetPrinterData(struct torture_context *tctx,
5154 struct dcerpc_binding_handle *b,
5155 struct policy_handle *handle,
5156 const char *value_name,
5157 enum winreg_Type type,
5158 uint8_t *data,
5159 uint32_t offered)
5161 struct spoolss_SetPrinterData r;
5163 r.in.handle = handle;
5164 r.in.value_name = value_name;
5165 r.in.type = type;
5166 r.in.data = data;
5167 r.in.offered = offered;
5169 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
5170 r.in.value_name);
5172 torture_assert_ntstatus_ok(tctx,
5173 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
5174 "SetPrinterData failed");
5175 torture_assert_werr_ok(tctx, r.out.result,
5176 "SetPrinterData failed");
5178 return true;
5181 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
5182 struct dcerpc_binding_handle *b,
5183 struct policy_handle *handle,
5184 const char *printer_name,
5185 struct dcerpc_binding_handle *winreg_handle,
5186 struct policy_handle *hive_handle)
5188 const char *values[] = {
5189 "spootyfoot",
5190 "spooty\\foot",
5191 #if 0
5192 /* FIXME: not working with s3 atm. */
5193 "spooty,foot",
5194 "spooty,fo,ot",
5195 #endif
5196 "spooty foot",
5197 #if 0
5198 /* FIXME: not working with s3 atm. */
5199 "spooty\\fo,ot",
5200 "spooty,fo\\ot"
5201 #endif
5203 int i;
5205 for (i=0; i < ARRAY_SIZE(values); i++) {
5207 enum winreg_Type type, expected_type = REG_SZ;
5208 DATA_BLOB blob;
5209 uint8_t *data;
5210 uint32_t needed;
5212 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
5213 type = REG_SZ;
5215 torture_assert(tctx,
5216 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
5217 "SetPrinterData failed");
5219 torture_assert(tctx,
5220 test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
5221 "GetPrinterData failed");
5223 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
5224 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
5225 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
5227 if (winreg_handle && hive_handle) {
5229 enum winreg_Type w_type;
5230 uint32_t w_size;
5231 uint32_t w_length;
5232 uint8_t *w_data;
5234 torture_assert(tctx,
5235 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5236 printer_name, "PrinterDriverData", values[i],
5237 &w_type, &w_size, &w_length, &w_data), "");
5239 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
5240 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
5241 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
5242 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
5245 torture_assert(tctx,
5246 test_DeletePrinterData(tctx, b, handle, values[i]),
5247 "DeletePrinterData failed");
5250 return true;
5254 static bool test_EnumPrinterKey(struct torture_context *tctx,
5255 struct dcerpc_binding_handle *b,
5256 struct policy_handle *handle,
5257 const char *key_name,
5258 const char ***array);
5260 static bool test_SetPrinterDataEx(struct torture_context *tctx,
5261 struct dcerpc_binding_handle *b,
5262 struct policy_handle *handle,
5263 const char *key_name,
5264 const char *value_name,
5265 enum winreg_Type type,
5266 uint8_t *data,
5267 uint32_t offered)
5269 NTSTATUS status;
5270 struct spoolss_SetPrinterDataEx r;
5272 r.in.handle = handle;
5273 r.in.key_name = key_name;
5274 r.in.value_name = value_name;
5275 r.in.type = type;
5276 r.in.data = data;
5277 r.in.offered = offered;
5279 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
5280 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
5282 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
5284 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
5285 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
5287 return true;
5290 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
5291 struct dcerpc_pipe *p,
5292 struct policy_handle *handle)
5294 struct dcerpc_binding_handle *b = p->binding_handle;
5295 const char *value_name = "dog";
5296 const char *keys[] = {
5297 "torturedataex",
5298 "torture data ex",
5299 "torturedataex_with_subkey\\subkey",
5300 "torturedataex_with_subkey\\subkey:0",
5301 "torturedataex_with_subkey\\subkey:1",
5302 "torturedataex_with_subkey\\subkey\\subsubkey",
5303 "torturedataex_with_subkey\\subkey\\subsubkey:0",
5304 "torturedataex_with_subkey\\subkey\\subsubkey:1",
5305 "torture,data",
5306 "torture,data,ex",
5307 "torture,data\\ex",
5308 "torture\\data,ex",
5309 "torture/data",
5310 "torture/data ex",
5311 "torture/data ex/sub",
5312 "torture//data",
5313 "torture//data ex",
5314 "torture//data ex/sub",
5315 "torture//data ex//sub",
5317 int i;
5319 for (i=0; i < ARRAY_SIZE(keys); i++) {
5321 char *c;
5322 const char *key;
5323 enum winreg_Type type;
5324 DATA_BLOB blob_in, blob_out;
5325 const char **subkeys;
5326 uint32_t ecount;
5327 struct spoolss_PrinterEnumValues *einfo;
5328 uint32_t needed;
5330 blob_in = data_blob_talloc(tctx, NULL, 42);
5332 generate_random_buffer(blob_in.data, blob_in.length);
5334 torture_assert(tctx,
5335 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
5336 "failed to call SetPrinterDataEx");
5338 torture_assert(tctx,
5339 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
5340 "failed to call GetPrinterDataEx");
5342 blob_out.length = needed;
5343 torture_assert(tctx,
5344 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
5345 "failed to call EnumPrinterDataEx");
5347 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5348 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5349 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5351 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5352 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5353 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5354 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5355 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5356 if (einfo[0].data_length > 0) {
5357 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5360 key = talloc_strdup(tctx, keys[i]);
5362 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
5363 return false;
5366 c = strchr(key, '\\');
5367 if (c) {
5368 int k;
5370 /* we have subkeys */
5372 *c = 0;
5374 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
5375 return false;
5378 for (k=0; subkeys && subkeys[k]; k++) {
5380 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
5382 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
5383 return false;
5387 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5388 return false;
5391 } else {
5392 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5393 return false;
5398 return true;
5401 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
5402 struct dcerpc_pipe *p,
5403 struct policy_handle *handle)
5405 struct dcerpc_binding_handle *b = p->binding_handle;
5406 const char *key = "torturedataex";
5407 const char *values[] = {
5408 "torture_value",
5409 "torture value",
5410 "torture,value",
5411 "torture/value",
5412 "torture\\value",
5413 "torture\\\\value"
5415 int i;
5417 for (i=0; i < ARRAY_SIZE(values); i++) {
5419 enum winreg_Type type;
5420 DATA_BLOB blob_in, blob_out;
5421 uint32_t ecount;
5422 struct spoolss_PrinterEnumValues *einfo;
5423 uint32_t needed;
5425 if (torture_setting_bool(tctx, "samba3", false)) {
5426 char *q;
5427 q = strrchr(values[i], ',');
5428 if (q) {
5429 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
5430 values[i]);
5431 continue;
5435 blob_in = data_blob_talloc(tctx, NULL, 42);
5437 generate_random_buffer(blob_in.data, blob_in.length);
5439 torture_assert(tctx,
5440 test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
5441 "failed to call SetPrinterDataEx");
5443 torture_assert(tctx,
5444 test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
5445 "failed to call GetPrinterDataEx");
5447 blob_out.length = needed;
5448 torture_assert(tctx,
5449 test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
5450 "failed to call EnumPrinterDataEx");
5452 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5453 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5454 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5456 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5457 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5458 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5459 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5460 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5461 if (einfo[0].data_length > 0) {
5462 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5465 torture_assert(tctx,
5466 test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5467 "failed to call DeletePrinterDataEx");
5470 return true;
5474 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5475 struct dcerpc_pipe *p,
5476 struct policy_handle *handle,
5477 const char *printername,
5478 struct dcerpc_binding_handle *winreg_handle,
5479 struct policy_handle *hive_handle)
5481 struct dcerpc_binding_handle *b = p->binding_handle;
5482 const char *value_name = "dog";
5483 const char *key_name = "torturedataex";
5484 enum winreg_Type types[] = {
5485 REG_SZ,
5486 REG_MULTI_SZ,
5487 REG_DWORD,
5488 REG_BINARY
5490 const char *str = "abcdefghi";
5491 int t, s;
5493 for (t=0; t < ARRAY_SIZE(types); t++) {
5494 for (s=0; s < strlen(str); s++) {
5496 enum winreg_Type type;
5497 const char *string = talloc_strndup(tctx, str, s);
5498 const char *array[2];
5499 DATA_BLOB blob = data_blob_string_const(string);
5500 DATA_BLOB data;
5501 uint8_t *data_out;
5502 uint32_t needed, offered = 0;
5503 uint32_t ecount;
5504 struct spoolss_PrinterEnumValues *einfo;
5506 array[0] = talloc_strdup(tctx, string);
5507 array[1] = NULL;
5509 if (types[t] == REG_DWORD) {
5510 s = 0xffff;
5513 switch (types[t]) {
5514 case REG_BINARY:
5515 data = blob;
5516 offered = blob.length;
5517 break;
5518 case REG_DWORD:
5519 data = data_blob_talloc(tctx, NULL, 4);
5520 SIVAL(data.data, 0, 0x12345678);
5521 offered = 4;
5522 break;
5523 case REG_SZ:
5524 torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5525 type = REG_SZ;
5526 offered = data.length;
5527 /*strlen_m_term(data.string)*2;*/
5528 break;
5529 case REG_MULTI_SZ:
5530 torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5531 type = REG_MULTI_SZ;
5532 offered = data.length;
5533 break;
5534 default:
5535 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5538 torture_assert(tctx,
5539 test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5540 "failed to call SetPrinterDataEx");
5542 torture_assert(tctx,
5543 test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
5544 "failed to call GetPrinterDataEx");
5546 torture_assert(tctx,
5547 test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5548 "failed to call EnumPrinterDataEx");
5550 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5551 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5552 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5554 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5555 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5556 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5557 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5558 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5559 if (einfo[0].data_length > 0) {
5560 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5563 if (winreg_handle && hive_handle) {
5564 enum winreg_Type w_type;
5565 uint32_t w_size;
5566 uint32_t w_length;
5567 uint8_t *w_data;
5569 torture_assert(tctx,
5570 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5571 printername, key_name, value_name,
5572 &w_type, &w_size, &w_length, &w_data), "");
5574 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5575 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5576 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5577 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5580 torture_assert(tctx,
5581 test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5582 "failed to call DeletePrinterDataEx");
5586 return true;
5589 static bool test_PrinterData_winreg(struct torture_context *tctx,
5590 struct dcerpc_pipe *p,
5591 struct policy_handle *handle,
5592 const char *printer_name)
5594 struct dcerpc_binding_handle *b = p->binding_handle;
5595 struct dcerpc_pipe *p2;
5596 bool ret = true;
5597 struct policy_handle hive_handle;
5598 struct dcerpc_binding_handle *b2;
5600 torture_assert_ntstatus_ok(tctx,
5601 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5602 "could not open winreg pipe");
5603 b2 = p2->binding_handle;
5605 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5607 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5608 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5610 test_winreg_CloseKey(tctx, b2, &hive_handle);
5612 talloc_free(p2);
5614 return ret;
5617 static bool test_Forms_winreg(struct torture_context *tctx,
5618 struct dcerpc_binding_handle *b,
5619 struct policy_handle *handle,
5620 bool print_server,
5621 const char *printer_name)
5623 struct dcerpc_pipe *p2;
5624 bool ret = true;
5625 struct policy_handle hive_handle;
5626 struct dcerpc_binding_handle *b2;
5628 torture_assert_ntstatus_ok(tctx,
5629 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5630 "could not open winreg pipe");
5631 b2 = p2->binding_handle;
5633 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5635 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5637 test_winreg_CloseKey(tctx, b2, &hive_handle);
5639 talloc_free(p2);
5641 return ret;
5644 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5645 struct dcerpc_pipe *p,
5646 struct policy_handle *handle,
5647 const char *printer_name)
5649 struct dcerpc_binding_handle *b = p->binding_handle;
5650 struct dcerpc_pipe *p2;
5651 bool ret = true;
5652 struct policy_handle hive_handle;
5653 struct dcerpc_binding_handle *b2;
5655 torture_assert_ntstatus_ok(tctx,
5656 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5657 "could not open winreg pipe");
5658 b2 = p2->binding_handle;
5660 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5662 ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5664 test_winreg_CloseKey(tctx, b2, &hive_handle);
5666 talloc_free(p2);
5668 return ret;
5671 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5672 struct dcerpc_pipe *p,
5673 struct policy_handle *handle,
5674 const char *printer_name,
5675 const char *driver_name,
5676 const char *environment,
5677 enum spoolss_DriverOSVersion version)
5679 struct dcerpc_binding_handle *b = p->binding_handle;
5680 struct dcerpc_pipe *p2;
5681 bool ret = true;
5682 struct policy_handle hive_handle;
5683 struct dcerpc_binding_handle *b2;
5685 torture_assert_ntstatus_ok(tctx,
5686 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5687 "could not open winreg pipe");
5688 b2 = p2->binding_handle;
5690 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5692 ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
5694 test_winreg_CloseKey(tctx, b2, &hive_handle);
5696 talloc_free(p2);
5698 return ret;
5701 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5702 struct dcerpc_binding_handle *b,
5703 const char *environment)
5705 struct dcerpc_pipe *p2;
5706 bool ret = true;
5707 struct policy_handle hive_handle;
5708 struct dcerpc_binding_handle *b2;
5710 torture_assert_ntstatus_ok(tctx,
5711 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5712 "could not open winreg pipe");
5713 b2 = p2->binding_handle;
5715 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5717 ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5719 test_winreg_CloseKey(tctx, b2, &hive_handle);
5721 talloc_free(p2);
5723 return ret;
5726 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5727 struct dcerpc_pipe *p,
5728 struct policy_handle *handle,
5729 const char *printer_name)
5731 struct spoolss_SetPrinterInfoCtr info_ctr;
5732 struct spoolss_DevmodeContainer devmode_ctr;
5733 struct sec_desc_buf secdesc_ctr;
5734 union spoolss_SetPrinterInfo sinfo;
5735 union spoolss_PrinterInfo info;
5736 struct dcerpc_binding_handle *b = p->binding_handle;
5737 const char *pname;
5739 ZERO_STRUCT(info_ctr);
5740 ZERO_STRUCT(devmode_ctr);
5741 ZERO_STRUCT(secdesc_ctr);
5743 torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5745 torture_assert(tctx,
5746 test_GetPrinter_level(tctx, b, handle, 2, &info),
5747 "failed to query Printer level 2");
5749 torture_assert(tctx,
5750 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5751 "failed to convert");
5753 info_ctr.level = 2;
5754 info_ctr.info = sinfo;
5756 #define TEST_SZ(wname, iname) \
5757 do {\
5758 enum winreg_Type type;\
5759 uint8_t *data;\
5760 uint32_t needed;\
5761 DATA_BLOB blob;\
5762 const char *str;\
5763 torture_assert(tctx,\
5764 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5765 "failed to query");\
5766 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5767 blob = data_blob_const(data, needed);\
5768 torture_assert(tctx,\
5769 pull_reg_sz(tctx, &blob, &str),\
5770 "failed to pull REG_SZ");\
5771 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5772 } while(0);
5775 #define TEST_SET_SZ(wname, iname, val) \
5776 do {\
5777 enum winreg_Type type;\
5778 uint8_t *data;\
5779 uint32_t needed;\
5780 DATA_BLOB blob;\
5781 const char *str;\
5782 sinfo.info2->iname = val;\
5783 torture_assert(tctx,\
5784 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5785 "failed to call SetPrinter");\
5786 torture_assert(tctx,\
5787 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5788 "failed to query");\
5789 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5790 blob = data_blob_const(data, needed);\
5791 torture_assert(tctx,\
5792 pull_reg_sz(tctx, &blob, &str),\
5793 "failed to pull REG_SZ");\
5794 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5795 } while(0);
5797 #define TEST_SET_DWORD(wname, iname, val) \
5798 do {\
5799 enum winreg_Type type;\
5800 uint8_t *data;\
5801 uint32_t needed;\
5802 uint32_t value;\
5803 sinfo.info2->iname = val;\
5804 torture_assert(tctx,\
5805 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5806 "failed to call SetPrinter");\
5807 torture_assert(tctx,\
5808 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5809 "failed to query");\
5810 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5811 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5812 value = IVAL(data, 0); \
5813 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5814 } while(0);
5816 TEST_SET_SZ("description", comment, "newval");
5817 TEST_SET_SZ("location", location, "newval");
5818 TEST_SET_SZ("driverName", drivername, "newval");
5819 /* TEST_SET_DWORD("priority", priority, 25); */
5821 torture_assert(tctx,
5822 test_GetPrinter_level(tctx, b, handle, 2, &info),
5823 "failed to query Printer level 2");
5825 TEST_SZ("description", info.info2.comment);
5826 TEST_SZ("driverName", info.info2.drivername);
5827 TEST_SZ("location", info.info2.location);
5829 pname = strrchr(info.info2.printername, '\\');
5830 if (pname == NULL) {
5831 pname = info.info2.printername;
5832 } else {
5833 pname++;
5835 TEST_SZ("printerName", pname);
5836 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5837 /* TEST_SZ("printShareName", info.info2.sharename); */
5839 /* FIXME gd: complete the list */
5841 #undef TEST_SZ
5842 #undef TEST_SET_SZ
5843 #undef TEST_DWORD
5845 torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5847 return true;
5850 static bool test_print_processors_winreg(struct torture_context *tctx,
5851 void *private_data)
5853 struct test_spoolss_context *ctx =
5854 talloc_get_type_abort(private_data, struct test_spoolss_context);
5855 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5856 struct dcerpc_binding_handle *b = p->binding_handle;
5858 return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5861 static bool test_AddPrintProcessor(struct torture_context *tctx,
5862 struct dcerpc_binding_handle *b,
5863 const char *environment,
5864 const char *path_name,
5865 const char *print_processor_name,
5866 WERROR expected_error)
5868 struct spoolss_AddPrintProcessor r;
5870 r.in.server = NULL;
5871 r.in.architecture = environment;
5872 r.in.path_name = path_name;
5873 r.in.print_processor_name = print_processor_name;
5875 torture_comment(tctx, "Testing AddPrintProcessor(%s)\n",
5876 print_processor_name);
5878 torture_assert_ntstatus_ok(tctx,
5879 dcerpc_spoolss_AddPrintProcessor_r(b, tctx, &r),
5880 "spoolss_AddPrintProcessor failed");
5881 torture_assert_werr_equal(tctx, r.out.result, expected_error,
5882 "spoolss_AddPrintProcessor failed");
5884 return true;
5887 static bool test_DeletePrintProcessor(struct torture_context *tctx,
5888 struct dcerpc_binding_handle *b,
5889 const char *environment,
5890 const char *print_processor_name,
5891 WERROR expected_error)
5893 struct spoolss_DeletePrintProcessor r;
5895 r.in.server = NULL;
5896 r.in.architecture = environment;
5897 r.in.print_processor_name = print_processor_name;
5899 torture_comment(tctx, "Testing DeletePrintProcessor(%s)\n",
5900 print_processor_name);
5902 torture_assert_ntstatus_ok(tctx,
5903 dcerpc_spoolss_DeletePrintProcessor_r(b, tctx, &r),
5904 "spoolss_DeletePrintProcessor failed");
5905 torture_assert_werr_equal(tctx, r.out.result, expected_error,
5906 "spoolss_DeletePrintProcessor failed");
5908 return true;
5911 static bool test_add_print_processor(struct torture_context *tctx,
5912 void *private_data)
5914 struct test_spoolss_context *ctx =
5915 talloc_get_type_abort(private_data, struct test_spoolss_context);
5916 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5917 struct dcerpc_binding_handle *b = p->binding_handle;
5918 int i;
5920 struct {
5921 const char *environment;
5922 const char *path_name;
5923 const char *print_processor_name;
5924 WERROR expected_add_result;
5925 WERROR expected_del_result;
5926 } tests[] = {
5928 .environment = ctx->environment,
5929 .path_name = "",
5930 .print_processor_name = "winprint",
5931 .expected_add_result = WERR_PRINT_PROCESSOR_ALREADY_INSTALLED,
5932 .expected_del_result = WERR_CAN_NOT_COMPLETE
5934 .environment = ctx->environment,
5935 .path_name = "",
5936 .print_processor_name = "unknown",
5937 .expected_add_result = WERR_MOD_NOT_FOUND,
5938 .expected_del_result = WERR_UNKNOWN_PRINTPROCESSOR
5942 for (i=0; i < ARRAY_SIZE(tests); i++) {
5943 torture_assert(tctx,
5944 test_AddPrintProcessor(tctx, b,
5945 tests[i].environment,
5946 tests[i].path_name,
5947 tests[i].print_processor_name,
5948 tests[i].expected_add_result),
5949 "add print processor failed");
5950 torture_assert(tctx,
5951 test_DeletePrintProcessor(tctx, b,
5952 tests[i].environment,
5953 tests[i].print_processor_name,
5954 tests[i].expected_del_result),
5955 "delete print processor failed");
5958 return true;
5961 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5962 struct dcerpc_binding_handle *b,
5963 struct policy_handle *handle,
5964 uint32_t *change_id)
5966 enum winreg_Type type;
5967 uint8_t *data;
5968 uint32_t needed;
5970 torture_assert(tctx,
5971 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5972 "failed to call GetPrinterData");
5974 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5975 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5977 *change_id = IVAL(data, 0);
5979 return true;
5982 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5983 struct dcerpc_pipe *p,
5984 struct policy_handle *handle,
5985 uint32_t *change_id)
5987 enum winreg_Type type;
5988 uint8_t *data;
5989 uint32_t needed;
5991 torture_assert(tctx,
5992 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5993 "failed to call GetPrinterData");
5995 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5996 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5998 *change_id = IVAL(data, 0);
6000 return true;
6003 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
6004 struct dcerpc_binding_handle *b,
6005 struct policy_handle *handle,
6006 uint32_t *change_id)
6008 union spoolss_PrinterInfo info;
6010 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
6011 "failed to query Printer level 0");
6013 *change_id = info.info0.change_id;
6015 return true;
6018 static bool test_ChangeID(struct torture_context *tctx,
6019 struct dcerpc_pipe *p,
6020 struct policy_handle *handle)
6022 uint32_t change_id, change_id_ex, change_id_info;
6023 uint32_t change_id2, change_id_ex2, change_id_info2;
6024 union spoolss_PrinterInfo info;
6025 const char *comment;
6026 struct dcerpc_binding_handle *b = p->binding_handle;
6028 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
6030 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6031 "failed to query for ChangeID");
6032 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6033 "failed to query for ChangeID");
6034 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6035 "failed to query for ChangeID");
6037 torture_assert_int_equal(tctx, change_id, change_id_ex,
6038 "change_ids should all be equal");
6039 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
6040 "change_ids should all be equal");
6043 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
6045 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6046 "failed to query for ChangeID");
6047 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
6048 "failed to query Printer level 2");
6049 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6050 "failed to query for ChangeID");
6051 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6052 "failed to query for ChangeID");
6053 torture_assert_int_equal(tctx, change_id, change_id_ex,
6054 "change_id should not have changed");
6055 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
6056 "change_id should not have changed");
6059 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
6061 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
6062 "failed to query for ChangeID");
6063 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
6064 "failed to query for ChangeID");
6065 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
6066 "failed to query for ChangeID");
6067 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
6068 "failed to query Printer level 2");
6069 comment = talloc_strdup(tctx, info.info2.comment);
6072 struct spoolss_SetPrinterInfoCtr info_ctr;
6073 struct spoolss_DevmodeContainer devmode_ctr;
6074 struct sec_desc_buf secdesc_ctr;
6075 union spoolss_SetPrinterInfo sinfo;
6077 ZERO_STRUCT(info_ctr);
6078 ZERO_STRUCT(devmode_ctr);
6079 ZERO_STRUCT(secdesc_ctr);
6082 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
6083 sinfo.info2->comment = "torture_comment";
6085 info_ctr.level = 2;
6086 info_ctr.info = sinfo;
6088 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6089 "failed to call SetPrinter");
6091 sinfo.info2->comment = comment;
6093 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6094 "failed to call SetPrinter");
6098 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
6099 "failed to query for ChangeID");
6100 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
6101 "failed to query for ChangeID");
6102 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
6103 "failed to query for ChangeID");
6105 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
6106 "change_ids should all be equal");
6107 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
6108 "change_ids should all be equal");
6110 torture_assert(tctx, (change_id < change_id2),
6111 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6112 change_id2, change_id));
6113 torture_assert(tctx, (change_id_ex < change_id_ex2),
6114 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6115 change_id_ex2, change_id_ex));
6116 torture_assert(tctx, (change_id_info < change_id_info2),
6117 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
6118 change_id_info2, change_id_info));
6120 torture_comment(tctx, "ChangeID tests succeeded\n\n");
6122 return true;
6125 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
6126 struct dcerpc_pipe *p,
6127 struct policy_handle *handle)
6129 NTSTATUS status;
6130 struct dcerpc_binding *b;
6131 struct dcerpc_pipe *p2;
6132 struct spoolss_ClosePrinter cp;
6134 /* only makes sense on SMB */
6135 if (p->conn->transport.transport != NCACN_NP) {
6136 return true;
6139 torture_comment(tctx, "Testing close on secondary pipe\n");
6141 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
6142 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
6144 status = dcerpc_secondary_connection(p, &p2, b);
6145 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
6147 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
6148 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
6150 cp.in.handle = handle;
6151 cp.out.handle = handle;
6153 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
6154 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
6155 "ERROR: Allowed close on secondary connection");
6157 talloc_free(p2);
6159 return true;
6162 static bool test_OpenPrinter_badname(struct torture_context *tctx,
6163 struct dcerpc_binding_handle *b, const char *name)
6165 NTSTATUS status;
6166 struct spoolss_OpenPrinter op;
6167 struct spoolss_OpenPrinterEx opEx;
6168 struct policy_handle handle;
6169 bool ret = true;
6171 op.in.printername = name;
6172 op.in.datatype = NULL;
6173 op.in.devmode_ctr.devmode= NULL;
6174 op.in.access_mask = 0;
6175 op.out.handle = &handle;
6177 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
6179 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
6180 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
6181 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
6182 "unexpected result");
6184 if (W_ERROR_IS_OK(op.out.result)) {
6185 ret &=test_ClosePrinter(tctx, b, &handle);
6188 opEx.in.printername = name;
6189 opEx.in.datatype = NULL;
6190 opEx.in.devmode_ctr.devmode = NULL;
6191 opEx.in.access_mask = 0;
6192 opEx.in.userlevel_ctr.level = 1;
6193 opEx.in.userlevel_ctr.user_info.level1 = NULL;
6194 opEx.out.handle = &handle;
6196 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
6198 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
6199 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
6200 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
6201 "unexpected result");
6203 if (W_ERROR_IS_OK(opEx.out.result)) {
6204 ret &=test_ClosePrinter(tctx, b, &handle);
6207 return ret;
6210 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
6211 void *private_data)
6213 struct test_spoolss_context *ctx =
6214 talloc_get_type_abort(private_data, struct test_spoolss_context);
6216 const char *badnames[] = {
6217 "__INVALID_PRINTER__",
6218 "\\\\__INVALID_HOST__",
6220 "\\\\\\",
6221 "\\\\\\__INVALID_PRINTER__"
6223 const char *badname;
6224 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6225 const char *server_name = dcerpc_server_name(p);
6226 struct dcerpc_binding_handle *b = p->binding_handle;
6227 int i;
6229 for (i=0; i < ARRAY_SIZE(badnames); i++) {
6230 torture_assert(tctx,
6231 test_OpenPrinter_badname(tctx, b, badnames[i]),
6232 "");
6235 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
6236 torture_assert(tctx,
6237 test_OpenPrinter_badname(tctx, b, badname),
6238 "");
6240 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
6241 torture_assert(tctx,
6242 test_OpenPrinter_badname(tctx, b, badname),
6243 "");
6245 return true;
6248 static bool test_OpenPrinter(struct torture_context *tctx,
6249 struct dcerpc_pipe *p,
6250 const char *name,
6251 const char *environment,
6252 bool open_only)
6254 NTSTATUS status;
6255 struct spoolss_OpenPrinter r;
6256 struct policy_handle handle;
6257 bool ret = true;
6258 struct dcerpc_binding_handle *b = p->binding_handle;
6260 r.in.printername = name;
6261 r.in.datatype = NULL;
6262 r.in.devmode_ctr.devmode= NULL;
6263 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6264 r.out.handle = &handle;
6266 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
6268 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
6270 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
6272 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
6274 if (open_only) {
6275 goto close_printer;
6278 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6279 ret = false;
6282 if (!torture_setting_bool(tctx, "samba3", false)) {
6283 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6284 ret = false;
6288 close_printer:
6289 if (!test_ClosePrinter(tctx, b, &handle)) {
6290 ret = false;
6293 return ret;
6296 static bool test_OpenPrinterEx(struct torture_context *tctx,
6297 struct dcerpc_binding_handle *b,
6298 const char *printername,
6299 const char *datatype,
6300 struct spoolss_DeviceMode *devmode,
6301 uint32_t access_mask,
6302 struct spoolss_UserLevelCtr *userlevel_ctr,
6303 struct policy_handle *handle,
6304 WERROR expected_result)
6306 struct spoolss_OpenPrinterEx r;
6308 r.in.printername = printername;
6309 r.in.datatype = datatype;
6310 r.in.devmode_ctr.devmode= devmode;
6311 r.in.access_mask = access_mask;
6312 r.in.userlevel_ctr = *userlevel_ctr;
6313 r.out.handle = handle;
6315 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
6317 torture_assert_ntstatus_ok(tctx,
6318 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
6319 "OpenPrinterEx failed");
6321 torture_assert_werr_equal(tctx, r.out.result, expected_result,
6322 "OpenPrinterEx failed");
6324 return true;
6327 static bool call_OpenPrinterEx(struct torture_context *tctx,
6328 struct dcerpc_pipe *p,
6329 const char *name,
6330 struct spoolss_DeviceMode *devmode,
6331 struct policy_handle *handle)
6333 struct spoolss_UserLevelCtr userlevel_ctr;
6334 struct spoolss_UserLevel1 userlevel1;
6335 struct dcerpc_binding_handle *b = p->binding_handle;
6337 userlevel1.size = 1234;
6338 userlevel1.client = "hello";
6339 userlevel1.user = "spottyfoot!";
6340 userlevel1.build = 1;
6341 userlevel1.major = 2;
6342 userlevel1.minor = 3;
6343 userlevel1.processor = 4;
6345 userlevel_ctr.level = 1;
6346 userlevel_ctr.user_info.level1 = &userlevel1;
6348 return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
6349 SEC_FLAG_MAXIMUM_ALLOWED,
6350 &userlevel_ctr,
6351 handle,
6352 WERR_OK);
6355 static bool test_printer_rename(struct torture_context *tctx,
6356 void *private_data)
6358 struct torture_printer_context *t =
6359 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
6360 struct dcerpc_pipe *p = t->spoolss_pipe;
6362 bool ret = true;
6363 union spoolss_PrinterInfo info;
6364 union spoolss_SetPrinterInfo sinfo;
6365 struct spoolss_SetPrinterInfoCtr info_ctr;
6366 struct spoolss_DevmodeContainer devmode_ctr;
6367 struct sec_desc_buf secdesc_ctr;
6368 const char *printer_name;
6369 const char *printer_name_orig;
6370 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
6371 struct policy_handle new_handle;
6372 const char *q;
6373 struct dcerpc_binding_handle *b = p->binding_handle;
6375 ZERO_STRUCT(devmode_ctr);
6376 ZERO_STRUCT(secdesc_ctr);
6378 torture_comment(tctx, "Testing Printer rename operations\n");
6380 torture_assert(tctx,
6381 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
6382 "failed to call GetPrinter level 2");
6384 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
6386 q = strrchr(info.info2.printername, '\\');
6387 if (q) {
6388 torture_warning(tctx,
6389 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6392 torture_assert(tctx,
6393 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
6395 sinfo.info2->printername = printer_name_new;
6397 info_ctr.level = 2;
6398 info_ctr.info = sinfo;
6400 torture_assert(tctx,
6401 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
6402 "failed to call SetPrinter level 2");
6404 torture_assert(tctx,
6405 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
6406 "failed to call GetPrinter level 2");
6408 printer_name = talloc_strdup(tctx, info.info2.printername);
6410 q = strrchr(info.info2.printername, '\\');
6411 if (q) {
6412 torture_warning(tctx,
6413 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6414 q++;
6415 printer_name = q;
6418 torture_assert_str_equal(tctx, printer_name, printer_name_new,
6419 "new printer name was not set");
6421 /* samba currently cannot fully rename printers */
6422 if (!torture_setting_bool(tctx, "samba3", false)) {
6423 torture_assert(tctx,
6424 test_OpenPrinter_badname(tctx, b, printer_name_orig),
6425 "still can open printer with oldname after rename");
6426 } else {
6427 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
6430 torture_assert(tctx,
6431 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
6432 "failed to open printer with new name");
6434 torture_assert(tctx,
6435 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
6436 "failed to call GetPrinter level 2");
6438 torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
6439 "new printer name was not set");
6441 torture_assert(tctx,
6442 test_ClosePrinter(tctx, b, &new_handle),
6443 "failed to close printer");
6445 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
6447 return ret;
6450 static bool test_openprinter(struct torture_context *tctx,
6451 struct dcerpc_binding_handle *b,
6452 const char *real_printername)
6454 struct spoolss_UserLevelCtr userlevel_ctr;
6455 struct policy_handle handle;
6456 struct spoolss_UserLevel1 userlevel1;
6457 const char *printername = NULL;
6458 int i;
6460 struct {
6461 const char *suffix;
6462 WERROR expected_result;
6463 } tests[] = {
6465 .suffix = "rubbish",
6466 .expected_result = WERR_INVALID_PRINTER_NAME
6468 .suffix = ", LocalOnl",
6469 .expected_result = WERR_INVALID_PRINTER_NAME
6471 .suffix = ", localOnly",
6472 .expected_result = WERR_INVALID_PRINTER_NAME
6474 .suffix = ", localonl",
6475 .expected_result = WERR_INVALID_PRINTER_NAME
6477 .suffix = ",LocalOnl",
6478 .expected_result = WERR_INVALID_PRINTER_NAME
6480 .suffix = ",localOnl2",
6481 .expected_result = WERR_INVALID_PRINTER_NAME
6483 .suffix = ", DrvConver2t",
6484 .expected_result = WERR_INVALID_PRINTER_NAME
6486 .suffix = ", drvconvert",
6487 .expected_result = WERR_INVALID_PRINTER_NAME
6489 .suffix = ",drvconvert",
6490 .expected_result = WERR_INVALID_PRINTER_NAME
6492 .suffix = ", DrvConvert",
6493 .expected_result = WERR_OK
6495 .suffix = " , DrvConvert",
6496 .expected_result = WERR_INVALID_PRINTER_NAME
6498 .suffix = ",DrvConvert",
6499 .expected_result = WERR_OK
6501 .suffix = ", DrvConvertsadfasdf",
6502 .expected_result = WERR_OK
6504 .suffix = ",DrvConvertasdfasd",
6505 .expected_result = WERR_OK
6507 .suffix = ", LocalOnly",
6508 .expected_result = WERR_OK
6510 .suffix = " , LocalOnly",
6511 .expected_result = WERR_INVALID_PRINTER_NAME
6513 .suffix = ",LocalOnly",
6514 .expected_result = WERR_OK
6516 .suffix = ", LocalOnlysagi4gjfkd",
6517 .expected_result = WERR_OK
6519 .suffix = ",LocalOnlysagi4gjfkd",
6520 .expected_result = WERR_OK
6524 userlevel1.size = 1234;
6525 userlevel1.client = "hello";
6526 userlevel1.user = "spottyfoot!";
6527 userlevel1.build = 1;
6528 userlevel1.major = 2;
6529 userlevel1.minor = 3;
6530 userlevel1.processor = 4;
6532 userlevel_ctr.level = 1;
6533 userlevel_ctr.user_info.level1 = &userlevel1;
6535 torture_comment(tctx, "Testing openprinterex printername pattern\n");
6537 torture_assert(tctx,
6538 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0,
6539 &userlevel_ctr, &handle,
6540 WERR_OK),
6541 "OpenPrinterEx failed");
6542 test_ClosePrinter(tctx, b, &handle);
6544 for (i=0; i < ARRAY_SIZE(tests); i++) {
6546 printername = talloc_asprintf(tctx, "%s%s",
6547 real_printername,
6548 tests[i].suffix);
6550 torture_assert(tctx,
6551 test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0,
6552 &userlevel_ctr, &handle,
6553 tests[i].expected_result),
6554 "OpenPrinterEx failed");
6555 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6556 test_ClosePrinter(tctx, b, &handle);
6560 return true;
6564 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6565 struct dcerpc_pipe *p,
6566 const char *name,
6567 const char *environment)
6569 struct policy_handle handle;
6570 bool ret = true;
6571 struct dcerpc_binding_handle *b = p->binding_handle;
6573 if (!test_openprinter(tctx, b, name)) {
6574 return false;
6577 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6578 return false;
6581 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6582 ret = false;
6585 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6586 ret = false;
6589 if (!test_EnumForms_all(tctx, b, &handle, false)) {
6590 ret = false;
6593 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6594 ret = false;
6597 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6598 ret = false;
6601 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6602 ret = false;
6605 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6606 ret = false;
6609 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6610 ret = false;
6613 if (!test_printer_all_keys(tctx, b, &handle)) {
6614 ret = false;
6617 if (!test_PausePrinter(tctx, b, &handle)) {
6618 ret = false;
6621 if (!test_DoPrintTest(tctx, b, &handle)) {
6622 ret = false;
6625 if (!test_ResumePrinter(tctx, b, &handle)) {
6626 ret = false;
6629 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
6630 ret = false;
6633 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
6634 ret = false;
6637 if (!torture_setting_bool(tctx, "samba3", false)) {
6638 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6639 ret = false;
6643 if (!test_ClosePrinter(tctx, b, &handle)) {
6644 ret = false;
6647 return ret;
6650 static bool test_EnumPrinters_old(struct torture_context *tctx,
6651 void *private_data)
6653 struct test_spoolss_context *ctx =
6654 talloc_get_type_abort(private_data, struct test_spoolss_context);
6655 struct spoolss_EnumPrinters r;
6656 NTSTATUS status;
6657 uint16_t levels[] = {1, 2, 4, 5};
6658 int i;
6659 bool ret = true;
6660 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6661 struct dcerpc_binding_handle *b = p->binding_handle;
6663 for (i=0;i<ARRAY_SIZE(levels);i++) {
6664 union spoolss_PrinterInfo *info;
6665 int j;
6666 uint32_t needed;
6667 uint32_t count;
6669 r.in.flags = PRINTER_ENUM_LOCAL;
6670 r.in.server = "";
6671 r.in.level = levels[i];
6672 r.in.buffer = NULL;
6673 r.in.offered = 0;
6674 r.out.needed = &needed;
6675 r.out.count = &count;
6676 r.out.info = &info;
6678 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6680 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6681 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6683 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6684 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6685 r.in.buffer = &blob;
6686 r.in.offered = needed;
6687 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6690 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6692 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6694 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6696 if (!info) {
6697 torture_comment(tctx, "No printers returned\n");
6698 return true;
6701 for (j=0;j<count;j++) {
6702 if (r.in.level == 1) {
6703 char *unc = talloc_strdup(tctx, info[j].info1.name);
6704 char *slash, *name, *full_name;
6705 name = unc;
6706 if (unc[0] == '\\' && unc[1] == '\\') {
6707 unc +=2;
6709 slash = strchr(unc, '\\');
6710 if (slash) {
6711 slash++;
6712 name = slash;
6714 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6715 dcerpc_server_name(p), name);
6716 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6717 ret = false;
6719 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6720 ret = false;
6722 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6723 ret = false;
6725 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6726 ret = false;
6732 return ret;
6735 static bool test_EnumPrinters_level(struct torture_context *tctx,
6736 struct dcerpc_binding_handle *b,
6737 uint32_t flags,
6738 const char *servername,
6739 uint32_t level,
6740 uint32_t *count_p,
6741 union spoolss_PrinterInfo **info_p)
6743 struct spoolss_EnumPrinters r;
6744 union spoolss_PrinterInfo *info;
6745 uint32_t needed;
6746 uint32_t count;
6748 r.in.flags = flags;
6749 r.in.server = servername;
6750 r.in.level = level;
6751 r.in.buffer = NULL;
6752 r.in.offered = 0;
6753 r.out.needed = &needed;
6754 r.out.count = &count;
6755 r.out.info = &info;
6757 torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6758 r.in.server, r.in.level);
6760 torture_assert_ntstatus_ok(tctx,
6761 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6762 "EnumPrinters failed");
6763 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6764 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6765 r.in.buffer = &blob;
6766 r.in.offered = needed;
6767 torture_assert_ntstatus_ok(tctx,
6768 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6769 "EnumPrinters failed");
6772 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6774 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6776 if (count_p) {
6777 *count_p = count;
6779 if (info_p) {
6780 *info_p = info;
6783 return true;
6786 static const char *get_short_printername(struct torture_context *tctx,
6787 const char *name)
6789 const char *short_name;
6791 if (name[0] == '\\' && name[1] == '\\') {
6792 name += 2;
6793 short_name = strchr(name, '\\');
6794 if (short_name) {
6795 return talloc_strdup(tctx, short_name+1);
6799 return name;
6802 static const char *get_full_printername(struct torture_context *tctx,
6803 const char *name)
6805 const char *full_name = talloc_strdup(tctx, name);
6806 char *p;
6808 if (name && name[0] == '\\' && name[1] == '\\') {
6809 name += 2;
6810 p = strchr(name, '\\');
6811 if (p) {
6812 return full_name;
6816 return NULL;
6819 static bool test_OnePrinter_servername(struct torture_context *tctx,
6820 struct dcerpc_pipe *p,
6821 struct dcerpc_binding_handle *b,
6822 const char *servername,
6823 const char *printername)
6825 union spoolss_PrinterInfo info;
6826 const char *short_name = get_short_printername(tctx, printername);
6827 const char *full_name = get_full_printername(tctx, printername);
6829 if (short_name) {
6830 struct policy_handle handle;
6831 torture_assert(tctx,
6832 call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
6833 "failed to open printer");
6835 torture_assert(tctx,
6836 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6837 "failed to get printer info");
6839 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
6840 "unexpected servername");
6841 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
6842 "unexpected printername");
6844 if (info.info2.devmode) {
6845 const char *expected_devicename;
6846 expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
6847 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6848 "unexpected devicemode devicename");
6851 torture_assert(tctx,
6852 test_ClosePrinter(tctx, b, &handle),
6853 "failed to close printer");
6856 if (full_name) {
6857 struct policy_handle handle;
6859 torture_assert(tctx,
6860 call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
6861 "failed to open printer");
6863 torture_assert(tctx,
6864 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6865 "failed to get printer info");
6867 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
6868 "unexpected servername");
6869 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
6870 "unexpected printername");
6872 if (info.info2.devmode) {
6873 const char *expected_devicename;
6874 expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
6875 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6876 "unexpected devicemode devicename");
6879 torture_assert(tctx,
6880 test_ClosePrinter(tctx, b, &handle),
6881 "failed to close printer");
6884 return true;
6887 static bool test_EnumPrinters_servername(struct torture_context *tctx,
6888 void *private_data)
6890 struct test_spoolss_context *ctx =
6891 talloc_get_type_abort(private_data, struct test_spoolss_context);
6892 int i;
6893 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6894 struct dcerpc_binding_handle *b = p->binding_handle;
6895 uint32_t count;
6896 union spoolss_PrinterInfo *info;
6897 const char *servername;
6898 uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
6900 torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6902 servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6904 torture_assert(tctx,
6905 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6906 "failed to enumerate printers");
6908 for (i=0; i < count; i++) {
6910 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
6911 "unexpected servername");
6913 torture_assert(tctx,
6914 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6915 "failed to check printer");
6918 servername = "";
6920 torture_assert(tctx,
6921 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6922 "failed to enumerate printers");
6924 for (i=0; i < count; i++) {
6926 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
6927 "unexpected servername");
6929 torture_assert(tctx,
6930 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6931 "failed to check printer");
6935 return true;
6938 #if 0
6939 static bool test_GetPrinterDriver(struct torture_context *tctx,
6940 struct dcerpc_binding_handle *b,
6941 struct policy_handle *handle,
6942 const char *driver_name)
6944 struct spoolss_GetPrinterDriver r;
6945 uint32_t needed;
6947 r.in.handle = handle;
6948 r.in.architecture = "W32X86";
6949 r.in.level = 1;
6950 r.in.buffer = NULL;
6951 r.in.offered = 0;
6952 r.out.needed = &needed;
6954 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
6956 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6957 "failed to call GetPrinterDriver");
6958 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6959 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6960 r.in.buffer = &blob;
6961 r.in.offered = needed;
6962 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6963 "failed to call GetPrinterDriver");
6966 torture_assert_werr_ok(tctx, r.out.result,
6967 "failed to call GetPrinterDriver");
6969 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6971 return true;
6973 #endif
6975 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
6976 struct dcerpc_binding_handle *b,
6977 struct policy_handle *handle,
6978 const char *driver_name,
6979 const char *architecture,
6980 uint32_t level,
6981 uint32_t client_major_version,
6982 uint32_t client_minor_version,
6983 union spoolss_DriverInfo *info_p,
6984 WERROR *result_p)
6987 struct spoolss_GetPrinterDriver2 r;
6988 uint32_t needed;
6989 uint32_t server_major_version;
6990 uint32_t server_minor_version;
6992 r.in.handle = handle;
6993 r.in.architecture = architecture;
6994 r.in.client_major_version = client_major_version;
6995 r.in.client_minor_version = client_minor_version;
6996 r.in.buffer = NULL;
6997 r.in.offered = 0;
6998 r.in.level = level;
6999 r.out.needed = &needed;
7000 r.out.server_major_version = &server_major_version;
7001 r.out.server_minor_version = &server_minor_version;
7003 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
7004 driver_name, r.in.level);
7006 torture_assert_ntstatus_ok(tctx,
7007 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
7008 "failed to call GetPrinterDriver2");
7009 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
7010 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7011 r.in.buffer = &blob;
7012 r.in.offered = needed;
7013 torture_assert_ntstatus_ok(tctx,
7014 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
7015 "failed to call GetPrinterDriver2");
7018 if (result_p) {
7019 *result_p = r.out.result;
7022 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
7023 switch (r.in.level) {
7024 case 101:
7025 case 8:
7026 torture_comment(tctx,
7027 "level %d not implemented, not considering as an error\n",
7028 r.in.level);
7029 return true;
7030 default:
7031 break;
7035 torture_assert_werr_ok(tctx, r.out.result,
7036 "failed to call GetPrinterDriver2");
7038 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
7040 if (info_p) {
7041 *info_p = *r.out.info;
7044 return true;
7047 static bool test_GetPrinterDriver2(struct torture_context *tctx,
7048 struct dcerpc_binding_handle *b,
7049 struct policy_handle *handle,
7050 const char *driver_name,
7051 const char *architecture)
7053 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
7054 int i;
7057 for (i=0;i<ARRAY_SIZE(levels);i++) {
7059 torture_assert(tctx,
7060 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
7061 "");
7064 return true;
7067 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
7068 void *private_data)
7070 struct test_spoolss_context *ctx =
7071 talloc_get_type_abort(private_data, struct test_spoolss_context);
7072 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
7073 int i;
7074 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7075 struct dcerpc_binding_handle *b = p->binding_handle;
7076 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7078 for (i=0;i<ARRAY_SIZE(levels);i++) {
7080 uint32_t count;
7081 union spoolss_DriverInfo *info;
7083 torture_assert(tctx,
7084 test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
7085 "failed to enumerate drivers");
7087 if (!info) {
7088 torture_comment(tctx, "No printer drivers returned\n");
7089 break;
7093 return true;
7096 static bool test_DeletePrinter(struct torture_context *tctx,
7097 struct dcerpc_binding_handle *b,
7098 struct policy_handle *handle)
7100 struct spoolss_DeletePrinter r;
7102 torture_comment(tctx, "Testing DeletePrinter\n");
7104 r.in.handle = handle;
7106 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
7107 "failed to delete printer");
7108 torture_assert_werr_ok(tctx, r.out.result,
7109 "failed to delete printer");
7111 return true;
7114 static bool test_EnumPrinters_findname(struct torture_context *tctx,
7115 struct dcerpc_binding_handle *b,
7116 uint32_t flags,
7117 uint32_t level,
7118 const char *name,
7119 bool *found)
7121 struct spoolss_EnumPrinters e;
7122 uint32_t count;
7123 union spoolss_PrinterInfo *info;
7124 uint32_t needed;
7125 int i;
7127 *found = false;
7129 e.in.flags = flags;
7130 e.in.server = NULL;
7131 e.in.level = level;
7132 e.in.buffer = NULL;
7133 e.in.offered = 0;
7134 e.out.count = &count;
7135 e.out.info = &info;
7136 e.out.needed = &needed;
7138 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
7139 "failed to enum printers");
7141 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
7142 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
7143 e.in.buffer = &blob;
7144 e.in.offered = needed;
7146 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
7147 "failed to enum printers");
7150 torture_assert_werr_ok(tctx, e.out.result,
7151 "failed to enum printers");
7153 for (i=0; i < count; i++) {
7155 const char *current = NULL;
7156 const char *q;
7158 switch (level) {
7159 case 1:
7160 current = info[i].info1.name;
7161 break;
7164 if (strequal(current, name)) {
7165 *found = true;
7166 break;
7169 q = strrchr(current, '\\');
7170 if (q) {
7171 if (!e.in.server) {
7172 torture_warning(tctx,
7173 "server returns printername %s incl. servername although we did not set servername", current);
7175 q++;
7176 if (strequal(q, name)) {
7177 *found = true;
7178 break;
7183 return true;
7186 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
7187 struct dcerpc_pipe *p,
7188 const char *printername,
7189 bool ex)
7191 WERROR result;
7192 struct spoolss_AddPrinter r;
7193 struct spoolss_AddPrinterEx rex;
7194 struct spoolss_SetPrinterInfoCtr info_ctr;
7195 struct spoolss_SetPrinterInfo1 info1;
7196 struct spoolss_DevmodeContainer devmode_ctr;
7197 struct sec_desc_buf secdesc_ctr;
7198 struct spoolss_UserLevelCtr userlevel_ctr;
7199 struct policy_handle handle;
7200 bool found = false;
7201 struct dcerpc_binding_handle *b = p->binding_handle;
7203 ZERO_STRUCT(devmode_ctr);
7204 ZERO_STRUCT(secdesc_ctr);
7205 ZERO_STRUCT(userlevel_ctr);
7206 ZERO_STRUCT(info1);
7208 torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
7209 ex ? "Ex":"", printername);
7211 /* try to add printer to wellknown printer list (level 1) */
7213 userlevel_ctr.level = 1;
7215 info_ctr.info.info1 = &info1;
7216 info_ctr.level = 1;
7218 rex.in.server = NULL;
7219 rex.in.info_ctr = &info_ctr;
7220 rex.in.devmode_ctr = &devmode_ctr;
7221 rex.in.secdesc_ctr = &secdesc_ctr;
7222 rex.in.userlevel_ctr = &userlevel_ctr;
7223 rex.out.handle = &handle;
7225 r.in.server = NULL;
7226 r.in.info_ctr = &info_ctr;
7227 r.in.devmode_ctr = &devmode_ctr;
7228 r.in.secdesc_ctr = &secdesc_ctr;
7229 r.out.handle = &handle;
7231 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7232 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7233 "failed to add printer");
7234 result = ex ? rex.out.result : r.out.result;
7235 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
7236 "unexpected result code");
7238 info1.name = printername;
7239 info1.flags = PRINTER_ATTRIBUTE_SHARED;
7241 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7242 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7243 "failed to add printer");
7244 result = ex ? rex.out.result : r.out.result;
7245 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7246 "unexpected result code");
7248 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7249 better do a real check to see the printer is really there */
7251 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7252 PRINTER_ENUM_NETWORK, 1,
7253 printername,
7254 &found),
7255 "failed to enum printers");
7257 torture_assert(tctx, found, "failed to find newly added printer");
7259 info1.flags = 0;
7261 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7262 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7263 "failed to add printer");
7264 result = ex ? rex.out.result : r.out.result;
7265 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7266 "unexpected result code");
7268 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
7269 better do a real check to see the printer has really been removed
7270 from the well known printer list */
7272 found = false;
7274 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7275 PRINTER_ENUM_NETWORK, 1,
7276 printername,
7277 &found),
7278 "failed to enum printers");
7279 #if 0
7280 torture_assert(tctx, !found, "printer still in well known printer list");
7281 #endif
7282 return true;
7285 static bool test_AddPrinter_normal(struct torture_context *tctx,
7286 struct dcerpc_pipe *p,
7287 struct policy_handle *handle_p,
7288 const char *printername,
7289 const char *drivername,
7290 const char *portname,
7291 struct spoolss_DeviceMode *devmode,
7292 bool ex)
7294 WERROR result;
7295 struct spoolss_AddPrinter r;
7296 struct spoolss_AddPrinterEx rex;
7297 struct spoolss_SetPrinterInfoCtr info_ctr;
7298 struct spoolss_SetPrinterInfo2 info2;
7299 struct spoolss_DevmodeContainer devmode_ctr;
7300 struct sec_desc_buf secdesc_ctr;
7301 struct spoolss_UserLevelCtr userlevel_ctr;
7302 struct policy_handle handle;
7303 bool found = false;
7304 bool existing_printer_deleted = false;
7305 struct dcerpc_binding_handle *b = p->binding_handle;
7307 ZERO_STRUCT(devmode_ctr);
7308 ZERO_STRUCT(secdesc_ctr);
7309 ZERO_STRUCT(userlevel_ctr);
7311 torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
7312 ex ? "Ex":"", printername);
7314 devmode_ctr.devmode = devmode;
7316 userlevel_ctr.level = 1;
7318 rex.in.server = NULL;
7319 rex.in.info_ctr = &info_ctr;
7320 rex.in.devmode_ctr = &devmode_ctr;
7321 rex.in.secdesc_ctr = &secdesc_ctr;
7322 rex.in.userlevel_ctr = &userlevel_ctr;
7323 rex.out.handle = &handle;
7325 r.in.server = NULL;
7326 r.in.info_ctr = &info_ctr;
7327 r.in.devmode_ctr = &devmode_ctr;
7328 r.in.secdesc_ctr = &secdesc_ctr;
7329 r.out.handle = &handle;
7331 again:
7333 /* try to add printer to printer list (level 2) */
7335 ZERO_STRUCT(info2);
7337 info_ctr.info.info2 = &info2;
7338 info_ctr.level = 2;
7340 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7341 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7342 "failed to add printer");
7343 result = ex ? rex.out.result : r.out.result;
7344 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
7345 "unexpected result code");
7347 info2.printername = printername;
7349 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7350 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7351 "failed to add printer");
7352 result = ex ? rex.out.result : r.out.result;
7354 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
7355 struct policy_handle printer_handle;
7357 if (existing_printer_deleted) {
7358 torture_fail(tctx, "already deleted printer still existing?");
7361 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
7362 "failed to open printer handle");
7364 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
7365 "failed to delete printer");
7367 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
7368 "failed to close server handle");
7370 existing_printer_deleted = true;
7372 goto again;
7375 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
7376 "unexpected result code");
7378 info2.portname = portname;
7380 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7381 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7382 "failed to add printer");
7383 result = ex ? rex.out.result : r.out.result;
7384 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
7385 "unexpected result code");
7387 info2.drivername = drivername;
7389 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7390 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7391 "failed to add printer");
7392 result = ex ? rex.out.result : r.out.result;
7394 /* w2k8r2 allows to add printer w/o defining printprocessor */
7396 if (!W_ERROR_IS_OK(result)) {
7397 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
7398 "unexpected result code");
7400 info2.printprocessor = "winprint";
7402 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7403 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7404 "failed to add printer");
7405 result = ex ? rex.out.result : r.out.result;
7406 torture_assert_werr_ok(tctx, result,
7407 "failed to add printer");
7410 *handle_p = handle;
7412 /* we are paranoid, really check if the printer is there now */
7414 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7415 PRINTER_ENUM_LOCAL, 1,
7416 printername,
7417 &found),
7418 "failed to enum printers");
7419 torture_assert(tctx, found, "failed to find newly added printer");
7421 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7422 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7423 "failed to add printer");
7424 result = ex ? rex.out.result : r.out.result;
7425 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7426 "unexpected result code");
7428 return true;
7431 static bool test_printer_info(struct torture_context *tctx,
7432 void *private_data)
7434 struct torture_printer_context *t =
7435 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7436 struct dcerpc_pipe *p = t->spoolss_pipe;
7437 struct dcerpc_binding_handle *b = p->binding_handle;
7439 bool ret = true;
7441 if (torture_setting_bool(tctx, "samba3", false)) {
7442 torture_skip(tctx, "skipping printer info cross tests against samba 3");
7445 if (!test_PrinterInfo(tctx, b, &t->handle)) {
7446 ret = false;
7449 if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
7450 ret = false;
7453 return ret;
7456 static bool test_EnumPrinterKey(struct torture_context *tctx,
7457 struct dcerpc_binding_handle *b,
7458 struct policy_handle *handle,
7459 const char *key_name,
7460 const char ***array)
7462 struct spoolss_EnumPrinterKey r;
7463 uint32_t needed = 0;
7464 union spoolss_KeyNames key_buffer;
7465 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7466 uint32_t _ndr_size;
7467 int i;
7469 r.in.handle = handle;
7470 r.in.key_name = key_name;
7471 r.out.key_buffer = &key_buffer;
7472 r.out.needed = &needed;
7473 r.out._ndr_size = &_ndr_size;
7475 for (i=0; i < ARRAY_SIZE(offered); i++) {
7477 if (offered[i] < 0 && needed) {
7478 if (needed <= 4) {
7479 continue;
7481 r.in.offered = needed + offered[i];
7482 } else {
7483 r.in.offered = offered[i];
7486 ZERO_STRUCT(key_buffer);
7488 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
7490 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7491 "failed to call EnumPrinterKey");
7492 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
7494 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7495 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7496 _ndr_size, r.in.offered/2));
7498 r.in.offered = needed;
7499 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7500 "failed to call EnumPrinterKey");
7503 if (offered[i] > 0) {
7504 torture_assert_werr_ok(tctx, r.out.result,
7505 "failed to call EnumPrinterKey");
7508 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7509 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7510 _ndr_size, r.in.offered/2));
7512 torture_assert(tctx, (*r.out.needed <= r.in.offered),
7513 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
7515 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
7516 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
7518 if (key_buffer.string_array) {
7519 uint32_t calc_needed = 0;
7520 int s;
7521 for (s=0; key_buffer.string_array[s]; s++) {
7522 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7524 if (!key_buffer.string_array[0]) {
7525 calc_needed += 2;
7527 calc_needed += 2;
7529 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7530 "EnumPrinterKey unexpected size");
7534 if (array) {
7535 *array = key_buffer.string_array;
7538 return true;
7541 bool test_printer_all_keys(struct torture_context *tctx,
7542 struct dcerpc_binding_handle *b,
7543 struct policy_handle *handle)
7545 const char **key_array = NULL;
7546 int i;
7548 torture_comment(tctx, "Testing Printer Keys\n");
7550 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7551 "failed to call test_EnumPrinterKey");
7553 for (i=0; key_array && key_array[i]; i++) {
7554 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7555 "failed to call test_EnumPrinterKey");
7557 for (i=0; key_array && key_array[i]; i++) {
7558 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7559 "failed to call test_EnumPrinterDataEx");
7562 torture_comment(tctx, "Printer Keys test succeeded\n\n");
7564 return true;
7567 static bool test_openprinter_wrap(struct torture_context *tctx,
7568 void *private_data)
7570 struct torture_printer_context *t =
7571 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7572 struct dcerpc_pipe *p = t->spoolss_pipe;
7573 struct dcerpc_binding_handle *b = p->binding_handle;
7574 const char *printername = t->info2.printername;
7576 return test_openprinter(tctx, b, printername);
7579 static bool test_csetprinter(struct torture_context *tctx,
7580 void *private_data)
7582 struct torture_printer_context *t =
7583 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7584 struct dcerpc_pipe *p = t->spoolss_pipe;
7586 const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7587 const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7588 const char *portname = t->info2.portname;
7590 union spoolss_PrinterInfo info;
7591 struct policy_handle new_handle, new_handle2;
7592 struct dcerpc_binding_handle *b = p->binding_handle;
7594 torture_comment(tctx, "Testing c_setprinter\n");
7596 torture_assert(tctx,
7597 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7598 "failed to get level 0 printer info");
7599 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7600 info.info0.c_setprinter);
7602 /* check if c_setprinter on 1st handle increases after a printer has
7603 * been added */
7605 torture_assert(tctx,
7606 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7607 "failed to add new printer");
7608 torture_assert(tctx,
7609 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7610 "failed to get level 0 printer info");
7611 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7612 info.info0.c_setprinter);
7614 /* check if c_setprinter on new handle increases after a printer has
7615 * been added */
7617 torture_assert(tctx,
7618 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7619 "failed to get level 0 printer info");
7620 torture_comment(tctx, "csetprinter on created handle: %d\n",
7621 info.info0.c_setprinter);
7623 /* open the new printer and check if c_setprinter increases */
7625 torture_assert(tctx,
7626 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7627 "failed to open created printer");
7628 torture_assert(tctx,
7629 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
7630 "failed to get level 0 printer info");
7631 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
7632 info.info0.c_setprinter);
7634 /* cleanup */
7636 torture_assert(tctx,
7637 test_ClosePrinter(tctx, b, &new_handle2),
7638 "failed to close printer");
7639 torture_assert(tctx,
7640 test_DeletePrinter(tctx, b, &new_handle),
7641 "failed to delete new printer");
7643 return true;
7646 static bool compose_local_driver_directory(struct torture_context *tctx,
7647 const char *environment,
7648 const char *local_dir,
7649 const char **path)
7651 char *p;
7653 p = strrchr(local_dir, '/');
7654 if (!p) {
7655 return NULL;
7657 p++;
7659 if (strequal(environment, "Windows x64")) {
7660 if (!strequal(p, "x64")) {
7661 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
7663 } else if (strequal(environment, "Windows NT x86")) {
7664 if (!strequal(p, "i386")) {
7665 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
7667 } else {
7668 torture_assert(tctx, "unknown environment: '%s'\n", environment);
7671 return true;
7674 #if 0
7675 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
7676 const char *devicename)
7678 struct spoolss_DeviceMode *r;
7680 r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
7681 if (r == NULL) {
7682 return NULL;
7685 r->devicename = talloc_strdup(r, devicename);
7686 r->specversion = DMSPEC_NT4_AND_ABOVE;
7687 r->driverversion = 0x0600;
7688 r->size = 0x00dc;
7689 r->__driverextra_length = 0;
7690 r->fields = DEVMODE_FORMNAME |
7691 DEVMODE_TTOPTION |
7692 DEVMODE_PRINTQUALITY |
7693 DEVMODE_DEFAULTSOURCE |
7694 DEVMODE_COPIES |
7695 DEVMODE_SCALE |
7696 DEVMODE_PAPERSIZE |
7697 DEVMODE_ORIENTATION;
7698 r->orientation = DMORIENT_PORTRAIT;
7699 r->papersize = DMPAPER_LETTER;
7700 r->paperlength = 0;
7701 r->paperwidth = 0;
7702 r->scale = 100;
7703 r->copies = 55;
7704 r->defaultsource = DMBIN_FORMSOURCE;
7705 r->printquality = DMRES_HIGH;
7706 r->color = DMRES_MONOCHROME;
7707 r->duplex = DMDUP_SIMPLEX;
7708 r->yresolution = 0;
7709 r->ttoption = DMTT_SUBDEV;
7710 r->collate = DMCOLLATE_FALSE;
7711 r->formname = talloc_strdup(r, "Letter");
7713 return r;
7715 #endif
7717 static bool test_architecture_buffer(struct torture_context *tctx,
7718 void *private_data)
7720 struct test_spoolss_context *ctx =
7721 talloc_get_type_abort(private_data, struct test_spoolss_context);
7723 struct spoolss_OpenPrinterEx r;
7724 struct spoolss_UserLevel1 u1;
7725 struct policy_handle handle;
7726 uint32_t architectures[] = {
7727 PROCESSOR_ARCHITECTURE_INTEL,
7728 PROCESSOR_ARCHITECTURE_IA64,
7729 PROCESSOR_ARCHITECTURE_AMD64
7731 uint32_t needed[3];
7732 int i;
7733 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7734 struct dcerpc_binding_handle *b = p->binding_handle;
7736 for (i=0; i < ARRAY_SIZE(architectures); i++) {
7738 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7740 u1.size = 0;
7741 u1.client = NULL;
7742 u1.user = NULL;
7743 u1.build = 0;
7744 u1.major = 3;
7745 u1.minor = 0;
7746 u1.processor = architectures[i];
7748 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7749 r.in.datatype = NULL;
7750 r.in.devmode_ctr.devmode= NULL;
7751 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7752 r.in.userlevel_ctr.level = 1;
7753 r.in.userlevel_ctr.user_info.level1 = &u1;
7754 r.out.handle = &handle;
7756 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7757 torture_assert_werr_ok(tctx, r.out.result, "");
7760 struct spoolss_EnumPrinters e;
7761 uint32_t count;
7762 union spoolss_PrinterInfo *info;
7764 e.in.flags = PRINTER_ENUM_LOCAL;
7765 e.in.server = NULL;
7766 e.in.level = 2;
7767 e.in.buffer = NULL;
7768 e.in.offered = 0;
7769 e.out.count = &count;
7770 e.out.info = &info;
7771 e.out.needed = &needed[i];
7773 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7774 #if 0
7775 torture_comment(tctx, "needed was %d\n", needed[i]);
7776 #endif
7779 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7782 for (i=1; i < ARRAY_SIZE(architectures); i++) {
7783 if (needed[i-1] != needed[i]) {
7784 torture_fail(tctx,
7785 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7786 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7790 return true;
7793 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
7794 void *private_data)
7796 struct test_spoolss_context *ctx =
7797 talloc_get_type_abort(private_data, struct test_spoolss_context);
7798 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7799 struct dcerpc_binding_handle *b = p->binding_handle;
7801 return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
7804 static bool test_PrintServer_Forms(struct torture_context *tctx,
7805 void *private_data)
7807 struct test_spoolss_context *ctx =
7808 talloc_get_type_abort(private_data, struct test_spoolss_context);
7809 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7810 struct dcerpc_binding_handle *b = p->binding_handle;
7812 return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
7815 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
7816 void *private_data)
7818 struct test_spoolss_context *ctx =
7819 talloc_get_type_abort(private_data, struct test_spoolss_context);
7820 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7821 struct dcerpc_binding_handle *b = p->binding_handle;
7823 return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
7826 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
7828 NTSTATUS status;
7830 status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
7832 torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
7834 torture_assert(tctx,
7835 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
7836 "failed to open printserver");
7837 torture_assert(tctx,
7838 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
7839 "failed to get environment");
7841 return true;
7844 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
7846 struct test_spoolss_context *t;
7848 *data = t = talloc_zero(tctx, struct test_spoolss_context);
7850 return torture_rpc_spoolss_setup_common(tctx, t);
7853 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
7855 test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
7857 return true;
7860 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
7862 struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
7863 bool ret;
7865 ret = torture_rpc_spoolss_teardown_common(tctx, t);
7866 talloc_free(t);
7868 return ret;
7871 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
7873 struct dcerpc_pipe *p;
7874 struct dcerpc_binding_handle *b;
7875 const char *server_name_slash;
7876 const char *driver_name;
7877 const char *printer_name;
7878 const char *port_name;
7880 torture_assert_ntstatus_ok(tctx,
7881 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
7882 "Error connecting to server");
7884 p = t->spoolss_pipe;
7885 b = p->binding_handle;
7886 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7888 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
7889 t->driver.info8.driver_name = TORTURE_DRIVER;
7890 t->driver.info8.driver_path = "pscript5.dll";
7891 t->driver.info8.data_file = "cups6.ppd";
7892 t->driver.info8.config_file = "ps5ui.dll";
7893 t->driver.info8.help_file = "pscript.hlp";
7894 t->driver.info8.default_datatype = "RAW";
7895 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
7896 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
7897 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
7898 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
7899 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
7900 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
7901 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
7902 t->driver.info8.dependent_files->string[5] = "cups6.ini";
7903 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
7904 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
7906 t->driver.local.driver_directory= "/usr/share/cups/drivers";
7908 t->info2.portname = "LPT1:";
7910 printer_name = t->info2.printername;
7911 port_name = t->info2.portname;
7913 torture_assert(tctx,
7914 fillup_printserver_info(tctx, p, &t->driver),
7915 "failed to fillup printserver info");
7917 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
7919 torture_assert(tctx,
7920 compose_local_driver_directory(tctx, t->driver.remote.environment,
7921 t->driver.local.driver_directory,
7922 &t->driver.local.driver_directory),
7923 "failed to compose local driver directory");
7925 t->info2.drivername = "Microsoft XPS Document Writer";
7927 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7928 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7929 t->info2.drivername, t->driver.remote.environment);
7930 t->have_driver = true;
7931 goto try_add;
7934 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
7935 t->info2.drivername, t->driver.remote.environment);
7937 t->info2.drivername = "Microsoft XPS Document Writer v4";
7939 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7940 torture_comment(tctx, "driver '%s' (architecture: %s, version: 4) is present on server\n",
7941 t->info2.drivername, t->driver.remote.environment);
7942 t->have_driver = true;
7943 goto try_add;
7946 torture_comment(tctx, "trying to upload own driver\n");
7948 if (!directory_exist(t->driver.local.driver_directory)) {
7949 torture_warning(tctx, "no local driver is available!");
7950 t->have_driver = false;
7951 goto try_add;
7954 torture_assert(tctx,
7955 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
7956 "failed to upload printer driver");
7958 torture_assert(tctx,
7959 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
7960 "failed to add driver");
7962 t->added_driver = true;
7963 t->have_driver = true;
7965 try_add:
7966 driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7968 if (t->wellknown) {
7969 torture_assert(tctx,
7970 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
7971 "failed to add wellknown printer");
7972 } else {
7973 torture_assert(tctx,
7974 test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
7975 "failed to add printer");
7978 return true;
7981 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
7983 struct torture_printer_context *t;
7985 *data = t = talloc_zero(tctx, struct torture_printer_context);
7987 t->ex = false;
7988 t->wellknown = false;
7989 t->info2.printername = TORTURE_PRINTER;
7990 t->devmode = NULL;
7992 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7995 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
7997 struct torture_printer_context *t;
7999 *data = t = talloc_zero(tctx, struct torture_printer_context);
8001 t->ex = true;
8002 t->wellknown = false;
8003 t->info2.printername = TORTURE_PRINTER_EX;
8004 t->devmode = NULL;
8006 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8009 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
8011 struct torture_printer_context *t;
8013 *data = t = talloc_zero(tctx, struct torture_printer_context);
8015 t->ex = false;
8016 t->wellknown = true;
8017 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
8018 t->devmode = NULL;
8020 /* FIXME */
8021 if (t->wellknown) {
8022 torture_skip(tctx, "skipping AddPrinter level 1");
8025 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8028 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
8030 struct torture_printer_context *t;
8032 *data = t = talloc_zero(tctx, struct torture_printer_context);
8034 t->ex = true;
8035 t->wellknown = true;
8036 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
8037 t->devmode = NULL;
8039 /* FIXME */
8040 if (t->wellknown) {
8041 torture_skip(tctx, "skipping AddPrinterEx level 1");
8044 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8047 #if 0
8048 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
8050 struct torture_printer_context *t;
8052 *data = t = talloc_zero(tctx, struct torture_printer_context);
8054 t->ex = true;
8055 t->wellknown = false;
8056 t->info2.printername = TORTURE_PRINTER_EX;
8057 t->devmode = torture_devicemode(t, TORTURE_PRINTER_EX);
8059 return torture_rpc_spoolss_printer_setup_common(tctx, t);
8061 #endif
8063 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
8065 bool found = false;
8066 struct dcerpc_pipe *p = t->spoolss_pipe;
8067 struct dcerpc_binding_handle *b;
8068 const char *printer_name = t->info2.printername;
8070 if (t->added_driver) {
8071 torture_assert(tctx,
8072 remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
8073 "failed to remove printer driver");
8076 if (p && !t->wellknown) {
8077 b = p->binding_handle;
8079 torture_assert(tctx,
8080 test_DeletePrinter(tctx, b, &t->handle),
8081 "failed to delete printer");
8083 torture_assert(tctx,
8084 test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
8085 printer_name, &found),
8086 "failed to enumerate printers");
8088 torture_assert(tctx, !found, "deleted printer still there");
8091 return true;
8094 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
8096 struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
8097 bool ret;
8099 ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
8100 talloc_free(t);
8102 return ret;
8105 static bool test_print_test(struct torture_context *tctx,
8106 void *private_data)
8108 struct torture_printer_context *t =
8109 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8110 struct dcerpc_pipe *p = t->spoolss_pipe;
8111 struct dcerpc_binding_handle *b = p->binding_handle;
8113 torture_assert(tctx,
8114 test_PausePrinter(tctx, b, &t->handle),
8115 "failed to pause printer");
8117 torture_assert(tctx,
8118 test_DoPrintTest(tctx, b, &t->handle),
8119 "failed to do print test");
8121 torture_assert(tctx,
8122 test_ResumePrinter(tctx, b, &t->handle),
8123 "failed to resume printer");
8125 return true;
8128 static bool test_print_test_extended(struct torture_context *tctx,
8129 void *private_data)
8131 struct torture_printer_context *t =
8132 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8133 struct dcerpc_pipe *p = t->spoolss_pipe;
8134 struct dcerpc_binding_handle *b = p->binding_handle;
8135 bool ret = true;
8137 torture_assert(tctx,
8138 test_PausePrinter(tctx, b, &t->handle),
8139 "failed to pause printer");
8141 ret = test_DoPrintTest_extended(tctx, b, &t->handle);
8142 if (ret == false) {
8143 torture_comment(tctx, "WARNING! failed to do extended print test\n");
8144 if (torture_setting_bool(tctx, "samba3", false)) {
8145 torture_comment(tctx, "non-critical for samba3\n");
8146 ret = true;
8147 tctx->last_result = TORTURE_SKIP;
8151 torture_assert(tctx,
8152 test_ResumePrinter(tctx, b, &t->handle),
8153 "failed to resume printer");
8155 return ret;
8158 static bool test_print_test_properties(struct torture_context *tctx,
8159 void *private_data)
8161 struct torture_printer_context *t =
8162 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8163 struct dcerpc_pipe *p = t->spoolss_pipe;
8164 struct dcerpc_binding_handle *b = p->binding_handle;
8166 if (torture_setting_bool(tctx, "samba3", false)) {
8167 torture_skip(tctx, "skip printer job property tests against samba");
8170 torture_assert(tctx,
8171 test_PausePrinter(tctx, b, &t->handle),
8172 "failed to pause printer");
8174 torture_assert(tctx,
8175 test_DoPrintTest_properties(tctx, b, &t->handle),
8176 "failed to test print job properties");
8178 torture_assert(tctx,
8179 test_ResumePrinter(tctx, b, &t->handle),
8180 "failed to resume printer");
8182 return true;
8185 /* use smbd file IO to spool a print job */
8186 static bool test_print_test_smbd(struct torture_context *tctx,
8187 void *private_data)
8189 struct torture_printer_context *t =
8190 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8191 struct dcerpc_pipe *p = t->spoolss_pipe;
8192 struct dcerpc_binding_handle *b = p->binding_handle;
8193 NTSTATUS status;
8194 uint32_t count;
8195 union spoolss_JobInfo *info = NULL;
8196 int i;
8198 struct smb2_tree *tree;
8199 struct smb2_handle job_h;
8200 struct cli_credentials *credentials = cmdline_credentials;
8201 struct smbcli_options options;
8202 TALLOC_CTX *mem_ctx = talloc_new(tctx);
8204 * Do not test against the dynamically added printers, printing via
8205 * smbd means that a different spoolss process may handle the
8206 * OpenPrinter request to the one that handled the AddPrinter request.
8207 * This currently leads to an ugly race condition where one process
8208 * sees the new printer and one doesn't.
8210 const char *share = TORTURE_PRINTER_STATIC1;
8212 torture_comment(tctx, "Testing smbd job spooling\n");
8213 lpcfg_smbcli_options(tctx->lp_ctx, &options);
8215 status = smb2_connect(mem_ctx,
8216 torture_setting_string(tctx, "host", NULL),
8217 lpcfg_smb_ports(tctx->lp_ctx),
8218 share,
8219 lpcfg_resolve_context(tctx->lp_ctx),
8220 credentials,
8221 &tree,
8222 tctx->ev,
8223 &options,
8224 lpcfg_socket_options(tctx->lp_ctx),
8225 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
8226 if (!NT_STATUS_IS_OK(status)) {
8227 printf("Failed to connect to SMB2 printer %s - %s\n",
8228 share, nt_errstr(status));
8229 return false;
8232 status = torture_smb2_testfile(tree, "smbd_spooler_job", &job_h);
8233 torture_assert_ntstatus_ok(tctx, status, "smbd spool job create");
8235 status = smb2_util_write(tree, job_h, "exciting print job data", 0,
8236 sizeof("exciting print job data"));
8237 torture_assert_ntstatus_ok(tctx, status, "smbd spool job write");
8239 /* check back end spoolss job was created */
8240 torture_assert(tctx,
8241 test_EnumJobs_args(tctx, b, &t->handle, 1, &count, &info),
8242 "EnumJobs level 1 failed");
8244 for (i = 0; i < count; i++) {
8245 if (!strcmp(info[i].info1.document_name, "smbd_spooler_job")) {
8246 break;
8249 torture_assert(tctx, (i != count), "smbd_spooler_job not found");
8251 status = smb2_util_close(tree, job_h);
8252 torture_assert_ntstatus_ok(tctx, status, "smbd spool job close");
8254 /* disconnect from printer share */
8255 talloc_free(mem_ctx);
8257 return true;
8260 static bool test_printer_sd(struct torture_context *tctx,
8261 void *private_data)
8263 struct torture_printer_context *t =
8264 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8265 struct dcerpc_pipe *p = t->spoolss_pipe;
8266 struct dcerpc_binding_handle *b = p->binding_handle;
8268 torture_assert(tctx,
8269 test_PrinterInfo_SD(tctx, b, &t->handle),
8270 "failed to test security descriptors");
8272 return true;
8275 static bool test_printer_dm(struct torture_context *tctx,
8276 void *private_data)
8278 struct torture_printer_context *t =
8279 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8280 struct dcerpc_pipe *p = t->spoolss_pipe;
8282 torture_assert(tctx,
8283 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
8284 "failed to test devicemodes");
8286 return true;
8289 static bool test_printer_info_winreg(struct torture_context *tctx,
8290 void *private_data)
8292 struct torture_printer_context *t =
8293 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8294 struct dcerpc_pipe *p = t->spoolss_pipe;
8296 torture_assert(tctx,
8297 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
8298 "failed to test printer info winreg");
8300 return true;
8303 static bool test_printer_change_id(struct torture_context *tctx,
8304 void *private_data)
8306 struct torture_printer_context *t =
8307 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8308 struct dcerpc_pipe *p = t->spoolss_pipe;
8310 torture_assert(tctx,
8311 test_ChangeID(tctx, p, &t->handle),
8312 "failed to test change id");
8314 return true;
8317 static bool test_printer_keys(struct torture_context *tctx,
8318 void *private_data)
8320 struct torture_printer_context *t =
8321 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8322 struct dcerpc_pipe *p = t->spoolss_pipe;
8323 struct dcerpc_binding_handle *b = p->binding_handle;
8325 torture_assert(tctx,
8326 test_printer_all_keys(tctx, b, &t->handle),
8327 "failed to test printer keys");
8329 return true;
8332 static bool test_printer_data_consistency(struct torture_context *tctx,
8333 void *private_data)
8335 struct torture_printer_context *t =
8336 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8337 struct dcerpc_pipe *p = t->spoolss_pipe;
8339 torture_assert(tctx,
8340 test_EnumPrinterData_consistency(tctx, p, &t->handle),
8341 "failed to test printer data consistency");
8343 return true;
8346 static bool test_printer_data_keys(struct torture_context *tctx,
8347 void *private_data)
8349 struct torture_printer_context *t =
8350 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8351 struct dcerpc_pipe *p = t->spoolss_pipe;
8353 torture_assert(tctx,
8354 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
8355 "failed to test printer data keys");
8357 return true;
8360 static bool test_printer_data_values(struct torture_context *tctx,
8361 void *private_data)
8363 struct torture_printer_context *t =
8364 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8365 struct dcerpc_pipe *p = t->spoolss_pipe;
8367 torture_assert(tctx,
8368 test_SetPrinterDataEx_values(tctx, p, &t->handle),
8369 "failed to test printer data values");
8371 return true;
8374 static bool test_printer_data_set(struct torture_context *tctx,
8375 void *private_data)
8377 struct torture_printer_context *t =
8378 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8379 struct dcerpc_pipe *p = t->spoolss_pipe;
8381 torture_assert(tctx,
8382 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
8383 "failed to test printer data set");
8385 return true;
8388 static bool test_printer_data_winreg(struct torture_context *tctx,
8389 void *private_data)
8391 struct torture_printer_context *t =
8392 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8393 struct dcerpc_pipe *p = t->spoolss_pipe;
8395 torture_assert(tctx,
8396 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
8397 "failed to test printer data winreg");
8399 return true;
8402 static bool test_printer_data_dsspooler(struct torture_context *tctx,
8403 void *private_data)
8405 struct torture_printer_context *t =
8406 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8407 struct dcerpc_pipe *p = t->spoolss_pipe;
8409 torture_assert(tctx,
8410 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
8411 "failed to test printer data winreg dsspooler");
8413 return true;
8416 static bool test_printer_ic(struct torture_context *tctx,
8417 void *private_data)
8419 struct torture_printer_context *t =
8420 talloc_get_type_abort(private_data,
8421 struct torture_printer_context);
8422 struct dcerpc_pipe *p = t->spoolss_pipe;
8423 struct dcerpc_binding_handle *b = p->binding_handle;
8424 struct policy_handle gdi_handle;
8426 if (torture_setting_bool(tctx, "samba3", false)) {
8427 torture_skip(tctx, "skip printer information context tests against samba");
8431 struct spoolss_CreatePrinterIC r;
8432 struct spoolss_DevmodeContainer devmode_ctr;
8434 ZERO_STRUCT(devmode_ctr);
8436 r.in.handle = &t->handle;
8437 r.in.devmode_ctr = &devmode_ctr;
8438 r.out.gdi_handle = &gdi_handle;
8440 torture_assert_ntstatus_ok(tctx,
8441 dcerpc_spoolss_CreatePrinterIC_r(b, tctx, &r),
8442 "CreatePrinterIC failed");
8443 torture_assert_werr_ok(tctx, r.out.result,
8444 "CreatePrinterIC failed");
8448 struct spoolss_PlayGDIScriptOnPrinterIC r;
8449 DATA_BLOB in,out;
8450 int i;
8451 uint32_t num_fonts = 0;
8453 in = data_blob_string_const("");
8455 r.in.gdi_handle = &gdi_handle;
8456 r.in.pIn = in.data;
8457 r.in.cIn = in.length;
8458 r.in.ul = 0;
8460 for (i = 0; i < 4; i++) {
8462 out = data_blob_talloc_zero(tctx, i);
8464 r.in.cOut = out.length;
8465 r.out.pOut = out.data;
8467 torture_assert_ntstatus_ok(tctx,
8468 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8469 "PlayGDIScriptOnPrinterIC failed");
8470 torture_assert_werr_equal(tctx, r.out.result, WERR_NOMEM,
8471 "PlayGDIScriptOnPrinterIC failed");
8474 out = data_blob_talloc_zero(tctx, 4);
8476 r.in.cOut = out.length;
8477 r.out.pOut = out.data;
8479 torture_assert_ntstatus_ok(tctx,
8480 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8481 "PlayGDIScriptOnPrinterIC failed");
8482 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
8483 "PlayGDIScriptOnPrinterIC failed");
8485 /* now we should have the required length, so retry with a
8486 * buffer which is large enough to carry all font ids */
8488 num_fonts = IVAL(r.out.pOut, 0);
8490 torture_comment(tctx, "PlayGDIScriptOnPrinterIC gave font count of %d\n", num_fonts);
8492 out = data_blob_talloc_zero(tctx,
8493 num_fonts * sizeof(struct UNIVERSAL_FONT_ID) + 4);
8495 r.in.cOut = out.length;
8496 r.out.pOut = out.data;
8498 torture_assert_ntstatus_ok(tctx,
8499 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
8500 "PlayGDIScriptOnPrinterIC failed");
8501 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
8502 "PlayGDIScriptOnPrinterIC failed");
8507 struct spoolss_DeletePrinterIC r;
8509 r.in.gdi_handle = &gdi_handle;
8510 r.out.gdi_handle = &gdi_handle;
8512 torture_assert_ntstatus_ok(tctx,
8513 dcerpc_spoolss_DeletePrinterIC_r(b, tctx, &r),
8514 "DeletePrinterIC failed");
8515 torture_assert_werr_ok(tctx, r.out.result,
8516 "DeletePrinterIC failed");
8520 return true;
8523 static bool test_printer_bidi(struct torture_context *tctx,
8524 void *private_data)
8526 struct torture_printer_context *t =
8527 talloc_get_type_abort(private_data,
8528 struct torture_printer_context);
8529 struct dcerpc_pipe *p = t->spoolss_pipe;
8530 struct dcerpc_binding_handle *b = p->binding_handle;
8531 struct spoolss_RpcSendRecvBidiData r;
8532 struct RPC_BIDI_REQUEST_CONTAINER bidi_req;
8533 struct RPC_BIDI_RESPONSE_CONTAINER *bidi_rep = NULL;
8535 if (torture_setting_bool(tctx, "samba3", false)) {
8536 torture_skip(tctx, "skip printer bidirectional tests against samba");
8539 ZERO_STRUCT(bidi_req);
8541 r.in.hPrinter = t->handle;
8542 r.in.pAction = "foobar";
8543 r.in.pReqData = &bidi_req;
8544 r.out.ppRespData = &bidi_rep;
8546 torture_assert_ntstatus_ok(tctx,
8547 dcerpc_spoolss_RpcSendRecvBidiData_r(b, tctx, &r),
8548 "RpcSendRecvBidiData failed");
8549 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
8550 "RpcSendRecvBidiData failed");
8552 if (!(t->info2.attributes & PRINTER_ATTRIBUTE_ENABLE_BIDI)) {
8553 torture_skip(tctx, "skipping further tests as printer is not BIDI enabled");
8556 r.in.pAction = BIDI_ACTION_ENUM_SCHEMA;
8558 torture_assert_ntstatus_ok(tctx,
8559 dcerpc_spoolss_RpcSendRecvBidiData_r(b, tctx, &r),
8560 "RpcSendRecvBidiData failed");
8561 torture_assert_werr_ok(tctx, r.out.result,
8562 "RpcSendRecvBidiData failed");
8564 return true;
8567 static bool test_printer_set_publish(struct torture_context *tctx,
8568 struct dcerpc_binding_handle *b,
8569 struct policy_handle *handle)
8571 union spoolss_PrinterInfo info;
8572 struct spoolss_SetPrinterInfo7 info7;
8573 struct spoolss_SetPrinterInfoCtr info_ctr;
8574 struct spoolss_DevmodeContainer devmode_ctr;
8575 struct sec_desc_buf secdesc_ctr;
8577 info7.guid = "";
8578 info7.action = DSPRINT_PUBLISH;
8580 ZERO_STRUCT(info_ctr);
8581 ZERO_STRUCT(devmode_ctr);
8582 ZERO_STRUCT(secdesc_ctr);
8583 info_ctr.level = 7;
8584 info_ctr.info.info7 = &info7;
8586 torture_assert(tctx,
8587 test_SetPrinter(tctx, b, handle, &info_ctr,
8588 &devmode_ctr, &secdesc_ctr, 0), "");
8590 torture_assert(tctx,
8591 test_GetPrinter_level(tctx, b, handle, 2, &info),
8592 "");
8593 torture_assert(tctx,
8594 (info.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED),
8595 "info2 publish flag not set");
8596 torture_assert(tctx,
8597 test_GetPrinter_level(tctx, b, handle, 7, &info),
8598 "");
8599 if (info.info7.action & DSPRINT_PENDING) {
8600 torture_comment(tctx, "publish is pending\n");
8601 torture_assert_int_equal(tctx,
8602 info.info7.action,
8603 (DSPRINT_PENDING | DSPRINT_PUBLISH),
8604 "info7 publish flag not set");
8605 } else {
8606 struct GUID guid;
8607 torture_assert_int_equal(tctx,
8608 info.info7.action,
8609 DSPRINT_PUBLISH,
8610 "info7 publish flag not set");
8611 torture_assert_ntstatus_ok(tctx,
8612 GUID_from_string(info.info7.guid,
8613 &guid),
8614 "invalid published printer GUID");
8617 return true;
8620 static bool test_printer_set_unpublish(struct torture_context *tctx,
8621 struct dcerpc_binding_handle *b,
8622 struct policy_handle *handle)
8624 union spoolss_PrinterInfo info;
8625 struct spoolss_SetPrinterInfo7 info7;
8626 struct spoolss_SetPrinterInfoCtr info_ctr;
8627 struct spoolss_DevmodeContainer devmode_ctr;
8628 struct sec_desc_buf secdesc_ctr;
8630 info7.action = DSPRINT_UNPUBLISH;
8631 info7.guid = "";
8633 ZERO_STRUCT(info_ctr);
8634 ZERO_STRUCT(devmode_ctr);
8635 ZERO_STRUCT(secdesc_ctr);
8636 info_ctr.level = 7;
8637 info_ctr.info.info7 = &info7;
8639 torture_assert(tctx,
8640 test_SetPrinter(tctx, b, handle, &info_ctr,
8641 &devmode_ctr, &secdesc_ctr, 0), "");
8643 torture_assert(tctx,
8644 test_GetPrinter_level(tctx, b, handle, 2, &info),
8645 "");
8646 torture_assert(tctx,
8647 !(info.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED),
8648 "info2 publish flag still set");
8649 torture_assert(tctx,
8650 test_GetPrinter_level(tctx, b, handle, 7, &info),
8651 "");
8653 if (info.info7.action & DSPRINT_PENDING) {
8654 struct GUID guid;
8655 torture_comment(tctx, "unpublish is pending\n");
8656 torture_assert_int_equal(tctx,
8657 info.info7.action,
8658 (DSPRINT_PENDING | DSPRINT_UNPUBLISH),
8659 "info7 unpublish flag not set");
8660 torture_assert_ntstatus_ok(tctx,
8661 GUID_from_string(info.info7.guid,
8662 &guid),
8663 "invalid printer GUID");
8664 } else {
8665 torture_assert_int_equal(tctx,
8666 info.info7.action, DSPRINT_UNPUBLISH,
8667 "info7 unpublish flag not set");
8670 return true;
8673 static bool test_printer_publish_toggle(struct torture_context *tctx,
8674 void *private_data)
8676 struct torture_printer_context *t =
8677 talloc_get_type_abort(private_data,
8678 struct torture_printer_context);
8679 struct dcerpc_pipe *p = t->spoolss_pipe;
8680 struct dcerpc_binding_handle *b = p->binding_handle;
8681 struct policy_handle *handle = &t->handle;
8682 union spoolss_PrinterInfo info7;
8683 union spoolss_PrinterInfo info2;
8685 /* check publish status via level 7 and level 2 */
8686 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 7, &info7),
8687 "");
8688 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info2),
8689 "");
8691 if (info2.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
8692 torture_assert_int_equal(tctx,
8693 info7.info7.action, DSPRINT_PUBLISH,
8694 "info7 publish flag not set");
8695 torture_assert(tctx, test_printer_set_unpublish(tctx, b, handle), "");
8696 torture_assert(tctx, test_printer_set_publish(tctx, b, handle), "");
8697 } else {
8698 torture_assert_int_equal(tctx,
8699 info7.info7.action, DSPRINT_UNPUBLISH,
8700 "info7 unpublish flag not set");
8701 torture_assert(tctx, test_printer_set_publish(tctx, b, handle), "");
8702 torture_assert(tctx, test_printer_set_unpublish(tctx, b, handle), "");
8705 return true;
8708 static bool test_driver_info_winreg(struct torture_context *tctx,
8709 void *private_data)
8711 struct torture_printer_context *t =
8712 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
8713 struct dcerpc_pipe *p = t->spoolss_pipe;
8714 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
8716 if (!t->have_driver) {
8717 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
8720 torture_assert(tctx,
8721 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
8722 "failed to test driver info winreg");
8724 return true;
8727 void torture_tcase_printer(struct torture_tcase *tcase)
8729 torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
8730 torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
8731 torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
8732 torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
8733 torture_tcase_add_simple_test(tcase, "print_test_smbd", test_print_test_smbd);
8734 torture_tcase_add_simple_test(tcase, "print_test_properties", test_print_test_properties);
8735 torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
8736 torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
8737 torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
8738 torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
8739 torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
8740 torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
8741 torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
8742 torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
8743 torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
8744 torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
8745 torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
8746 torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
8747 torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
8748 torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
8749 torture_tcase_add_simple_test(tcase, "printer_ic", test_printer_ic);
8750 torture_tcase_add_simple_test(tcase, "bidi", test_printer_bidi);
8751 torture_tcase_add_simple_test(tcase, "publish_toggle",
8752 test_printer_publish_toggle);
8755 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
8757 struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
8758 struct torture_tcase *tcase;
8760 tcase = torture_suite_add_tcase(suite, "addprinter");
8762 torture_tcase_set_fixture(tcase,
8763 torture_rpc_spoolss_printer_setup,
8764 torture_rpc_spoolss_printer_teardown);
8766 torture_tcase_printer(tcase);
8768 tcase = torture_suite_add_tcase(suite, "addprinterex");
8770 torture_tcase_set_fixture(tcase,
8771 torture_rpc_spoolss_printerex_setup,
8772 torture_rpc_spoolss_printer_teardown);
8774 torture_tcase_printer(tcase);
8776 tcase = torture_suite_add_tcase(suite, "addprinterwkn");
8778 torture_tcase_set_fixture(tcase,
8779 torture_rpc_spoolss_printerwkn_setup,
8780 torture_rpc_spoolss_printer_teardown);
8782 tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
8784 torture_tcase_set_fixture(tcase,
8785 torture_rpc_spoolss_printerexwkn_setup,
8786 torture_rpc_spoolss_printer_teardown);
8788 #if 0
8789 /* test is not correct */
8790 tcase = torture_suite_add_tcase(suite, "addprinterdm");
8792 torture_tcase_set_fixture(tcase,
8793 torture_rpc_spoolss_printerdm_setup,
8794 torture_rpc_spoolss_printer_teardown);
8796 torture_tcase_printer(tcase);
8797 #endif
8798 return suite;
8801 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
8803 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
8804 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
8806 torture_tcase_set_fixture(tcase,
8807 torture_rpc_spoolss_setup,
8808 torture_rpc_spoolss_teardown);
8810 torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
8811 torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
8812 torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
8813 torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
8814 torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
8815 torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
8816 torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
8817 torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
8818 torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
8819 torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
8820 torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
8821 torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
8822 torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
8823 torture_tcase_add_simple_test(tcase, "add_processor", test_add_print_processor);
8824 torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
8825 torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
8826 torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
8827 torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
8828 torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
8829 torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
8830 torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
8832 torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
8834 return suite;
8837 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
8838 struct dcerpc_binding_handle *b,
8839 const char *server,
8840 const char *environment,
8841 const char **dir_p)
8843 struct spoolss_GetPrinterDriverDirectory r;
8844 uint32_t needed;
8846 r.in.server = server;
8847 r.in.environment = environment;
8848 r.in.level = 1;
8849 r.in.buffer = NULL;
8850 r.in.offered = 0;
8851 r.out.needed = &needed;
8853 torture_assert_ntstatus_ok(tctx,
8854 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8855 "failed to query driver directory");
8857 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
8858 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
8859 r.in.buffer = &blob;
8860 r.in.offered = needed;
8862 torture_assert_ntstatus_ok(tctx,
8863 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8864 "failed to query driver directory");
8867 torture_assert_werr_ok(tctx, r.out.result,
8868 "failed to query driver directory");
8870 if (dir_p) {
8871 *dir_p = r.out.info->info1.directory_name;
8874 return true;
8877 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8879 if (info_ctr == NULL) {
8880 return NULL;
8883 switch (info_ctr->level) {
8884 case 1:
8885 return info_ctr->info.info1->driver_name;
8886 case 2:
8887 return info_ctr->info.info2->driver_name;
8888 case 3:
8889 return info_ctr->info.info3->driver_name;
8890 case 4:
8891 return info_ctr->info.info4->driver_name;
8892 case 6:
8893 return info_ctr->info.info6->driver_name;
8894 case 8:
8895 return info_ctr->info.info8->driver_name;
8896 default:
8897 return NULL;
8901 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8903 if (info_ctr == NULL) {
8904 return NULL;
8907 switch (info_ctr->level) {
8908 case 2:
8909 return info_ctr->info.info2->architecture;
8910 case 3:
8911 return info_ctr->info.info3->architecture;
8912 case 4:
8913 return info_ctr->info.info4->architecture;
8914 case 6:
8915 return info_ctr->info.info6->architecture;
8916 case 8:
8917 return info_ctr->info.info8->architecture;
8918 default:
8919 return NULL;
8924 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
8925 struct dcerpc_binding_handle *b,
8926 const char *servername,
8927 struct spoolss_AddDriverInfoCtr *info_ctr,
8928 WERROR expected_result)
8930 struct spoolss_AddPrinterDriver r;
8931 const char *drivername = get_driver_from_info(info_ctr);
8932 const char *environment = get_environment_from_info(info_ctr);
8934 r.in.servername = servername;
8935 r.in.info_ctr = info_ctr;
8937 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
8938 drivername, info_ctr->level, environment);
8940 torture_assert_ntstatus_ok(tctx,
8941 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
8942 "spoolss_AddPrinterDriver failed");
8943 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8944 "spoolss_AddPrinterDriver failed with unexpected result");
8946 return true;
8950 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
8951 struct dcerpc_binding_handle *b,
8952 const char *servername,
8953 struct spoolss_AddDriverInfoCtr *info_ctr,
8954 uint32_t flags,
8955 WERROR expected_result)
8957 struct spoolss_AddPrinterDriverEx r;
8958 const char *drivername = get_driver_from_info(info_ctr);
8959 const char *environment = get_environment_from_info(info_ctr);
8961 r.in.servername = servername;
8962 r.in.info_ctr = info_ctr;
8963 r.in.flags = flags;
8965 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
8966 drivername, info_ctr->level, environment);
8968 torture_assert_ntstatus_ok(tctx,
8969 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
8970 "AddPrinterDriverEx failed");
8971 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8972 "AddPrinterDriverEx failed with unexpected result");
8974 return true;
8977 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
8978 if (path && strlen(path)) {\
8979 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
8982 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
8983 struct dcerpc_binding_handle *b,
8984 const char *server_name,
8985 struct spoolss_AddDriverInfo8 *r,
8986 uint32_t flags,
8987 bool ex,
8988 const char *remote_driver_dir)
8990 struct spoolss_AddDriverInfoCtr info_ctr;
8991 struct spoolss_AddDriverInfo1 info1;
8993 ZERO_STRUCT(info1);
8995 info_ctr.level = 1;
8996 info_ctr.info.info1 = &info1;
8998 if (ex) {
8999 torture_assert(tctx,
9000 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
9001 "failed to test AddPrinterDriverEx level 1");
9002 } else {
9003 torture_assert(tctx,
9004 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9005 "failed to test AddPrinterDriver level 1");
9008 info1.driver_name = r->driver_name;
9010 if (ex) {
9011 torture_assert(tctx,
9012 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
9013 "failed to test AddPrinterDriverEx level 1");
9014 } else {
9015 torture_assert(tctx,
9016 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9017 "failed to test AddPrinterDriver level 1");
9020 return true;
9023 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
9024 struct dcerpc_binding_handle *b,
9025 const char *server_name,
9026 struct spoolss_AddDriverInfo8 *r,
9027 uint32_t flags,
9028 bool ex,
9029 const char *remote_driver_dir)
9031 struct spoolss_AddDriverInfoCtr info_ctr;
9032 struct spoolss_AddDriverInfo2 info2;
9033 union spoolss_DriverInfo info;
9035 ZERO_STRUCT(info2);
9037 info_ctr.level = 2;
9038 info_ctr.info.info2 = &info2;
9040 if (ex) {
9041 torture_assert(tctx,
9042 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9043 "failed to test AddPrinterDriverEx level 2");
9044 } else {
9045 torture_assert(tctx,
9046 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9047 "failed to test AddPrinterDriver level 2");
9050 info2.driver_name = r->driver_name;
9052 if (ex) {
9053 torture_assert(tctx,
9054 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9055 "failed to test AddPrinterDriverEx level 2");
9056 } else {
9057 torture_assert(tctx,
9058 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9059 "failed to test AddPrinterDriver level 2");
9062 info2.version = r->version;
9064 if (ex) {
9065 torture_assert(tctx,
9066 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9067 "failed to test AddPrinterDriverEx level 2");
9068 } else {
9069 torture_assert(tctx,
9070 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9071 "failed to test AddPrinterDriver level 2");
9074 info2.architecture = r->architecture;
9076 if (ex) {
9077 torture_assert(tctx,
9078 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9079 "failed to test AddPrinterDriverEx level 2");
9080 } else {
9081 torture_assert(tctx,
9082 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9083 "failed to test AddPrinterDriver level 2");
9086 info2.driver_path = r->driver_path;
9088 if (ex) {
9089 torture_assert(tctx,
9090 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9091 "failed to test AddPrinterDriverEx level 2");
9092 } else {
9093 torture_assert(tctx,
9094 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9095 "failed to test AddPrinterDriver level 2");
9098 info2.data_file = r->data_file;
9100 if (ex) {
9101 torture_assert(tctx,
9102 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
9103 "failed to test AddPrinterDriverEx level 2");
9104 } else {
9105 torture_assert(tctx,
9106 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
9107 "failed to test AddPrinterDriver level 2");
9110 info2.config_file = r->config_file;
9112 if (ex) {
9113 torture_assert(tctx,
9114 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
9115 "failed to test AddPrinterDriverEx");
9118 if (ex) {
9119 torture_assert(tctx,
9120 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9121 "failed to test AddPrinterDriverEx level 2");
9122 } else {
9123 torture_assert(tctx,
9124 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
9125 "failed to test AddPrinterDriver level 2");
9128 torture_assert(tctx,
9129 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
9130 "failed to find added printer driver");
9132 if (remote_driver_dir) {
9133 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
9134 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
9135 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
9138 return true;
9141 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
9142 struct dcerpc_binding_handle *b,
9143 const char *server_name,
9144 struct spoolss_AddDriverInfo8 *r,
9145 uint32_t flags,
9146 bool ex,
9147 const char *remote_driver_dir)
9149 struct spoolss_AddDriverInfoCtr info_ctr;
9150 struct spoolss_AddDriverInfo3 info3;
9151 union spoolss_DriverInfo info;
9153 info3.driver_name = r->driver_name;
9154 info3.version = r->version;
9155 info3.architecture = r->architecture;
9156 info3.driver_path = r->driver_path;
9157 info3.data_file = r->data_file;
9158 info3.config_file = r->config_file;
9159 info3.help_file = r->help_file;
9160 info3.monitor_name = r->monitor_name;
9161 info3.default_datatype = r->default_datatype;
9162 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
9163 info3.dependent_files = r->dependent_files;
9165 info_ctr.level = 3;
9166 info_ctr.info.info3 = &info3;
9168 if (ex) {
9169 torture_assert(tctx,
9170 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9171 "failed to test AddPrinterDriverEx level 3");
9172 } else {
9173 torture_assert(tctx,
9174 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
9175 "failed to test AddPrinterDriver level 3");
9178 torture_assert(tctx,
9179 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
9180 "failed to find added printer driver");
9182 if (remote_driver_dir) {
9183 int i;
9184 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
9185 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
9186 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
9187 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
9188 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
9189 ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
9193 return true;
9196 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
9197 struct dcerpc_binding_handle *b,
9198 const char *server_name,
9199 struct spoolss_AddDriverInfo8 *r,
9200 uint32_t flags,
9201 bool ex,
9202 const char *remote_driver_dir)
9204 struct spoolss_AddDriverInfoCtr info_ctr;
9205 struct spoolss_AddDriverInfo4 info4;
9206 union spoolss_DriverInfo info;
9208 info4.version = r->version;
9209 info4.driver_name = r->driver_name;
9210 info4.architecture = r->architecture;
9211 info4.driver_path = r->driver_path;
9212 info4.data_file = r->data_file;
9213 info4.config_file = r->config_file;
9214 info4.help_file = r->help_file;
9215 info4.monitor_name = r->monitor_name;
9216 info4.default_datatype = r->default_datatype;
9217 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
9218 info4.dependent_files = r->dependent_files;
9219 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
9220 info4.previous_names = r->previous_names;
9222 info_ctr.level = 4;
9223 info_ctr.info.info4 = &info4;
9225 if (ex) {
9226 torture_assert(tctx,
9227 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9228 "failed to test AddPrinterDriverEx level 4");
9229 } else {
9230 torture_assert(tctx,
9231 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
9232 "failed to test AddPrinterDriver level 4");
9235 torture_assert(tctx,
9236 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
9237 "failed to find added printer driver");
9239 if (remote_driver_dir) {
9240 int i;
9241 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
9242 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
9243 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
9244 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
9245 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
9246 ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
9250 return true;
9253 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
9254 struct dcerpc_binding_handle *b,
9255 const char *server_name,
9256 struct spoolss_AddDriverInfo8 *r,
9257 uint32_t flags,
9258 bool ex,
9259 const char *remote_driver_dir)
9261 struct spoolss_AddDriverInfoCtr info_ctr;
9262 struct spoolss_AddDriverInfo6 info6;
9263 union spoolss_DriverInfo info;
9265 info6.version = r->version;
9266 info6.driver_name = r->driver_name;
9267 info6.architecture = r->architecture;
9268 info6.driver_path = r->driver_path;
9269 info6.data_file = r->data_file;
9270 info6.config_file = r->config_file;
9271 info6.help_file = r->help_file;
9272 info6.monitor_name = r->monitor_name;
9273 info6.default_datatype = r->default_datatype;
9274 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
9275 info6.dependent_files = r->dependent_files;
9276 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
9277 info6.previous_names = r->previous_names;
9278 info6.driver_date = r->driver_date;
9279 info6.driver_version = r->driver_version;
9280 info6.manufacturer_name = r->manufacturer_name;
9281 info6.manufacturer_url = r->manufacturer_url;
9282 info6.hardware_id = r->hardware_id;
9283 info6.provider = r->provider;
9285 info_ctr.level = 6;
9286 info_ctr.info.info6 = &info6;
9288 if (ex) {
9289 torture_assert(tctx,
9290 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9291 "failed to test AddPrinterDriverEx level 6");
9292 } else {
9293 torture_assert(tctx,
9294 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9295 "failed to test AddPrinterDriver level 6");
9298 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9300 if (!ex) {
9301 return true;
9304 torture_assert(tctx,
9305 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
9306 "failed to find added printer driver");
9308 if (remote_driver_dir) {
9309 int i;
9310 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
9311 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
9312 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
9313 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
9314 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
9315 ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
9319 torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
9320 torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
9322 return true;
9325 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
9326 struct dcerpc_binding_handle *b,
9327 const char *server_name,
9328 struct spoolss_AddDriverInfo8 *r,
9329 uint32_t flags,
9330 bool ex,
9331 const char *remote_driver_dir)
9333 struct spoolss_AddDriverInfoCtr info_ctr;
9334 union spoolss_DriverInfo info;
9336 info_ctr.level = 8;
9337 info_ctr.info.info8 = r;
9339 if (ex) {
9340 torture_assert(tctx,
9341 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
9342 "failed to test AddPrinterDriverEx level 8");
9343 } else {
9344 torture_assert(tctx,
9345 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
9346 "failed to test AddPrinterDriver level 8");
9349 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9351 if (!ex) {
9352 return true;
9355 torture_assert(tctx,
9356 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
9357 "failed to find added printer driver");
9359 if (remote_driver_dir) {
9360 int i;
9361 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
9362 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
9363 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
9364 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
9365 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
9366 ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
9370 torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
9371 torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
9373 return true;
9376 #undef ASSERT_DRIVER_PATH
9378 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
9379 struct dcerpc_binding_handle *b,
9380 const char *server,
9381 const char *driver,
9382 const char *environment,
9383 WERROR expected_result)
9385 struct spoolss_DeletePrinterDriver r;
9387 r.in.server = server;
9388 r.in.architecture = environment;
9389 r.in.driver = driver;
9391 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
9393 torture_assert_ntstatus_ok(tctx,
9394 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
9395 "DeletePrinterDriver failed");
9396 torture_assert_werr_equal(tctx, r.out.result, expected_result,
9397 "DeletePrinterDriver failed with unexpected result");
9399 return true;
9402 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
9403 struct dcerpc_binding_handle *b,
9404 const char *server,
9405 const char *driver,
9406 const char *environment,
9407 uint32_t delete_flags,
9408 uint32_t version,
9409 WERROR expected_result)
9411 struct spoolss_DeletePrinterDriverEx r;
9413 r.in.server = server;
9414 r.in.architecture = environment;
9415 r.in.driver = driver;
9416 r.in.delete_flags = delete_flags;
9417 r.in.version = version;
9419 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
9421 torture_assert_ntstatus_ok(tctx,
9422 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
9423 "DeletePrinterDriverEx failed");
9424 torture_assert_werr_equal(tctx, r.out.result, expected_result,
9425 "DeletePrinterDriverEx failed with unexpected result");
9427 return true;
9430 static bool test_DeletePrinterDriver(struct torture_context *tctx,
9431 struct dcerpc_binding_handle *b,
9432 const char *server_name,
9433 const char *driver,
9434 const char *environment)
9436 torture_assert(tctx,
9437 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
9438 "failed to delete driver");
9440 torture_assert(tctx,
9441 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
9442 "failed to delete driver");
9444 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
9445 torture_fail(tctx, "deleted driver still enumerated");
9448 torture_assert(tctx,
9449 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
9450 "2nd delete failed");
9452 return true;
9455 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
9456 struct dcerpc_binding_handle *b,
9457 const char *server_name,
9458 const char *driver,
9459 const char *environment,
9460 uint32_t delete_flags,
9461 uint32_t version)
9463 torture_assert(tctx,
9464 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
9465 "failed to delete driver");
9467 torture_assert(tctx,
9468 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
9469 "failed to delete driver");
9471 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
9472 torture_fail(tctx, "deleted driver still enumerated");
9475 torture_assert(tctx,
9476 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
9477 "2nd delete failed");
9479 return true;
9482 static bool test_PrinterDriver_args(struct torture_context *tctx,
9483 struct dcerpc_binding_handle *b,
9484 const char *server_name,
9485 uint32_t level,
9486 struct spoolss_AddDriverInfo8 *r,
9487 uint32_t add_flags,
9488 uint32_t delete_flags,
9489 uint32_t delete_version,
9490 bool ex,
9491 const char *remote_driver_dir)
9493 bool ret = true;
9495 switch (level) {
9496 case 1:
9497 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9498 break;
9499 case 2:
9500 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9501 break;
9502 case 3:
9503 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9504 break;
9505 case 4:
9506 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9507 break;
9508 case 6:
9509 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9510 break;
9511 case 8:
9512 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
9513 break;
9514 default:
9515 return false;
9518 if (ret == false) {
9519 return ret;
9522 if (level == 1) {
9523 return ret;
9526 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
9528 if (!ex && (level == 6 || level == 8)) {
9529 return ret;
9533 struct dcerpc_pipe *p2;
9534 struct policy_handle hive_handle;
9535 struct dcerpc_binding_handle *b2;
9537 torture_assert_ntstatus_ok(tctx,
9538 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
9539 "could not open winreg pipe");
9540 b2 = p2->binding_handle;
9542 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
9544 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
9546 test_winreg_CloseKey(tctx, b2, &hive_handle);
9548 talloc_free(p2);
9551 if (ex) {
9552 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
9553 } else {
9554 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
9558 static bool fillup_printserver_info(struct torture_context *tctx,
9559 struct dcerpc_pipe *p,
9560 struct torture_driver_context *d)
9562 struct policy_handle server_handle;
9563 struct dcerpc_binding_handle *b = p->binding_handle;
9564 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9566 torture_assert(tctx,
9567 test_OpenPrinter_server(tctx, p, &server_handle),
9568 "failed to open printserver");
9569 torture_assert(tctx,
9570 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
9571 "failed to get environment");
9572 torture_assert(tctx,
9573 test_ClosePrinter(tctx, b, &server_handle),
9574 "failed to close printserver");
9576 torture_assert(tctx,
9577 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
9578 d->local.environment ? d->local.environment : d->remote.environment,
9579 &d->remote.driver_directory),
9580 "failed to get driver directory");
9582 return true;
9585 static const char *driver_directory_dir(const char *driver_directory)
9587 char *p;
9589 p = strrchr(driver_directory, '\\');
9590 if (p) {
9591 return p+1;
9594 return NULL;
9597 static const char *driver_directory_share(struct torture_context *tctx,
9598 const char *driver_directory)
9600 const char *p;
9601 char *tok;
9603 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
9604 driver_directory += 2;
9607 p = talloc_strdup(tctx, driver_directory);
9609 torture_assert(tctx,
9610 next_token_talloc(tctx, &p, &tok, "\\"),
9611 "cannot explode uri");
9612 torture_assert(tctx,
9613 next_token_talloc(tctx, &p, &tok, "\\"),
9614 "cannot explode uri");
9616 return tok;
9619 static bool upload_printer_driver_file(struct torture_context *tctx,
9620 struct smbcli_state *cli,
9621 struct torture_driver_context *d,
9622 const char *file_name)
9624 XFILE *f;
9625 int fnum;
9626 uint8_t *buf;
9627 int maxwrite = 64512;
9628 off_t nread = 0;
9629 size_t start = 0;
9630 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
9631 const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
9632 const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
9634 if (!file_name || strlen(file_name) == 0) {
9635 return true;
9638 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
9640 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
9641 if (fnum == -1) {
9642 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
9645 f = x_fopen(local_name, O_RDONLY, 0);
9646 if (f == NULL) {
9647 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
9650 buf = talloc_array(tctx, uint8_t, maxwrite);
9651 if (!buf) {
9652 x_fclose(f);
9653 return false;
9656 while (!x_feof(f)) {
9657 int n = maxwrite;
9658 int ret;
9660 if ((n = x_fread(buf, 1, n, f)) < 1) {
9661 if((n == 0) && x_feof(f))
9662 break; /* Empty local file. */
9664 torture_warning(tctx,
9665 "failed to read file: %s\n", strerror(errno));
9666 break;
9669 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
9671 if (n != ret) {
9672 torture_warning(tctx,
9673 "failed to write file: %s\n", smbcli_errstr(cli->tree));
9674 break;
9677 nread += n;
9680 x_fclose(f);
9682 torture_assert_ntstatus_ok(tctx,
9683 smbcli_close(cli->tree, fnum),
9684 "failed to close file");
9686 return true;
9689 static bool connect_printer_driver_share(struct torture_context *tctx,
9690 const char *server_name,
9691 const char *share_name,
9692 struct smbcli_state **cli)
9694 struct smbcli_options smb_options;
9695 struct smbcli_session_options smb_session_options;
9697 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
9698 share_name, server_name);
9700 lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
9701 lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
9703 torture_assert_ntstatus_ok(tctx,
9704 smbcli_full_connection(tctx, cli, server_name,
9705 lpcfg_smb_ports(tctx->lp_ctx),
9706 share_name, NULL,
9707 lpcfg_socket_options(tctx->lp_ctx),
9708 cmdline_credentials,
9709 lpcfg_resolve_context(tctx->lp_ctx),
9710 tctx->ev,
9711 &smb_options,
9712 &smb_session_options,
9713 lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
9714 "failed to open driver share");
9716 return true;
9719 static bool upload_printer_driver(struct torture_context *tctx,
9720 const char *server_name,
9721 struct torture_driver_context *d)
9723 struct smbcli_state *cli;
9724 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9725 int i;
9727 torture_assert(tctx,
9728 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9729 "failed to connect to driver share");
9731 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
9732 server_name, share_name);
9734 torture_assert(tctx,
9735 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
9736 "failed to upload driver_path");
9737 torture_assert(tctx,
9738 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
9739 "failed to upload data_file");
9740 torture_assert(tctx,
9741 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
9742 "failed to upload config_file");
9743 torture_assert(tctx,
9744 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
9745 "failed to upload help_file");
9746 if (d->info8.dependent_files) {
9747 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9748 torture_assert(tctx,
9749 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9750 "failed to upload dependent_files");
9754 talloc_free(cli);
9756 return true;
9759 static bool check_printer_driver_file(struct torture_context *tctx,
9760 struct smbcli_state *cli,
9761 struct torture_driver_context *d,
9762 const char *file_name)
9764 const char *remote_arch_dir = driver_directory_dir(d->remote.driver_directory);
9765 const char *remote_name = talloc_asprintf(tctx, "%s\\%d\\%s",
9766 remote_arch_dir,
9767 d->info8.version,
9768 file_name);
9769 int fnum;
9771 torture_assert(tctx, (file_name && strlen(file_name) != 0), "invalid filename");
9773 torture_comment(tctx, "checking for driver file at %s\n", remote_name);
9775 fnum = smbcli_open(cli->tree, remote_name, O_RDONLY, DENY_NONE);
9776 if (fnum == -1) {
9777 return false;
9780 torture_assert_ntstatus_ok(tctx,
9781 smbcli_close(cli->tree, fnum),
9782 "failed to close driver file");
9784 return true;
9787 static bool check_printer_driver_files(struct torture_context *tctx,
9788 const char *server_name,
9789 struct torture_driver_context *d,
9790 bool expect_exist)
9792 struct smbcli_state *cli;
9793 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9794 int i;
9796 torture_assert(tctx,
9797 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9798 "failed to connect to driver share");
9800 torture_comment(tctx, "checking %sexistent driver files at \\\\%s\\%s\n",
9801 (expect_exist ? "": "non-"),
9802 server_name, share_name);
9804 if (d->info8.driver_path && d->info8.driver_path[0]) {
9805 torture_assert(tctx,
9806 check_printer_driver_file(tctx, cli, d, d->info8.driver_path) == expect_exist,
9807 "failed driver_path check");
9809 if (d->info8.data_file && d->info8.data_file[0]) {
9810 torture_assert(tctx,
9811 check_printer_driver_file(tctx, cli, d, d->info8.data_file) == expect_exist,
9812 "failed data_file check");
9814 if (d->info8.config_file && d->info8.config_file[0]) {
9815 torture_assert(tctx,
9816 check_printer_driver_file(tctx, cli, d, d->info8.config_file) == expect_exist,
9817 "failed config_file check");
9819 if (d->info8.help_file && d->info8.help_file[0]) {
9820 torture_assert(tctx,
9821 check_printer_driver_file(tctx, cli, d, d->info8.help_file) == expect_exist,
9822 "failed help_file check");
9824 if (d->info8.dependent_files) {
9825 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9826 torture_assert(tctx,
9827 check_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]) == expect_exist,
9828 "failed dependent_files check");
9832 talloc_free(cli);
9834 return true;
9837 static bool remove_printer_driver_file(struct torture_context *tctx,
9838 struct smbcli_state *cli,
9839 struct torture_driver_context *d,
9840 const char *file_name)
9842 const char *remote_name;
9843 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
9845 if (!file_name || strlen(file_name) == 0) {
9846 return true;
9849 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
9851 torture_comment(tctx, "Removing %s\n", remote_name);
9853 torture_assert_ntstatus_ok(tctx,
9854 smbcli_unlink(cli->tree, remote_name),
9855 "failed to unlink");
9857 return true;
9860 static bool remove_printer_driver(struct torture_context *tctx,
9861 const char *server_name,
9862 struct torture_driver_context *d)
9864 struct smbcli_state *cli;
9865 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9866 int i;
9868 torture_assert(tctx,
9869 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9870 "failed to connect to driver share");
9872 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
9873 server_name, share_name);
9875 torture_assert(tctx,
9876 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
9877 "failed to remove driver_path");
9878 torture_assert(tctx,
9879 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
9880 "failed to remove data_file");
9881 if (!strequal(d->info8.config_file, d->info8.driver_path)) {
9882 torture_assert(tctx,
9883 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
9884 "failed to remove config_file");
9886 torture_assert(tctx,
9887 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
9888 "failed to remove help_file");
9889 if (d->info8.dependent_files) {
9890 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9891 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
9892 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
9893 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
9894 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
9895 continue;
9897 torture_assert(tctx,
9898 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9899 "failed to remove dependent_files");
9903 talloc_free(cli);
9905 return true;
9909 static bool test_add_driver_arg(struct torture_context *tctx,
9910 struct dcerpc_pipe *p,
9911 struct torture_driver_context *d)
9913 bool ret = true;
9914 struct dcerpc_binding_handle *b = p->binding_handle;
9915 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9916 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
9917 int i;
9918 struct spoolss_AddDriverInfo8 info8;
9919 uint32_t add_flags = APD_COPY_NEW_FILES;
9920 uint32_t delete_flags = 0;
9922 ZERO_STRUCT(info8);
9924 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
9925 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
9927 torture_assert(tctx,
9928 fillup_printserver_info(tctx, p, d),
9929 "failed to fillup printserver info");
9931 if (!directory_exist(d->local.driver_directory)) {
9932 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9935 torture_assert(tctx,
9936 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9937 "failed to upload printer driver");
9939 info8 = d->info8;
9940 if (d->info8.dependent_files) {
9941 info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
9942 if (d->info8.dependent_files->string) {
9943 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9945 info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
9946 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9947 info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
9951 info8.architecture = d->local.environment;
9953 for (i=0; i < ARRAY_SIZE(levels); i++) {
9955 if (torture_setting_bool(tctx, "samba3", false)) {
9956 switch (levels[i]) {
9957 case 2:
9958 case 4:
9959 case 8:
9960 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9961 continue;
9962 default:
9963 break;
9966 if (torture_setting_bool(tctx, "w2k3", false)) {
9967 switch (levels[i]) {
9968 case 8:
9969 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9970 continue;
9971 default:
9972 break;
9976 torture_comment(tctx,
9977 "Testing PrinterDriver%s '%s' add & delete level %d\n",
9978 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9980 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);
9983 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
9984 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
9985 if (d->info8.config_file) {
9986 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
9988 if (d->info8.help_file) {
9989 info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
9991 if (d->info8.dependent_files && d->info8.dependent_files->string) {
9992 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9993 info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
9997 for (i=0; i < ARRAY_SIZE(levels); i++) {
9999 if (torture_setting_bool(tctx, "samba3", false)) {
10000 switch (levels[i]) {
10001 case 2:
10002 case 4:
10003 case 8:
10004 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
10005 continue;
10006 default:
10007 break;
10010 if (torture_setting_bool(tctx, "w2k3", false)) {
10011 switch (levels[i]) {
10012 case 8:
10013 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
10014 continue;
10015 default:
10016 break;
10020 torture_comment(tctx,
10021 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
10022 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
10024 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);
10027 torture_assert(tctx,
10028 remove_printer_driver(tctx, dcerpc_server_name(p), d),
10029 "failed to remove printer driver");
10031 torture_comment(tctx, "\n");
10033 return ret;
10036 static bool test_add_driver_ex_64(struct torture_context *tctx,
10037 struct dcerpc_pipe *p)
10039 struct torture_driver_context *d;
10041 d = talloc_zero(tctx, struct torture_driver_context);
10043 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10044 d->info8.driver_name = TORTURE_DRIVER_EX;
10045 d->info8.architecture = NULL;
10046 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10047 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10048 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10049 d->local.environment = talloc_strdup(d, "Windows x64");
10050 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
10051 d->ex = true;
10053 return test_add_driver_arg(tctx, p, d);
10056 static bool test_add_driver_ex_32(struct torture_context *tctx,
10057 struct dcerpc_pipe *p)
10059 struct torture_driver_context *d;
10061 d = talloc_zero(tctx, struct torture_driver_context);
10063 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10064 d->info8.driver_name = TORTURE_DRIVER_EX;
10065 d->info8.architecture = NULL;
10066 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10067 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10068 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10069 d->local.environment = talloc_strdup(d, "Windows NT x86");
10070 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10071 d->ex = true;
10073 return test_add_driver_arg(tctx, p, d);
10076 static bool test_add_driver_64(struct torture_context *tctx,
10077 struct dcerpc_pipe *p)
10079 struct torture_driver_context *d;
10081 d = talloc_zero(tctx, struct torture_driver_context);
10083 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10084 d->info8.driver_name = TORTURE_DRIVER;
10085 d->info8.architecture = NULL;
10086 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10087 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10088 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10089 d->local.environment = talloc_strdup(d, "Windows x64");
10090 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
10091 d->ex = false;
10093 return test_add_driver_arg(tctx, p, d);
10096 static bool test_add_driver_32(struct torture_context *tctx,
10097 struct dcerpc_pipe *p)
10099 struct torture_driver_context *d;
10101 d = talloc_zero(tctx, struct torture_driver_context);
10103 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10104 d->info8.driver_name = TORTURE_DRIVER;
10105 d->info8.architecture = NULL;
10106 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10107 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10108 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10109 d->local.environment = talloc_strdup(d, "Windows NT x86");
10110 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10111 d->ex = false;
10113 return test_add_driver_arg(tctx, p, d);
10116 static bool test_add_driver_adobe(struct torture_context *tctx,
10117 struct dcerpc_pipe *p)
10119 struct torture_driver_context *d;
10121 if (!torture_setting_bool(tctx, "samba3", false)) {
10122 torture_skip(tctx, "skipping adobe test which only works against samba3");
10125 d = talloc_zero(tctx, struct torture_driver_context);
10127 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
10128 d->info8.driver_name = TORTURE_DRIVER_ADOBE;
10129 d->info8.architecture = NULL;
10130 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
10131 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
10132 d->info8.config_file = talloc_strdup(d, "ADOBEPS4.DRV");
10133 #if 0
10134 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
10135 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
10136 #endif
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_adobe_cupsaddsmb(struct torture_context *tctx,
10145 struct dcerpc_pipe *p)
10147 struct torture_driver_context *d;
10148 struct spoolss_StringArray *a;
10150 if (!torture_setting_bool(tctx, "samba3", false)) {
10151 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
10154 d = talloc_zero(tctx, struct torture_driver_context);
10156 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
10157 d->info8.driver_name = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
10158 d->info8.architecture = NULL;
10159 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
10160 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
10161 d->info8.config_file = NULL;
10162 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
10163 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
10164 d->info8.default_datatype = talloc_strdup(d, "RAW");
10166 a = talloc_zero(d, struct spoolss_StringArray);
10167 a->string = talloc_zero_array(a, const char *, 7);
10168 a->string[0] = talloc_strdup(a->string, "ADOBEPS4.DRV");
10169 a->string[1] = talloc_strdup(a->string, "DEFPRTR2.PPD");
10170 a->string[2] = talloc_strdup(a->string, "ADOBEPS4.HLP");
10171 a->string[3] = talloc_strdup(a->string, "PSMON.DLL");
10172 a->string[4] = talloc_strdup(a->string, "ADFONTS.MFM");
10173 a->string[5] = talloc_strdup(a->string, "ICONLIB.DLL");
10175 d->info8.dependent_files = a;
10176 d->local.environment = talloc_strdup(d, "Windows 4.0");
10177 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
10178 d->ex = false;
10180 return test_add_driver_arg(tctx, p, d);
10183 static bool test_add_driver_timestamps(struct torture_context *tctx,
10184 struct dcerpc_pipe *p)
10186 struct torture_driver_context *d;
10187 struct timeval t = timeval_current();
10189 d = talloc_zero(tctx, struct torture_driver_context);
10191 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10192 d->info8.driver_name = TORTURE_DRIVER_TIMESTAMPS;
10193 d->info8.architecture = NULL;
10194 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10195 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10196 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10197 d->info8.driver_date = timeval_to_nttime(&t);
10198 d->local.environment = talloc_strdup(d, "Windows NT x86");
10199 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10200 d->ex = true;
10202 torture_assert(tctx,
10203 test_add_driver_arg(tctx, p, d),
10204 "");
10206 unix_to_nt_time(&d->info8.driver_date, 1);
10208 torture_assert(tctx,
10209 test_add_driver_arg(tctx, p, d),
10210 "");
10212 return true;
10215 static bool test_multiple_drivers(struct torture_context *tctx,
10216 struct dcerpc_pipe *p)
10218 struct torture_driver_context *d;
10219 struct dcerpc_binding_handle *b = p->binding_handle;
10220 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10221 int i;
10222 struct spoolss_AddDriverInfo8 info8;
10223 uint32_t add_flags = APD_COPY_NEW_FILES;
10224 uint32_t delete_flags = 0;
10226 d = talloc_zero(tctx, struct torture_driver_context);
10228 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10229 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10230 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10231 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10232 d->local.environment = talloc_strdup(d, "Windows NT x86");
10233 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
10234 d->ex = true;
10236 torture_assert(tctx,
10237 fillup_printserver_info(tctx, p, d),
10238 "failed to fillup printserver info");
10240 if (!directory_exist(d->local.driver_directory)) {
10241 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10244 torture_assert(tctx,
10245 upload_printer_driver(tctx, dcerpc_server_name(p), d),
10246 "failed to upload printer driver");
10248 info8 = d->info8;
10249 info8.architecture = d->local.environment;
10251 for (i=0; i < 3; i++) {
10252 info8.driver_name = talloc_asprintf(d, "torture_test_driver_%d", i);
10254 torture_assert(tctx,
10255 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &info8, add_flags, true, NULL),
10256 "failed to add driver");
10259 torture_assert(tctx,
10260 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_0", info8.architecture, delete_flags, info8.version),
10261 "failed to delete driver");
10263 torture_assert(tctx,
10264 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_1", NULL),
10265 "torture_test_driver_1 no longer on the server");
10267 torture_assert(tctx,
10268 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
10269 "torture_test_driver_2 no longer on the server");
10271 torture_assert(tctx,
10272 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_1", info8.architecture, delete_flags, info8.version),
10273 "failed to delete driver");
10275 torture_assert(tctx,
10276 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
10277 "torture_test_driver_2 no longer on the server");
10279 torture_assert(tctx,
10280 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_2", info8.architecture, delete_flags, info8.version),
10281 "failed to delete driver");
10283 torture_assert(tctx,
10284 remove_printer_driver(tctx, dcerpc_server_name(p), d),
10285 "failed to remove printer driver");
10287 return true;
10290 static bool test_del_driver_all_files(struct torture_context *tctx,
10291 struct dcerpc_pipe *p)
10293 struct torture_driver_context *d;
10294 struct spoolss_StringArray *a;
10295 uint32_t add_flags = APD_COPY_NEW_FILES;
10296 uint32_t delete_flags = DPD_DELETE_ALL_FILES;
10297 struct dcerpc_binding_handle *b = p->binding_handle;
10298 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10300 d = talloc_zero(tctx, struct torture_driver_context);
10302 d->ex = true;
10303 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10304 d->info8.driver_name = TORTURE_DRIVER_DELETER;
10305 d->info8.architecture = NULL;
10306 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
10307 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
10308 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
10309 d->info8.help_file = talloc_strdup(d, "pscript.hlp");
10310 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
10311 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
10313 a = talloc_zero(d, struct spoolss_StringArray);
10314 a->string = talloc_zero_array(a, const char *, 3);
10315 a->string[0] = talloc_strdup(a->string, "cups6.inf");
10316 a->string[1] = talloc_strdup(a->string, "cups6.ini");
10318 d->info8.dependent_files = a;
10319 d->info8.architecture = d->local.environment;
10321 torture_assert(tctx,
10322 fillup_printserver_info(tctx, p, d),
10323 "failed to fillup printserver info");
10325 if (!directory_exist(d->local.driver_directory)) {
10326 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10329 torture_assert(tctx,
10330 upload_printer_driver(tctx, dcerpc_server_name(p), d),
10331 "failed to upload printer driver");
10333 torture_assert(tctx,
10334 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d->info8, add_flags, true, NULL),
10335 "failed to add driver");
10337 torture_assert(tctx,
10338 test_DeletePrinterDriverEx(tctx, b, server_name_slash,
10339 d->info8.driver_name,
10340 d->local.environment,
10341 delete_flags,
10342 d->info8.version),
10343 "failed to delete driver");
10345 torture_assert(tctx,
10346 check_printer_driver_files(tctx, dcerpc_server_name(p), d, false),
10347 "printer driver file check failed");
10349 talloc_free(d);
10350 return true;
10353 static bool test_del_driver_unused_files(struct torture_context *tctx,
10354 struct dcerpc_pipe *p)
10356 struct torture_driver_context *d1;
10357 struct torture_driver_context *d2;
10358 uint32_t add_flags = APD_COPY_NEW_FILES;
10359 struct dcerpc_binding_handle *b = p->binding_handle;
10360 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
10362 d1 = talloc_zero(tctx, struct torture_driver_context);
10363 d1->ex = true;
10364 d1->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10365 d1->info8.driver_name = TORTURE_DRIVER_DELETER;
10366 d1->info8.architecture = NULL;
10367 d1->info8.driver_path = talloc_strdup(d1, "pscript5.dll");
10368 d1->info8.data_file = talloc_strdup(d1, "cups6.ppd");
10369 d1->info8.config_file = talloc_strdup(d1, "cupsui6.dll");
10370 d1->info8.help_file = talloc_strdup(d1, "pscript.hlp");
10371 d1->local.environment = talloc_strdup(d1, SPOOLSS_ARCHITECTURE_x64);
10372 d1->local.driver_directory = talloc_strdup(d1, "/usr/share/cups/drivers/x64");
10373 d1->info8.architecture = d1->local.environment;
10375 d2 = talloc_zero(tctx, struct torture_driver_context);
10376 d2->ex = true;
10377 d2->info8.version = SPOOLSS_DRIVER_VERSION_200X;
10378 d2->info8.driver_name = TORTURE_DRIVER_DELETERIN;
10379 d2->info8.architecture = NULL;
10380 d2->info8.driver_path = talloc_strdup(d2, "pscript5.dll"); /* overlapping */
10381 d2->info8.data_file = talloc_strdup(d2, "cupsps6.dll");
10382 d2->info8.config_file = talloc_strdup(d2, "cups6.ini");
10383 d2->info8.help_file = talloc_strdup(d2, "pscript.hlp"); /* overlapping */
10384 d2->local.environment = talloc_strdup(d2, SPOOLSS_ARCHITECTURE_x64);
10385 d2->local.driver_directory = talloc_strdup(d2, "/usr/share/cups/drivers/x64");
10386 d2->info8.architecture = d2->local.environment;
10388 torture_assert(tctx,
10389 fillup_printserver_info(tctx, p, d1),
10390 "failed to fillup printserver info");
10391 torture_assert(tctx,
10392 fillup_printserver_info(tctx, p, d2),
10393 "failed to fillup printserver info");
10395 if (!directory_exist(d1->local.driver_directory)) {
10396 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
10399 torture_assert(tctx,
10400 upload_printer_driver(tctx, dcerpc_server_name(p), d1),
10401 "failed to upload printer driver");
10402 torture_assert(tctx,
10403 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d1->info8, add_flags, true, NULL),
10404 "failed to add driver");
10406 torture_assert(tctx,
10407 upload_printer_driver(tctx, dcerpc_server_name(p), d2),
10408 "failed to upload printer driver");
10409 torture_assert(tctx,
10410 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d2->info8, add_flags, true, NULL),
10411 "failed to add driver");
10413 /* some files are in use by a separate driver, should fail */
10414 torture_assert(tctx,
10415 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10416 d1->info8.driver_name,
10417 d1->local.environment,
10418 DPD_DELETE_ALL_FILES,
10419 d1->info8.version,
10420 WERR_PRINTER_DRIVER_IN_USE),
10421 "invalid delete driver response");
10423 /* should only delete files not in use by other driver */
10424 torture_assert(tctx,
10425 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10426 d1->info8.driver_name,
10427 d1->local.environment,
10428 DPD_DELETE_UNUSED_FILES,
10429 d1->info8.version,
10430 WERR_OK),
10431 "failed to delete driver (unused files)");
10433 /* check non-overlapping were deleted */
10434 d1->info8.driver_path = NULL;
10435 d1->info8.help_file = NULL;
10436 torture_assert(tctx,
10437 check_printer_driver_files(tctx, dcerpc_server_name(p), d1, false),
10438 "printer driver file check failed");
10439 /* d2 files should be uneffected */
10440 torture_assert(tctx,
10441 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, true),
10442 "printer driver file check failed");
10444 torture_assert(tctx,
10445 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
10446 d2->info8.driver_name,
10447 d2->local.environment,
10448 DPD_DELETE_ALL_FILES,
10449 d2->info8.version,
10450 WERR_OK),
10451 "failed to delete driver");
10453 torture_assert(tctx,
10454 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, false),
10455 "printer driver file check failed");
10457 talloc_free(d1);
10458 talloc_free(d2);
10459 return true;
10462 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
10464 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
10466 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
10467 "driver", &ndr_table_spoolss);
10468 torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
10469 torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
10471 torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
10472 torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
10474 torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
10476 torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
10478 torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
10480 torture_rpc_tcase_add_test(tcase, "multiple_drivers", test_multiple_drivers);
10482 torture_rpc_tcase_add_test(tcase, "del_driver_all_files", test_del_driver_all_files);
10484 torture_rpc_tcase_add_test(tcase, "del_driver_unused_files", test_del_driver_unused_files);
10486 return suite;