s3-selftest: Remove some unnecessary comma
[Samba/gebeck_regimport.git] / source4 / torture / rpc / spoolss.c
blobdf800dc8af06474553781bd6327649871640b33f
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
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 "lib/cmdline/popt_common.h"
39 #include "system/filesys.h"
40 #include "torture/ndr/ndr.h"
42 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
43 #define TORTURE_PRINTER "torture_printer"
44 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
45 #define TORTURE_PRINTER_EX "torture_printer_ex"
46 #define TORTURE_DRIVER "torture_driver"
47 #define TORTURE_DRIVER_EX "torture_driver_ex"
48 #define TORTURE_DRIVER_ADOBE "torture_driver_adobe"
49 #define TORTURE_DRIVER_EX_ADOBE "torture_driver_ex_adobe"
50 #define TORTURE_DRIVER_ADOBE_CUPSADDSMB "torture_driver_adobe_cupsaddsmb"
51 #define TORTURE_DRIVER_TIMESTAMPS "torture_driver_timestamps"
52 #define TORTURE_DRIVER_DELETER "torture_driver_deleter"
53 #define TORTURE_DRIVER_DELETERIN "torture_driver_deleterin"
55 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
56 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
57 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
58 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
59 #define TOP_LEVEL_CONTROL_PRINTERS_KEY TOP_LEVEL_CONTROL_KEY "\\Printers"
60 #define TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY TOP_LEVEL_CONTROL_KEY "\\Environments"
62 struct test_spoolss_context {
63 struct dcerpc_pipe *spoolss_pipe;
65 /* server environment */
66 const char *environment;
68 /* print server handle */
69 struct policy_handle server_handle;
71 /* for EnumPorts */
72 uint32_t port_count[3];
73 union spoolss_PortInfo *ports[3];
75 /* for EnumPrinterDrivers */
76 uint32_t driver_count[8];
77 union spoolss_DriverInfo *drivers[8];
79 /* for EnumMonitors */
80 uint32_t monitor_count[3];
81 union spoolss_MonitorInfo *monitors[3];
83 /* for EnumPrintProcessors */
84 uint32_t print_processor_count[2];
85 union spoolss_PrintProcessorInfo *print_processors[2];
87 /* for EnumPrinters */
88 uint32_t printer_count[6];
89 union spoolss_PrinterInfo *printers[6];
92 struct torture_driver_context {
93 struct {
94 const char *driver_directory;
95 const char *environment;
96 } local;
97 struct {
98 const char *driver_directory;
99 const char *environment;
100 } remote;
101 struct spoolss_AddDriverInfo8 info8;
102 bool ex;
105 struct torture_printer_context {
106 struct dcerpc_pipe *spoolss_pipe;
107 struct spoolss_SetPrinterInfo2 info2;
108 struct torture_driver_context driver;
109 bool ex;
110 bool wellknown;
111 bool added_driver;
112 bool have_driver;
113 struct spoolss_DeviceMode *devmode;
114 struct policy_handle handle;
117 static bool upload_printer_driver(struct torture_context *tctx,
118 const char *server_name,
119 struct torture_driver_context *d);
120 static bool remove_printer_driver(struct torture_context *tctx,
121 const char *server_name,
122 struct torture_driver_context *d);
123 static bool fillup_printserver_info(struct torture_context *tctx,
124 struct dcerpc_pipe *p,
125 struct torture_driver_context *d);
126 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
127 struct dcerpc_binding_handle *b,
128 const char *server_name,
129 struct spoolss_AddDriverInfo8 *r,
130 uint32_t flags,
131 bool ex,
132 const char *remote_driver_dir);
134 #define COMPARE_STRING(tctx, c,r,e) \
135 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
137 /* not every compiler supports __typeof__() */
138 #if (__GNUC__ >= 3)
139 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
140 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
141 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
143 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
144 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
146 } while(0)
147 #else
148 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
149 #endif
151 #define COMPARE_UINT32(tctx, c, r, e) do {\
152 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
153 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
154 } while(0)
156 #define COMPARE_UINT64(tctx, c, r, e) do {\
157 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
158 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
159 } while(0)
162 #define COMPARE_NTTIME(tctx, c, r, e) do {\
163 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
164 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
165 } while(0)
167 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
168 int __i; \
169 if (!c.e && !r.e) { \
170 break; \
172 if (c.e && !r.e) { \
173 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
175 if (!c.e && r.e) { \
176 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
178 for (__i=0;c.e[__i] != NULL; __i++) { \
179 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
181 } while(0)
183 #define CHECK_ALIGN(size, n) do {\
184 if (size % n) {\
185 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
186 size, n, size + n - (size % n));\
188 } while(0)
190 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
192 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, needed, align) do { \
193 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
194 uint32_t size = ndr_size_##fn##_info(tctx, level, count, info);\
195 uint32_t round_size = DO_ROUND(size, align);\
196 if (round_size != needed) {\
197 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
198 CHECK_ALIGN(size, align);\
201 } while(0)
203 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, needed, align) do { \
204 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
205 uint32_t size = ndr_size_##fn##_info(tctx, count, info);\
206 uint32_t round_size = DO_ROUND(size, align);\
207 if (round_size != needed) {\
208 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
209 CHECK_ALIGN(size, align);\
212 } while(0)
214 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, needed, align) do { \
215 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
216 uint32_t size = ndr_size_##fn(info, level, 0);\
217 uint32_t round_size = DO_ROUND(size, align);\
218 if (round_size != needed) {\
219 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
220 CHECK_ALIGN(size, align);\
223 } while(0)
225 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context *tctx,
226 const union spoolss_PrinterInfo *i,
227 uint32_t level,
228 union spoolss_SetPrinterInfo *s)
230 switch (level) {
231 case 0:
232 s->info0 = talloc(tctx, struct spoolss_SetPrinterInfo0);
233 break;
234 case 2:
235 s->info2 = talloc(tctx, struct spoolss_SetPrinterInfo2);
236 s->info2->servername = i->info2.servername;
237 s->info2->printername = i->info2.printername;
238 s->info2->sharename = i->info2.sharename;
239 s->info2->portname = i->info2.portname;
240 s->info2->drivername = i->info2.drivername;
241 s->info2->comment = i->info2.comment;
242 s->info2->location = i->info2.location;
243 s->info2->devmode_ptr = 0;
244 s->info2->sepfile = i->info2.sepfile;
245 s->info2->printprocessor = i->info2.printprocessor;
246 s->info2->datatype = i->info2.datatype;
247 s->info2->parameters = i->info2.parameters;
248 s->info2->secdesc_ptr = 0;
249 s->info2->attributes = i->info2.attributes;
250 s->info2->priority = i->info2.priority;
251 s->info2->defaultpriority = i->info2.defaultpriority;
252 s->info2->starttime = i->info2.starttime;
253 s->info2->untiltime = i->info2.untiltime;
254 s->info2->status = i->info2.status;
255 s->info2->cjobs = i->info2.cjobs;
256 s->info2->averageppm = i->info2.averageppm;
257 break;
258 case 3:
259 case 4:
260 case 5:
261 case 6:
262 case 7:
263 case 8:
264 case 9:
265 default:
266 return false;
269 return true;
272 static bool test_OpenPrinter_server(struct torture_context *tctx,
273 struct dcerpc_pipe *p,
274 struct policy_handle *server_handle)
276 NTSTATUS status;
277 struct spoolss_OpenPrinter op;
278 struct dcerpc_binding_handle *b = p->binding_handle;
280 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
281 op.in.datatype = NULL;
282 op.in.devmode_ctr.devmode= NULL;
283 op.in.access_mask = 0;
284 op.out.handle = server_handle;
286 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
288 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
289 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
290 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
292 return true;
295 static bool test_EnumPorts(struct torture_context *tctx,
296 void *private_data)
298 struct test_spoolss_context *ctx =
299 talloc_get_type_abort(private_data, struct test_spoolss_context);
300 struct dcerpc_pipe *p = ctx->spoolss_pipe;
301 struct dcerpc_binding_handle *b = p->binding_handle;
302 NTSTATUS status;
303 struct spoolss_EnumPorts r;
304 uint16_t levels[] = { 1, 2 };
305 int i, j;
307 for (i=0;i<ARRAY_SIZE(levels);i++) {
308 int level = levels[i];
309 DATA_BLOB blob;
310 uint32_t needed;
311 uint32_t count;
312 union spoolss_PortInfo *info;
314 r.in.servername = "";
315 r.in.level = level;
316 r.in.buffer = NULL;
317 r.in.offered = 0;
318 r.out.needed = &needed;
319 r.out.count = &count;
320 r.out.info = &info;
322 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
324 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
325 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
326 if (W_ERROR_IS_OK(r.out.result)) {
327 /* TODO: do some more checks here */
328 continue;
330 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
331 "EnumPorts unexpected return code");
333 blob = data_blob_talloc_zero(ctx, needed);
334 r.in.buffer = &blob;
335 r.in.offered = needed;
337 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
338 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
340 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
342 torture_assert(tctx, info, "EnumPorts returned no info");
344 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, needed, 4);
346 ctx->port_count[level] = count;
347 ctx->ports[level] = info;
350 for (i=1;i<ARRAY_SIZE(levels);i++) {
351 int level = levels[i];
352 int old_level = levels[i-1];
353 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
354 "EnumPorts invalid value");
356 /* if the array sizes are not the same we would maybe segfault in the following code */
358 for (i=0;i<ARRAY_SIZE(levels);i++) {
359 int level = levels[i];
360 for (j=0;j<ctx->port_count[level];j++) {
361 union spoolss_PortInfo *cur = &ctx->ports[level][j];
362 union spoolss_PortInfo *ref = &ctx->ports[2][j];
363 switch (level) {
364 case 1:
365 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
366 break;
367 case 2:
368 /* level 2 is our reference, and it makes no sense to compare it to itself */
369 break;
374 return true;
377 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
378 void *private_data)
380 struct test_spoolss_context *ctx =
381 talloc_get_type_abort(private_data, struct test_spoolss_context);
383 NTSTATUS status;
384 struct dcerpc_pipe *p = ctx->spoolss_pipe;
385 struct dcerpc_binding_handle *b = p->binding_handle;
386 struct spoolss_GetPrintProcessorDirectory r;
387 struct {
388 uint16_t level;
389 const char *server;
390 } levels[] = {{
391 .level = 1,
392 .server = NULL
394 .level = 1,
395 .server = ""
397 .level = 78,
398 .server = ""
400 .level = 1,
401 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
403 .level = 1024,
404 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
407 int i;
408 uint32_t needed;
410 for (i=0;i<ARRAY_SIZE(levels);i++) {
411 int level = levels[i].level;
412 DATA_BLOB blob;
414 r.in.server = levels[i].server;
415 r.in.environment = ctx->environment;
416 r.in.level = level;
417 r.in.buffer = NULL;
418 r.in.offered = 0;
419 r.out.needed = &needed;
421 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
423 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
424 torture_assert_ntstatus_ok(tctx, status,
425 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
426 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
427 "GetPrintProcessorDirectory unexpected return code");
429 blob = data_blob_talloc_zero(tctx, needed);
430 r.in.buffer = &blob;
431 r.in.offered = needed;
433 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
434 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
436 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
438 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, needed, 2);
441 return true;
445 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
446 void *private_data)
448 struct test_spoolss_context *ctx =
449 talloc_get_type_abort(private_data, struct test_spoolss_context);
451 NTSTATUS status;
452 struct dcerpc_pipe *p = ctx->spoolss_pipe;
453 struct dcerpc_binding_handle *b = p->binding_handle;
454 struct spoolss_GetPrinterDriverDirectory r;
455 struct {
456 uint16_t level;
457 const char *server;
458 } levels[] = {{
459 .level = 1,
460 .server = NULL
462 .level = 1,
463 .server = ""
465 .level = 78,
466 .server = ""
468 .level = 1,
469 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
471 .level = 1024,
472 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
475 int i;
476 uint32_t needed;
478 for (i=0;i<ARRAY_SIZE(levels);i++) {
479 int level = levels[i].level;
480 DATA_BLOB blob;
482 r.in.server = levels[i].server;
483 r.in.environment = ctx->environment;
484 r.in.level = level;
485 r.in.buffer = NULL;
486 r.in.offered = 0;
487 r.out.needed = &needed;
489 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
491 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
492 torture_assert_ntstatus_ok(tctx, status,
493 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
494 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
495 "GetPrinterDriverDirectory unexpected return code");
497 blob = data_blob_talloc_zero(tctx, needed);
498 r.in.buffer = &blob;
499 r.in.offered = needed;
501 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
502 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
504 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
506 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, needed, 2);
509 return true;
512 static bool test_EnumPrinterDrivers_args(struct torture_context *tctx,
513 struct dcerpc_binding_handle *b,
514 const char *server_name,
515 const char *environment,
516 uint32_t level,
517 uint32_t *count_p,
518 union spoolss_DriverInfo **info_p)
520 struct spoolss_EnumPrinterDrivers r;
521 uint32_t needed;
522 uint32_t count;
523 union spoolss_DriverInfo *info;
525 r.in.server = server_name;
526 r.in.environment = environment;
527 r.in.level = level;
528 r.in.buffer = NULL;
529 r.in.offered = 0;
530 r.out.needed = &needed;
531 r.out.count = &count;
532 r.out.info = &info;
534 torture_comment(tctx, "Testing EnumPrinterDrivers(%s) level %u\n",
535 r.in.environment, r.in.level);
537 torture_assert_ntstatus_ok(tctx,
538 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
539 "EnumPrinterDrivers failed");
540 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
541 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
542 r.in.buffer = &blob;
543 r.in.offered = needed;
545 torture_assert_ntstatus_ok(tctx,
546 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
547 "EnumPrinterDrivers failed");
550 torture_assert_werr_ok(tctx, r.out.result,
551 "EnumPrinterDrivers failed");
553 if (count_p) {
554 *count_p = count;
556 if (info_p) {
557 *info_p = info;
560 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, needed, 4);
562 return true;
566 static bool test_EnumPrinterDrivers_findone(struct torture_context *tctx,
567 struct dcerpc_binding_handle *b,
568 const char *server_name,
569 const char *environment,
570 uint32_t level,
571 const char *driver_name,
572 union spoolss_DriverInfo *info_p)
574 uint32_t count;
575 union spoolss_DriverInfo *info;
576 int i;
577 const char *environment_ret = NULL;
579 torture_assert(tctx,
580 test_EnumPrinterDrivers_args(tctx, b, server_name, environment, level, &count, &info),
581 "failed to enumerate printer drivers");
583 for (i=0; i < count; i++) {
584 const char *driver_name_ret;
585 switch (level) {
586 case 1:
587 driver_name_ret = info[i].info1.driver_name;
588 break;
589 case 2:
590 driver_name_ret = info[i].info2.driver_name;
591 environment_ret = info[i].info2.architecture;
592 break;
593 case 3:
594 driver_name_ret = info[i].info3.driver_name;
595 environment_ret = info[i].info3.architecture;
596 break;
597 case 4:
598 driver_name_ret = info[i].info4.driver_name;
599 environment_ret = info[i].info4.architecture;
600 break;
601 case 5:
602 driver_name_ret = info[i].info5.driver_name;
603 environment_ret = info[i].info5.architecture;
604 break;
605 case 6:
606 driver_name_ret = info[i].info6.driver_name;
607 environment_ret = info[i].info6.architecture;
608 break;
609 case 7:
610 driver_name_ret = info[i].info7.driver_name;
611 break;
612 case 8:
613 driver_name_ret = info[i].info8.driver_name;
614 environment_ret = info[i].info8.architecture;
615 break;
616 default:
617 break;
619 if (environment_ret) {
620 torture_assert_str_equal(tctx, environment, environment_ret, "architecture mismatch");
622 if (strequal(driver_name, driver_name_ret)) {
623 if (info_p) {
624 *info_p = info[i];
626 return true;
630 return false;
633 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
634 void *private_data)
636 struct test_spoolss_context *ctx =
637 talloc_get_type_abort(private_data, struct test_spoolss_context);
638 struct dcerpc_pipe *p = ctx->spoolss_pipe;
639 struct dcerpc_binding_handle *b = p->binding_handle;
640 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
641 int i, j, a;
643 /* FIXME: gd, come back and fix "" as server, and handle
644 * priority of returned error codes in torture test and samba 3
645 * server */
646 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
647 const char *environments[2];
649 environments[0] = SPOOLSS_ARCHITECTURE_ALL;
650 environments[1] = ctx->environment;
652 for (a=0;a<ARRAY_SIZE(environments);a++) {
654 for (i=0;i<ARRAY_SIZE(levels);i++) {
655 int level = levels[i];
656 uint32_t count;
657 union spoolss_DriverInfo *info;
659 torture_assert(tctx,
660 test_EnumPrinterDrivers_args(tctx, b, server_name, environments[a], level, &count, &info),
661 "failed to enumerate drivers");
663 ctx->driver_count[level] = count;
664 ctx->drivers[level] = info;
667 for (i=1;i<ARRAY_SIZE(levels);i++) {
668 int level = levels[i];
669 int old_level = levels[i-1];
671 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
672 "EnumPrinterDrivers invalid value");
675 for (i=0;i<ARRAY_SIZE(levels);i++) {
676 int level = levels[i];
678 for (j=0;j<ctx->driver_count[level];j++) {
679 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
680 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
682 switch (level) {
683 case 1:
684 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
685 break;
686 case 2:
687 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
688 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
689 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
690 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
691 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
692 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
693 break;
694 case 3:
695 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
696 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
697 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
698 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
699 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
700 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
701 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
702 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
703 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
704 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
705 break;
706 case 4:
707 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
708 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
709 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
710 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
711 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
712 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
713 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
714 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
715 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
716 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
717 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
718 break;
719 case 5:
720 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
721 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
722 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
723 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
724 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
725 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
726 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
727 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
728 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
729 break;
730 case 6:
731 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
732 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
733 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
734 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
735 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
736 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
737 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
738 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
739 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
740 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
741 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
742 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
743 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
744 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
745 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
746 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
747 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
748 break;
749 case 8:
750 /* level 8 is our reference, and it makes no sense to compare it to itself */
751 break;
757 return true;
760 static bool test_EnumMonitors(struct torture_context *tctx,
761 void *private_data)
763 struct test_spoolss_context *ctx =
764 talloc_get_type_abort(private_data, struct test_spoolss_context);
765 struct dcerpc_pipe *p = ctx->spoolss_pipe;
766 struct dcerpc_binding_handle *b = p->binding_handle;
767 NTSTATUS status;
768 struct spoolss_EnumMonitors r;
769 uint16_t levels[] = { 1, 2 };
770 int i, j;
772 for (i=0;i<ARRAY_SIZE(levels);i++) {
773 int level = levels[i];
774 DATA_BLOB blob;
775 uint32_t needed;
776 uint32_t count;
777 union spoolss_MonitorInfo *info;
779 r.in.servername = "";
780 r.in.level = level;
781 r.in.buffer = NULL;
782 r.in.offered = 0;
783 r.out.needed = &needed;
784 r.out.count = &count;
785 r.out.info = &info;
787 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
789 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
790 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
791 if (W_ERROR_IS_OK(r.out.result)) {
792 /* TODO: do some more checks here */
793 continue;
795 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
796 "EnumMonitors failed");
798 blob = data_blob_talloc_zero(ctx, needed);
799 r.in.buffer = &blob;
800 r.in.offered = needed;
802 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
803 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
805 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
807 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, needed, 4);
809 ctx->monitor_count[level] = count;
810 ctx->monitors[level] = info;
813 for (i=1;i<ARRAY_SIZE(levels);i++) {
814 int level = levels[i];
815 int old_level = levels[i-1];
816 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
817 "EnumMonitors invalid value");
820 for (i=0;i<ARRAY_SIZE(levels);i++) {
821 int level = levels[i];
822 for (j=0;j<ctx->monitor_count[level];j++) {
823 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
824 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
825 switch (level) {
826 case 1:
827 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
828 break;
829 case 2:
830 /* level 2 is our reference, and it makes no sense to compare it to itself */
831 break;
836 return true;
839 static bool test_EnumPrintProcessors_level(struct torture_context *tctx,
840 struct dcerpc_binding_handle *b,
841 const char *environment,
842 uint32_t level,
843 uint32_t *count_p,
844 union spoolss_PrintProcessorInfo **info_p,
845 WERROR expected_result)
847 struct spoolss_EnumPrintProcessors r;
848 DATA_BLOB blob;
849 uint32_t needed;
850 uint32_t count;
851 union spoolss_PrintProcessorInfo *info;
853 r.in.servername = "";
854 r.in.environment = environment;
855 r.in.level = level;
856 r.in.buffer = NULL;
857 r.in.offered = 0;
858 r.out.needed = &needed;
859 r.out.count = &count;
860 r.out.info = &info;
862 torture_comment(tctx, "Testing EnumPrintProcessors(%s) level %u\n",
863 r.in.environment, r.in.level);
865 torture_assert_ntstatus_ok(tctx,
866 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
867 "EnumPrintProcessors failed");
868 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
869 blob = data_blob_talloc_zero(tctx, needed);
870 r.in.buffer = &blob;
871 r.in.offered = needed;
872 torture_assert_ntstatus_ok(tctx,
873 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
874 "EnumPrintProcessors failed");
876 torture_assert_werr_equal(tctx, r.out.result, expected_result,
877 "EnumPrintProcessors failed");
879 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, level, count, needed, 4);
881 if (count_p) {
882 *count_p = count;
884 if (info_p) {
885 *info_p = info;
888 return true;
891 static bool test_EnumPrintProcessors(struct torture_context *tctx,
892 void *private_data)
894 struct test_spoolss_context *ctx =
895 talloc_get_type_abort(private_data, struct test_spoolss_context);
897 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
898 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
899 int i;
900 struct dcerpc_pipe *p = ctx->spoolss_pipe;
901 struct dcerpc_binding_handle *b = p->binding_handle;
903 torture_assert(tctx,
904 test_EnumPrintProcessors_level(tctx, b, "phantasy", 1, NULL, NULL, WERR_INVALID_ENVIRONMENT),
905 "test_EnumPrintProcessors_level failed");
907 for (i=0;i<ARRAY_SIZE(levels);i++) {
908 union spoolss_PrintProcessorInfo *info;
909 uint32_t count;
910 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
912 torture_assert(tctx,
913 test_EnumPrintProcessors_level(tctx, b, ctx->environment, levels[i], &count, &info, expected_result),
914 "test_EnumPrintProcessors_level failed");
917 return true;
920 static bool test_EnumPrintProcDataTypes_level(struct torture_context *tctx,
921 struct dcerpc_binding_handle *b,
922 const char *print_processor_name,
923 uint32_t level,
924 uint32_t *count_p,
925 union spoolss_PrintProcDataTypesInfo **info_p,
926 WERROR expected_result)
928 struct spoolss_EnumPrintProcDataTypes r;
929 DATA_BLOB blob;
930 uint32_t needed;
931 uint32_t count;
932 union spoolss_PrintProcDataTypesInfo *info;
934 r.in.servername = "";
935 r.in.print_processor_name = print_processor_name;
936 r.in.level = level;
937 r.in.buffer = NULL;
938 r.in.offered = 0;
939 r.out.needed = &needed;
940 r.out.count = &count;
941 r.out.info = &info;
943 torture_comment(tctx, "Testing EnumPrintProcDataTypes(%s) level %u\n",
944 r.in.print_processor_name, r.in.level);
946 torture_assert_ntstatus_ok(tctx,
947 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
948 "EnumPrintProcDataTypes failed");
949 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
950 blob = data_blob_talloc_zero(tctx, needed);
951 r.in.buffer = &blob;
952 r.in.offered = needed;
953 torture_assert_ntstatus_ok(tctx,
954 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
955 "EnumPrintProcDataTypes failed");
957 torture_assert_werr_equal(tctx, r.out.result, expected_result,
958 "EnumPrintProcDataTypes failed");
960 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, level, count, needed, 4);
962 if (count_p) {
963 *count_p = count;
965 if (info_p) {
966 *info_p = info;
969 return true;
972 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
973 void *private_data)
975 struct test_spoolss_context *ctx =
976 talloc_get_type_abort(private_data, struct test_spoolss_context);
978 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
979 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
980 int i;
981 struct dcerpc_pipe *p = ctx->spoolss_pipe;
982 struct dcerpc_binding_handle *b = p->binding_handle;
984 torture_assert(tctx,
985 test_EnumPrintProcDataTypes_level(tctx, b, NULL, 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
986 "test_EnumPrintProcDataTypes_level failed");
988 torture_assert(tctx,
989 test_EnumPrintProcDataTypes_level(tctx, b, "nonexisting", 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
990 "test_EnumPrintProcDataTypes_level failed");
992 for (i=0;i<ARRAY_SIZE(levels);i++) {
993 int level = levels[i];
994 uint32_t count;
995 union spoolss_PrintProcDataTypesInfo *info;
996 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
998 torture_assert(tctx,
999 test_EnumPrintProcDataTypes_level(tctx, b, "winprint", level, &count, &info, expected_result),
1000 "test_EnumPrintProcDataTypes_level failed");
1004 union spoolss_PrintProcessorInfo *info;
1005 uint32_t count;
1007 torture_assert(tctx,
1008 test_EnumPrintProcessors_level(tctx, b, ctx->environment, 1, &count, &info, WERR_OK),
1009 "test_EnumPrintProcessors_level failed");
1011 for (i=0; i < count; i++) {
1012 torture_assert(tctx,
1013 test_EnumPrintProcDataTypes_level(tctx, b, info[i].info1.print_processor_name, 1, NULL, NULL, WERR_OK),
1014 "test_EnumPrintProcDataTypes_level failed");
1019 return true;
1022 static bool test_EnumPrinters(struct torture_context *tctx,
1023 void *private_data)
1025 struct test_spoolss_context *ctx =
1026 talloc_get_type_abort(private_data, struct test_spoolss_context);
1027 struct dcerpc_pipe *p = ctx->spoolss_pipe;
1028 struct dcerpc_binding_handle *b = p->binding_handle;
1029 struct spoolss_EnumPrinters r;
1030 NTSTATUS status;
1031 uint16_t levels[] = { 0, 1, 2, 4, 5 };
1032 int i, j;
1034 for (i=0;i<ARRAY_SIZE(levels);i++) {
1035 int level = levels[i];
1036 DATA_BLOB blob;
1037 uint32_t needed;
1038 uint32_t count;
1039 union spoolss_PrinterInfo *info;
1041 r.in.flags = PRINTER_ENUM_LOCAL;
1042 r.in.server = "";
1043 r.in.level = level;
1044 r.in.buffer = NULL;
1045 r.in.offered = 0;
1046 r.out.needed = &needed;
1047 r.out.count = &count;
1048 r.out.info = &info;
1050 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1052 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1053 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1054 if (W_ERROR_IS_OK(r.out.result)) {
1055 /* TODO: do some more checks here */
1056 continue;
1058 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
1059 "EnumPrinters unexpected return code");
1061 blob = data_blob_talloc_zero(ctx, needed);
1062 r.in.buffer = &blob;
1063 r.in.offered = needed;
1065 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1066 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1068 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1070 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
1072 ctx->printer_count[level] = count;
1073 ctx->printers[level] = info;
1076 for (i=1;i<ARRAY_SIZE(levels);i++) {
1077 int level = levels[i];
1078 int old_level = levels[i-1];
1079 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
1080 "EnumPrinters invalid value");
1083 for (i=0;i<ARRAY_SIZE(levels);i++) {
1084 int level = levels[i];
1085 for (j=0;j<ctx->printer_count[level];j++) {
1086 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
1087 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
1088 switch (level) {
1089 case 0:
1090 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
1091 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
1092 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
1093 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
1094 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
1095 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
1096 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
1097 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
1098 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
1099 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
1100 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
1101 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
1102 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
1103 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
1104 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
1105 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
1106 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
1107 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
1108 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
1109 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
1110 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
1111 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
1112 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
1113 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
1114 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
1115 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
1116 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
1117 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
1118 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
1119 break;
1120 case 1:
1121 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
1122 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
1123 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
1124 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
1125 break;
1126 case 2:
1127 /* level 2 is our reference, and it makes no sense to compare it to itself */
1128 break;
1129 case 4:
1130 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
1131 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
1132 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
1133 break;
1134 case 5:
1135 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
1136 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
1137 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
1138 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
1139 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
1140 break;
1145 /* TODO:
1146 * - verify that the port of a printer was in the list returned by EnumPorts
1149 return true;
1152 static bool test_GetPrinterDriver2(struct torture_context *tctx,
1153 struct dcerpc_binding_handle *b,
1154 struct policy_handle *handle,
1155 const char *driver_name,
1156 const char *environment);
1158 bool test_GetPrinter_level(struct torture_context *tctx,
1159 struct dcerpc_binding_handle *b,
1160 struct policy_handle *handle,
1161 uint32_t level,
1162 union spoolss_PrinterInfo *info)
1164 struct spoolss_GetPrinter r;
1165 uint32_t needed;
1167 r.in.handle = handle;
1168 r.in.level = level;
1169 r.in.buffer = NULL;
1170 r.in.offered = 0;
1171 r.out.needed = &needed;
1173 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
1175 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1176 "GetPrinter failed");
1178 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1179 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
1180 r.in.buffer = &blob;
1181 r.in.offered = needed;
1183 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1184 "GetPrinter failed");
1187 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
1189 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, needed, 4);
1191 if (info && r.out.info) {
1192 *info = *r.out.info;
1195 return true;
1199 static bool test_GetPrinter(struct torture_context *tctx,
1200 struct dcerpc_binding_handle *b,
1201 struct policy_handle *handle,
1202 const char *environment)
1204 uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1205 int i;
1207 for (i=0;i<ARRAY_SIZE(levels);i++) {
1209 union spoolss_PrinterInfo info;
1211 ZERO_STRUCT(info);
1213 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
1214 "failed to call GetPrinter");
1216 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
1217 torture_assert(tctx,
1218 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
1219 "failed to call test_GetPrinterDriver2");
1223 return true;
1226 static bool test_SetPrinter(struct torture_context *tctx,
1227 struct dcerpc_binding_handle *b,
1228 struct policy_handle *handle,
1229 struct spoolss_SetPrinterInfoCtr *info_ctr,
1230 struct spoolss_DevmodeContainer *devmode_ctr,
1231 struct sec_desc_buf *secdesc_ctr,
1232 enum spoolss_PrinterControl command)
1234 struct spoolss_SetPrinter r;
1236 r.in.handle = handle;
1237 r.in.info_ctr = info_ctr;
1238 r.in.devmode_ctr = devmode_ctr;
1239 r.in.secdesc_ctr = secdesc_ctr;
1240 r.in.command = command;
1242 torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1244 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1245 "failed to call SetPrinter");
1246 torture_assert_werr_ok(tctx, r.out.result,
1247 "failed to call SetPrinter");
1249 return true;
1252 static bool test_SetPrinter_errors(struct torture_context *tctx,
1253 struct dcerpc_binding_handle *b,
1254 struct policy_handle *handle)
1256 struct spoolss_SetPrinter r;
1257 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1258 int i;
1260 struct spoolss_SetPrinterInfoCtr info_ctr;
1261 struct spoolss_DevmodeContainer devmode_ctr;
1262 struct sec_desc_buf secdesc_ctr;
1264 info_ctr.level = 0;
1265 info_ctr.info.info0 = NULL;
1267 ZERO_STRUCT(devmode_ctr);
1268 ZERO_STRUCT(secdesc_ctr);
1270 r.in.handle = handle;
1271 r.in.info_ctr = &info_ctr;
1272 r.in.devmode_ctr = &devmode_ctr;
1273 r.in.secdesc_ctr = &secdesc_ctr;
1274 r.in.command = 0;
1276 torture_comment(tctx, "Testing SetPrinter all zero\n");
1278 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1279 "failed to call SetPrinter");
1280 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1281 "failed to call SetPrinter");
1283 again:
1284 for (i=0; i < ARRAY_SIZE(levels); i++) {
1286 struct spoolss_SetPrinterInfo0 info0;
1287 struct spoolss_SetPrinterInfo1 info1;
1288 struct spoolss_SetPrinterInfo2 info2;
1289 struct spoolss_SetPrinterInfo3 info3;
1290 struct spoolss_SetPrinterInfo4 info4;
1291 struct spoolss_SetPrinterInfo5 info5;
1292 struct spoolss_SetPrinterInfo6 info6;
1293 struct spoolss_SetPrinterInfo7 info7;
1294 struct spoolss_SetPrinterInfo8 info8;
1295 struct spoolss_SetPrinterInfo9 info9;
1298 info_ctr.level = levels[i];
1299 switch (levels[i]) {
1300 case 0:
1301 ZERO_STRUCT(info0);
1302 info_ctr.info.info0 = &info0;
1303 break;
1304 case 1:
1305 ZERO_STRUCT(info1);
1306 info_ctr.info.info1 = &info1;
1307 break;
1308 case 2:
1309 ZERO_STRUCT(info2);
1310 info_ctr.info.info2 = &info2;
1311 break;
1312 case 3:
1313 ZERO_STRUCT(info3);
1314 info_ctr.info.info3 = &info3;
1315 break;
1316 case 4:
1317 ZERO_STRUCT(info4);
1318 info_ctr.info.info4 = &info4;
1319 break;
1320 case 5:
1321 ZERO_STRUCT(info5);
1322 info_ctr.info.info5 = &info5;
1323 break;
1324 case 6:
1325 ZERO_STRUCT(info6);
1326 info_ctr.info.info6 = &info6;
1327 break;
1328 case 7:
1329 ZERO_STRUCT(info7);
1330 info_ctr.info.info7 = &info7;
1331 break;
1332 case 8:
1333 ZERO_STRUCT(info8);
1334 info_ctr.info.info8 = &info8;
1335 break;
1336 case 9:
1337 ZERO_STRUCT(info9);
1338 info_ctr.info.info9 = &info9;
1339 break;
1342 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1343 info_ctr.level, r.in.command);
1345 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1346 "failed to call SetPrinter");
1348 switch (r.in.command) {
1349 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1350 /* is ignored for all levels other then 0 */
1351 if (info_ctr.level > 0) {
1352 /* ignored then */
1353 break;
1355 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1356 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1357 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1358 if (info_ctr.level > 0) {
1359 /* is invalid for all levels other then 0 */
1360 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1361 "unexpected error code returned");
1362 continue;
1363 } else {
1364 torture_assert_werr_ok(tctx, r.out.result,
1365 "failed to call SetPrinter with non 0 command");
1366 continue;
1368 break;
1370 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1371 /* FIXME: gd needs further investigation */
1372 default:
1373 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1374 "unexpected error code returned");
1375 continue;
1378 switch (info_ctr.level) {
1379 case 1:
1380 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1381 "unexpected error code returned");
1382 break;
1383 case 2:
1384 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1385 "unexpected error code returned");
1386 break;
1387 case 3:
1388 case 4:
1389 case 5:
1390 case 7:
1391 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1392 "unexpected error code returned");
1393 break;
1394 case 9:
1395 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1396 "unexpected error code returned");
1397 break;
1398 default:
1399 torture_assert_werr_ok(tctx, r.out.result,
1400 "failed to call SetPrinter");
1401 break;
1405 if (r.in.command < 5) {
1406 r.in.command++;
1407 goto again;
1410 return true;
1413 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1415 if ((r->level == 2) && (r->info.info2)) {
1416 r->info.info2->secdesc_ptr = 0;
1417 r->info.info2->devmode_ptr = 0;
1421 static bool test_PrinterInfo(struct torture_context *tctx,
1422 struct dcerpc_binding_handle *b,
1423 struct policy_handle *handle)
1425 NTSTATUS status;
1426 struct spoolss_SetPrinter s;
1427 struct spoolss_GetPrinter q;
1428 struct spoolss_GetPrinter q0;
1429 struct spoolss_SetPrinterInfoCtr info_ctr;
1430 union spoolss_PrinterInfo info;
1431 struct spoolss_DevmodeContainer devmode_ctr;
1432 struct sec_desc_buf secdesc_ctr;
1433 uint32_t needed;
1434 bool ret = true;
1435 int i;
1437 torture_skip(tctx, "Printer Info test is currently broken, skipping");
1439 uint32_t status_list[] = {
1440 /* these do not stick
1441 PRINTER_STATUS_PAUSED,
1442 PRINTER_STATUS_ERROR,
1443 PRINTER_STATUS_PENDING_DELETION, */
1444 PRINTER_STATUS_PAPER_JAM,
1445 PRINTER_STATUS_PAPER_OUT,
1446 PRINTER_STATUS_MANUAL_FEED,
1447 PRINTER_STATUS_PAPER_PROBLEM,
1448 PRINTER_STATUS_OFFLINE,
1449 PRINTER_STATUS_IO_ACTIVE,
1450 PRINTER_STATUS_BUSY,
1451 PRINTER_STATUS_PRINTING,
1452 PRINTER_STATUS_OUTPUT_BIN_FULL,
1453 PRINTER_STATUS_NOT_AVAILABLE,
1454 PRINTER_STATUS_WAITING,
1455 PRINTER_STATUS_PROCESSING,
1456 PRINTER_STATUS_INITIALIZING,
1457 PRINTER_STATUS_WARMING_UP,
1458 PRINTER_STATUS_TONER_LOW,
1459 PRINTER_STATUS_NO_TONER,
1460 PRINTER_STATUS_PAGE_PUNT,
1461 PRINTER_STATUS_USER_INTERVENTION,
1462 PRINTER_STATUS_OUT_OF_MEMORY,
1463 PRINTER_STATUS_DOOR_OPEN,
1464 PRINTER_STATUS_SERVER_UNKNOWN,
1465 PRINTER_STATUS_POWER_SAVE,
1466 /* these do not stick
1467 0x02000000,
1468 0x04000000,
1469 0x08000000,
1470 0x10000000,
1471 0x20000000,
1472 0x40000000,
1473 0x80000000 */
1475 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1476 uint32_t attribute_list[] = {
1477 PRINTER_ATTRIBUTE_QUEUED,
1478 /* fails with WERR_INVALID_DATATYPE:
1479 PRINTER_ATTRIBUTE_DIRECT, */
1480 /* does not stick
1481 PRINTER_ATTRIBUTE_DEFAULT, */
1482 PRINTER_ATTRIBUTE_SHARED,
1483 /* does not stick
1484 PRINTER_ATTRIBUTE_NETWORK, */
1485 PRINTER_ATTRIBUTE_HIDDEN,
1486 PRINTER_ATTRIBUTE_LOCAL,
1487 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1488 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1489 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1490 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1491 /* does not stick
1492 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1493 /* fails with WERR_INVALID_DATATYPE:
1494 PRINTER_ATTRIBUTE_RAW_ONLY, */
1495 /* these do not stick
1496 PRINTER_ATTRIBUTE_PUBLISHED,
1497 PRINTER_ATTRIBUTE_FAX,
1498 PRINTER_ATTRIBUTE_TS,
1499 0x00010000,
1500 0x00020000,
1501 0x00040000,
1502 0x00080000,
1503 0x00100000,
1504 0x00200000,
1505 0x00400000,
1506 0x00800000,
1507 0x01000000,
1508 0x02000000,
1509 0x04000000,
1510 0x08000000,
1511 0x10000000,
1512 0x20000000,
1513 0x40000000,
1514 0x80000000 */
1517 ZERO_STRUCT(devmode_ctr);
1518 ZERO_STRUCT(secdesc_ctr);
1520 s.in.handle = handle;
1521 s.in.command = 0;
1522 s.in.info_ctr = &info_ctr;
1523 s.in.devmode_ctr = &devmode_ctr;
1524 s.in.secdesc_ctr = &secdesc_ctr;
1526 q.in.handle = handle;
1527 q.out.info = &info;
1528 q0 = q;
1530 #define TESTGETCALL(call, r) \
1531 r.in.buffer = NULL; \
1532 r.in.offered = 0;\
1533 r.out.needed = &needed; \
1534 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1535 if (!NT_STATUS_IS_OK(status)) { \
1536 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1537 r.in.level, nt_errstr(status), __location__); \
1538 ret = false; \
1539 break; \
1541 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1542 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1543 r.in.buffer = &blob; \
1544 r.in.offered = needed; \
1546 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1547 if (!NT_STATUS_IS_OK(status)) { \
1548 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1549 r.in.level, nt_errstr(status), __location__); \
1550 ret = false; \
1551 break; \
1553 if (!W_ERROR_IS_OK(r.out.result)) { \
1554 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1555 r.in.level, win_errstr(r.out.result), __location__); \
1556 ret = false; \
1557 break; \
1561 #define TESTSETCALL_EXP(call, r, err) \
1562 clear_info2(&info_ctr);\
1563 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1564 if (!NT_STATUS_IS_OK(status)) { \
1565 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1566 r.in.info_ctr->level, nt_errstr(status), __location__); \
1567 ret = false; \
1568 break; \
1570 if (!W_ERROR_IS_OK(err)) { \
1571 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1572 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1573 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1574 ret = false; \
1576 break; \
1578 if (!W_ERROR_IS_OK(r.out.result)) { \
1579 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1580 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1581 ret = false; \
1582 break; \
1585 #define TESTSETCALL(call, r) \
1586 TESTSETCALL_EXP(call, r, WERR_OK)
1588 #define STRING_EQUAL(s1, s2, field) \
1589 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1590 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1591 #field, s2, __location__); \
1592 ret = false; \
1593 break; \
1596 #define MEM_EQUAL(s1, s2, length, field) \
1597 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1598 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1599 #field, (const char *)s2, __location__); \
1600 ret = false; \
1601 break; \
1604 #define INT_EQUAL(i1, i2, field) \
1605 if (i1 != i2) { \
1606 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1607 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1608 ret = false; \
1609 break; \
1612 #define SD_EQUAL(sd1, sd2, field) \
1613 if (!security_descriptor_equal(sd1, sd2)) { \
1614 torture_comment(tctx, "Failed to set %s (%s)\n", \
1615 #field, __location__); \
1616 ret = false; \
1617 break; \
1620 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1621 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1622 q.in.level = lvl1; \
1623 TESTGETCALL(GetPrinter, q) \
1624 info_ctr.level = lvl1; \
1625 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1626 info_ctr.info.info ## lvl1->field1 = value;\
1627 TESTSETCALL_EXP(SetPrinter, s, err) \
1628 info_ctr.info.info ## lvl1->field1 = ""; \
1629 TESTGETCALL(GetPrinter, q) \
1630 info_ctr.info.info ## lvl1->field1 = value; \
1631 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1632 q.in.level = lvl2; \
1633 TESTGETCALL(GetPrinter, q) \
1634 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1635 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1636 } while (0)
1638 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1639 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1640 } while (0);
1642 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1643 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1644 q.in.level = lvl1; \
1645 TESTGETCALL(GetPrinter, q) \
1646 info_ctr.level = lvl1; \
1647 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1648 info_ctr.info.info ## lvl1->field1 = value; \
1649 TESTSETCALL(SetPrinter, s) \
1650 info_ctr.info.info ## lvl1->field1 = 0; \
1651 TESTGETCALL(GetPrinter, q) \
1652 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1653 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1654 q.in.level = lvl2; \
1655 TESTGETCALL(GetPrinter, q) \
1656 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1657 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1658 } while (0)
1660 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1661 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1662 } while (0)
1664 q0.in.level = 0;
1665 do { TESTGETCALL(GetPrinter, q0) } while (0);
1667 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1668 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1670 /* level 0 printername does not stick */
1671 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1672 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1673 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1674 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1675 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1676 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1677 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1678 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1679 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1680 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1681 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1682 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1683 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1684 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1685 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1687 /* servername can be set but does not stick
1688 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1689 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1690 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1693 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1694 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1695 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1696 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1697 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1699 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1700 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1701 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1702 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1703 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1704 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1705 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1706 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1707 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1708 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1710 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1711 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1712 attribute_list[i],
1713 (attribute_list[i] | default_attribute)
1714 ); */
1715 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1716 attribute_list[i],
1717 (attribute_list[i] | default_attribute)
1719 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1720 attribute_list[i],
1721 (attribute_list[i] | default_attribute)
1723 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1724 attribute_list[i],
1725 (attribute_list[i] | default_attribute)
1727 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1728 attribute_list[i],
1729 (attribute_list[i] | default_attribute)
1730 ); */
1731 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1732 attribute_list[i],
1733 (attribute_list[i] | default_attribute)
1735 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1736 attribute_list[i],
1737 (attribute_list[i] | default_attribute)
1739 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1740 attribute_list[i],
1741 (attribute_list[i] | default_attribute)
1743 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1744 attribute_list[i],
1745 (attribute_list[i] | default_attribute)
1746 ); */
1747 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1748 attribute_list[i],
1749 (attribute_list[i] | default_attribute)
1751 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1752 attribute_list[i],
1753 (attribute_list[i] | default_attribute)
1755 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1756 attribute_list[i],
1757 (attribute_list[i] | default_attribute)
1761 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1762 /* level 2 sets do not stick
1763 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1764 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1765 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1766 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1767 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1768 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1771 /* priorities need to be between 0 and 99
1772 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1773 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1774 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1775 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1776 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1777 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1778 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1779 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1780 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1782 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1783 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1785 /* does not stick
1786 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1787 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1789 /* does not stick
1790 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1791 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1793 /* FIXME: gd also test devmode and secdesc behavior */
1796 /* verify composition of level 1 description field */
1797 const char *description;
1798 const char *tmp;
1800 q0.in.level = 1;
1801 do { TESTGETCALL(GetPrinter, q0) } while (0);
1803 description = talloc_strdup(tctx, q0.out.info->info1.description);
1805 q0.in.level = 2;
1806 do { TESTGETCALL(GetPrinter, q0) } while (0);
1808 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1809 q0.out.info->info2.printername,
1810 q0.out.info->info2.drivername,
1811 q0.out.info->info2.location);
1813 do { STRING_EQUAL(description, tmp, "description")} while (0);
1816 return ret;
1819 static bool test_security_descriptor_equal(struct torture_context *tctx,
1820 const struct security_descriptor *sd1,
1821 const struct security_descriptor *sd2)
1823 if (sd1 == sd2) {
1824 return true;
1827 if (!sd1 || !sd2) {
1828 torture_comment(tctx, "%s\n", __location__);
1829 return false;
1832 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1833 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1835 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1836 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1838 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1839 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1840 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1841 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1842 return false;
1844 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1845 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1846 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1847 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1848 return false;
1851 return true;
1854 static bool test_sd_set_level(struct torture_context *tctx,
1855 struct dcerpc_binding_handle *b,
1856 struct policy_handle *handle,
1857 uint32_t level,
1858 struct security_descriptor *sd)
1860 struct spoolss_SetPrinterInfoCtr info_ctr;
1861 struct spoolss_DevmodeContainer devmode_ctr;
1862 struct sec_desc_buf secdesc_ctr;
1863 union spoolss_SetPrinterInfo sinfo;
1865 ZERO_STRUCT(devmode_ctr);
1866 ZERO_STRUCT(secdesc_ctr);
1868 switch (level) {
1869 case 2: {
1870 union spoolss_PrinterInfo info;
1871 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1872 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1874 info_ctr.level = 2;
1875 info_ctr.info = sinfo;
1877 break;
1879 case 3: {
1880 struct spoolss_SetPrinterInfo3 info3;
1882 info3.sec_desc_ptr = 0;
1884 info_ctr.level = 3;
1885 info_ctr.info.info3 = &info3;
1887 break;
1889 default:
1890 return false;
1893 secdesc_ctr.sd = sd;
1895 torture_assert(tctx,
1896 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1898 return true;
1901 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1902 struct dcerpc_binding_handle *b,
1903 struct policy_handle *handle)
1905 union spoolss_PrinterInfo info;
1906 struct security_descriptor *sd1, *sd2;
1907 int i;
1909 /* just compare level 2 and level 3 */
1911 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1913 sd1 = info.info2.secdesc;
1915 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1917 sd2 = info.info3.secdesc;
1919 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1920 "SD level 2 != SD level 3");
1923 /* query level 2, set level 2, query level 2 */
1925 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1927 sd1 = info.info2.secdesc;
1929 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1931 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1933 sd2 = info.info2.secdesc;
1934 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1935 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1936 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1939 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1940 "SD level 2 != SD level 2 after SD has been set via level 2");
1943 /* query level 2, set level 3, query level 2 */
1945 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1947 sd1 = info.info2.secdesc;
1949 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1951 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1953 sd2 = info.info2.secdesc;
1955 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1956 "SD level 2 != SD level 2 after SD has been set via level 3");
1958 /* set modified sd level 3, query level 2 */
1960 for (i=0; i < 93; i++) {
1961 struct security_ace a;
1962 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1963 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1964 a.flags = 0;
1965 a.size = 0; /* autogenerated */
1966 a.access_mask = 0;
1967 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1968 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1971 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1973 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1974 sd2 = info.info2.secdesc;
1976 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1977 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1978 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1981 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1982 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1985 return true;
1989 * wrapper call that saves original sd, runs tests, and restores sd
1992 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1993 struct dcerpc_binding_handle *b,
1994 struct policy_handle *handle)
1996 union spoolss_PrinterInfo info;
1997 struct security_descriptor *sd;
1998 bool ret = true;
2000 torture_comment(tctx, "Testing Printer Security Descriptors\n");
2002 /* save original sd */
2004 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
2005 "failed to get initial security descriptor");
2007 sd = security_descriptor_copy(tctx, info.info2.secdesc);
2009 /* run tests */
2011 ret = test_PrinterInfo_SDs(tctx, b, handle);
2013 /* restore original sd */
2015 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
2016 "failed to restore initial security descriptor");
2018 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
2019 ret ? "succeeded" : "failed");
2022 return ret;
2025 static bool test_devmode_set_level(struct torture_context *tctx,
2026 struct dcerpc_binding_handle *b,
2027 struct policy_handle *handle,
2028 uint32_t level,
2029 struct spoolss_DeviceMode *devmode)
2031 struct spoolss_SetPrinterInfoCtr info_ctr;
2032 struct spoolss_DevmodeContainer devmode_ctr;
2033 struct sec_desc_buf secdesc_ctr;
2034 union spoolss_SetPrinterInfo sinfo;
2036 ZERO_STRUCT(devmode_ctr);
2037 ZERO_STRUCT(secdesc_ctr);
2039 switch (level) {
2040 case 2: {
2041 union spoolss_PrinterInfo info;
2042 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2043 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
2045 info_ctr.level = 2;
2046 info_ctr.info = sinfo;
2048 break;
2050 case 8: {
2051 struct spoolss_SetPrinterInfo8 info8;
2053 info8.devmode_ptr = 0;
2055 info_ctr.level = 8;
2056 info_ctr.info.info8 = &info8;
2058 break;
2060 default:
2061 return false;
2064 devmode_ctr.devmode = devmode;
2066 torture_assert(tctx,
2067 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
2069 return true;
2073 static bool test_devicemode_equal(struct torture_context *tctx,
2074 const struct spoolss_DeviceMode *d1,
2075 const struct spoolss_DeviceMode *d2)
2077 if (d1 == d2) {
2078 return true;
2081 if (!d1 || !d2) {
2082 torture_comment(tctx, "%s\n", __location__);
2083 return false;
2085 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
2086 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
2087 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
2088 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
2089 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
2090 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
2091 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
2092 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
2093 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
2094 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
2095 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
2096 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
2097 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
2098 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2099 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2100 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2101 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2102 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2103 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2104 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2105 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2106 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2107 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2108 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2109 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2110 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2111 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2112 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2113 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2114 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2115 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2116 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2117 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2118 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2119 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2121 return true;
2124 static bool test_devicemode_full(struct torture_context *tctx,
2125 struct dcerpc_binding_handle *b,
2126 struct policy_handle *handle)
2128 struct spoolss_SetPrinter s;
2129 struct spoolss_GetPrinter q;
2130 struct spoolss_GetPrinter q0;
2131 struct spoolss_SetPrinterInfoCtr info_ctr;
2132 struct spoolss_SetPrinterInfo8 info8;
2133 union spoolss_PrinterInfo info;
2134 struct spoolss_DevmodeContainer devmode_ctr;
2135 struct sec_desc_buf secdesc_ctr;
2136 uint32_t needed;
2137 bool ret = true;
2138 NTSTATUS status;
2140 #define TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, exp_value, expected_result) do { \
2141 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2142 q.in.level = lvl1; \
2143 TESTGETCALL(GetPrinter, q) \
2144 info_ctr.level = lvl1; \
2145 if (lvl1 == 2) {\
2146 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
2147 } else if (lvl1 == 8) {\
2148 info_ctr.info.info ## lvl1 = &info8; \
2150 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2151 devmode_ctr.devmode->field1 = value; \
2152 TESTSETCALL_EXP(SetPrinter, s, expected_result) \
2153 if (W_ERROR_IS_OK(expected_result)) { \
2154 TESTGETCALL(GetPrinter, q) \
2155 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2156 q.in.level = lvl2; \
2157 TESTGETCALL(GetPrinter, q) \
2158 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2160 } while (0)
2162 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, expected_result) do { \
2163 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, expected_result); \
2164 } while (0)
2166 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2167 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, WERR_OK); \
2168 } while (0)
2170 ZERO_STRUCT(devmode_ctr);
2171 ZERO_STRUCT(secdesc_ctr);
2172 ZERO_STRUCT(info8);
2174 s.in.handle = handle;
2175 s.in.command = 0;
2176 s.in.info_ctr = &info_ctr;
2177 s.in.devmode_ctr = &devmode_ctr;
2178 s.in.secdesc_ctr = &secdesc_ctr;
2180 q.in.handle = handle;
2181 q.out.info = &info;
2182 q0 = q;
2184 #if 0
2185 const char *devicename;/* [charset(UTF16)] */
2186 enum spoolss_DeviceModeSpecVersion specversion;
2187 uint16_t driverversion;
2188 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2189 uint32_t fields;
2190 #endif
2191 TEST_DEVMODE_INT_EXP(8, size, 8, size, __LINE__, WERR_INVALID_PARAM);
2192 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0, WERR_INVALID_PARAM);
2193 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0xffff, WERR_INVALID_PARAM);
2194 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);
2195 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2197 devmode_ctr.devmode->driverextra_data = data_blob_string_const("foobar");
2198 torture_assert(tctx,
2199 test_devmode_set_level(tctx, b, handle, 8, devmode_ctr.devmode),
2200 "failed to set devmode");
2202 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);
2203 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2205 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
2206 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
2207 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
2208 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
2209 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
2210 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
2211 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
2212 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
2213 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
2214 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
2215 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
2216 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
2217 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
2218 #if 0
2219 const char *formname;/* [charset(UTF16)] */
2220 #endif
2221 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
2222 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
2223 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
2224 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
2225 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
2226 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
2227 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
2228 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
2229 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
2230 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
2231 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
2232 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
2233 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
2234 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
2236 return ret;
2239 static bool call_OpenPrinterEx(struct torture_context *tctx,
2240 struct dcerpc_pipe *p,
2241 const char *name,
2242 struct spoolss_DeviceMode *devmode,
2243 struct policy_handle *handle);
2245 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2246 struct dcerpc_pipe *p,
2247 struct policy_handle *handle,
2248 const char *name)
2250 union spoolss_PrinterInfo info;
2251 struct spoolss_DeviceMode *devmode;
2252 struct spoolss_DeviceMode *devmode2;
2253 struct policy_handle handle_devmode;
2254 struct dcerpc_binding_handle *b = p->binding_handle;
2256 /* simply compare level8 and level2 devmode */
2258 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2260 devmode = info.info8.devmode;
2262 if (devmode && devmode->size == 0) {
2263 torture_fail(tctx,
2264 "devmode of zero size!");
2267 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2269 devmode2 = info.info2.devmode;
2271 if (devmode2 && devmode2->size == 0) {
2272 torture_fail(tctx,
2273 "devmode of zero size!");
2276 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2277 "DM level 8 != DM level 2");
2280 /* set devicemode level 8 and see if it persists */
2282 devmode->copies = 93;
2283 devmode->formname = talloc_strdup(tctx, "Legal");
2285 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2287 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2289 devmode2 = info.info8.devmode;
2291 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2292 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2294 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2296 devmode2 = info.info2.devmode;
2298 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2299 "modified DM level 8 != DM level 2");
2302 /* set devicemode level 2 and see if it persists */
2304 devmode->copies = 39;
2305 devmode->formname = talloc_strdup(tctx, "Executive");
2307 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2309 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2311 devmode2 = info.info8.devmode;
2313 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2314 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2316 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2318 devmode2 = info.info2.devmode;
2320 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2321 "modified DM level 8 != DM level 2");
2324 /* check every single bit in public part of devicemode */
2326 torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2327 "failed to set every single devicemode component");
2330 /* change formname upon open and see if it persists in getprinter calls */
2332 devmode->formname = talloc_strdup(tctx, "A4");
2333 devmode->copies = 42;
2335 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2336 "failed to open printer handle");
2338 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2340 devmode2 = info.info8.devmode;
2342 if (strequal(devmode->devicename, devmode2->devicename)) {
2343 torture_warning(tctx, "devicenames are the same\n");
2344 } else {
2345 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2346 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2349 if (strequal(devmode->formname, devmode2->formname)) {
2350 torture_warning(tctx, "formname are the same\n");
2351 } else {
2352 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2353 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2356 if (devmode->copies == devmode2->copies) {
2357 torture_warning(tctx, "copies are the same\n");
2358 } else {
2359 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2360 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2363 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2365 devmode2 = info.info2.devmode;
2367 if (strequal(devmode->devicename, devmode2->devicename)) {
2368 torture_warning(tctx, "devicenames are the same\n");
2369 } else {
2370 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2371 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2374 if (strequal(devmode->formname, devmode2->formname)) {
2375 torture_warning(tctx, "formname is the same\n");
2376 } else {
2377 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2378 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2381 if (devmode->copies == devmode2->copies) {
2382 torture_warning(tctx, "copies are the same\n");
2383 } else {
2384 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2385 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2388 test_ClosePrinter(tctx, b, &handle_devmode);
2390 return true;
2394 * wrapper call that saves original devmode, runs tests, and restores devmode
2397 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2398 struct dcerpc_pipe *p,
2399 struct policy_handle *handle,
2400 const char *name,
2401 struct spoolss_DeviceMode *addprinter_devmode)
2403 union spoolss_PrinterInfo info;
2404 struct spoolss_DeviceMode *devmode;
2405 bool ret = true;
2406 struct dcerpc_binding_handle *b = p->binding_handle;
2408 torture_comment(tctx, "Testing Printer Devicemodes\n");
2410 /* save original devmode */
2412 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2413 "failed to get initial global devicemode");
2415 devmode = info.info8.devmode;
2417 if (devmode && devmode->size == 0) {
2418 torture_fail(tctx,
2419 "devmode of zero size!");
2422 if (addprinter_devmode) {
2423 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
2424 torture_warning(tctx, "current global DM is != DM provided in addprinter");
2428 /* run tests */
2430 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2432 /* restore original devmode */
2434 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2435 "failed to restore initial global device mode");
2437 torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2438 ret ? "succeeded" : "failed");
2441 return ret;
2444 bool test_ClosePrinter(struct torture_context *tctx,
2445 struct dcerpc_binding_handle *b,
2446 struct policy_handle *handle)
2448 NTSTATUS status;
2449 struct spoolss_ClosePrinter r;
2451 r.in.handle = handle;
2452 r.out.handle = handle;
2454 torture_comment(tctx, "Testing ClosePrinter\n");
2456 status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2457 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2458 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2460 return true;
2463 static bool test_GetForm_args(struct torture_context *tctx,
2464 struct dcerpc_binding_handle *b,
2465 struct policy_handle *handle,
2466 const char *form_name,
2467 uint32_t level,
2468 union spoolss_FormInfo *info_p)
2470 NTSTATUS status;
2471 struct spoolss_GetForm r;
2472 uint32_t needed;
2474 r.in.handle = handle;
2475 r.in.form_name = form_name;
2476 r.in.level = level;
2477 r.in.buffer = NULL;
2478 r.in.offered = 0;
2479 r.out.needed = &needed;
2481 torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2483 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2484 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2486 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2487 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2488 r.in.buffer = &blob;
2489 r.in.offered = needed;
2490 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2491 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2493 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2495 torture_assert(tctx, r.out.info, "No form info returned");
2498 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2500 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
2502 if (info_p) {
2503 *info_p = *r.out.info;
2506 return true;
2509 static bool test_GetForm(struct torture_context *tctx,
2510 struct dcerpc_binding_handle *b,
2511 struct policy_handle *handle,
2512 const char *form_name,
2513 uint32_t level)
2515 return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2518 static bool test_EnumForms(struct torture_context *tctx,
2519 struct dcerpc_binding_handle *b,
2520 struct policy_handle *handle,
2521 bool print_server,
2522 uint32_t level,
2523 uint32_t *count_p,
2524 union spoolss_FormInfo **info_p)
2526 struct spoolss_EnumForms r;
2527 uint32_t needed;
2528 uint32_t count;
2529 union spoolss_FormInfo *info;
2531 r.in.handle = handle;
2532 r.in.level = level;
2533 r.in.buffer = NULL;
2534 r.in.offered = 0;
2535 r.out.needed = &needed;
2536 r.out.count = &count;
2537 r.out.info = &info;
2539 torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2541 torture_assert_ntstatus_ok(tctx,
2542 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2543 "EnumForms failed");
2545 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2546 torture_skip(tctx, "EnumForms level 2 not supported");
2549 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2550 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2553 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2554 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2555 r.in.buffer = &blob;
2556 r.in.offered = needed;
2558 torture_assert_ntstatus_ok(tctx,
2559 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2560 "EnumForms failed");
2562 torture_assert(tctx, info, "No forms returned");
2565 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2567 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
2569 if (info_p) {
2570 *info_p = info;
2572 if (count_p) {
2573 *count_p = count;
2576 return true;
2579 static bool test_EnumForms_all(struct torture_context *tctx,
2580 struct dcerpc_binding_handle *b,
2581 struct policy_handle *handle,
2582 bool print_server)
2584 uint32_t levels[] = { 1, 2 };
2585 int i, j;
2587 for (i=0; i<ARRAY_SIZE(levels); i++) {
2589 uint32_t count = 0;
2590 union spoolss_FormInfo *info = NULL;
2592 torture_assert(tctx,
2593 test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2594 "failed to enum forms");
2596 for (j = 0; j < count; j++) {
2597 if (!print_server) {
2598 torture_assert(tctx,
2599 test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2600 "failed to get form");
2605 return true;
2608 static bool test_EnumForms_find_one(struct torture_context *tctx,
2609 struct dcerpc_binding_handle *b,
2610 struct policy_handle *handle,
2611 bool print_server,
2612 const char *form_name)
2614 union spoolss_FormInfo *info;
2615 uint32_t count;
2616 bool found = false;
2617 int i;
2619 torture_assert(tctx,
2620 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2621 "failed to enumerate forms");
2623 for (i=0; i<count; i++) {
2624 if (strequal(form_name, info[i].info1.form_name)) {
2625 found = true;
2626 break;
2630 return found;
2633 static bool test_DeleteForm(struct torture_context *tctx,
2634 struct dcerpc_binding_handle *b,
2635 struct policy_handle *handle,
2636 const char *form_name,
2637 WERROR expected_result)
2639 struct spoolss_DeleteForm r;
2641 r.in.handle = handle;
2642 r.in.form_name = form_name;
2644 torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2646 torture_assert_ntstatus_ok(tctx,
2647 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2648 "DeleteForm failed");
2649 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2650 "DeleteForm gave unexpected result");
2651 if (W_ERROR_IS_OK(r.out.result)) {
2652 torture_assert_ntstatus_ok(tctx,
2653 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2654 "2nd DeleteForm failed");
2655 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2656 "2nd DeleteForm failed");
2659 return true;
2662 static bool test_AddForm(struct torture_context *tctx,
2663 struct dcerpc_binding_handle *b,
2664 struct policy_handle *handle,
2665 uint32_t level,
2666 union spoolss_AddFormInfo *info,
2667 WERROR expected_result)
2669 struct spoolss_AddForm r;
2671 if (level != 1) {
2672 torture_skip(tctx, "only level 1 supported");
2675 r.in.handle = handle;
2676 r.in.level = level;
2677 r.in.info = *info;
2679 torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2680 r.in.info.info1->form_name, r.in.level,
2681 r.in.info.info1->flags);
2683 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2684 "AddForm failed");
2685 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2686 "AddForm gave unexpected result");
2688 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2689 "2nd AddForm failed");
2690 if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2691 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2692 "2nd AddForm gave unexpected result");
2693 } else {
2694 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2695 "2nd AddForm gave unexpected result");
2698 return true;
2701 static bool test_SetForm(struct torture_context *tctx,
2702 struct dcerpc_binding_handle *b,
2703 struct policy_handle *handle,
2704 const char *form_name,
2705 uint32_t level,
2706 union spoolss_AddFormInfo *info)
2708 struct spoolss_SetForm r;
2710 r.in.handle = handle;
2711 r.in.form_name = form_name;
2712 r.in.level = level;
2713 r.in.info = *info;
2715 torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2716 form_name, r.in.level);
2718 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2719 "SetForm failed");
2721 torture_assert_werr_ok(tctx, r.out.result,
2722 "SetForm failed");
2724 return true;
2727 static bool test_GetForm_winreg(struct torture_context *tctx,
2728 struct dcerpc_binding_handle *b,
2729 struct policy_handle *handle,
2730 const char *key_name,
2731 const char *form_name,
2732 enum winreg_Type *w_type,
2733 uint32_t *w_size,
2734 uint32_t *w_length,
2735 uint8_t **w_data);
2737 static bool test_Forms_args(struct torture_context *tctx,
2738 struct dcerpc_binding_handle *b,
2739 struct policy_handle *handle,
2740 bool print_server,
2741 const char *printer_name,
2742 struct dcerpc_binding_handle *winreg_handle,
2743 struct policy_handle *hive_handle,
2744 const char *form_name,
2745 struct spoolss_AddFormInfo1 *info1,
2746 WERROR expected_add_result,
2747 WERROR expected_delete_result)
2749 union spoolss_FormInfo info;
2750 union spoolss_AddFormInfo add_info;
2752 enum winreg_Type w_type;
2753 uint32_t w_size;
2754 uint32_t w_length;
2755 uint8_t *w_data;
2757 add_info.info1 = info1;
2759 torture_assert(tctx,
2760 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2761 "failed to add form");
2763 if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2765 struct spoolss_FormInfo1 i1;
2767 torture_assert(tctx,
2768 test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2769 "failed to get form via winreg");
2771 i1.size.width = IVAL(w_data, 0);
2772 i1.size.height = IVAL(w_data, 4);
2773 i1.area.left = IVAL(w_data, 8);
2774 i1.area.top = IVAL(w_data, 12);
2775 i1.area.right = IVAL(w_data, 16);
2776 i1.area.bottom = IVAL(w_data, 20);
2777 /* skip index here */
2778 i1.flags = IVAL(w_data, 28);
2780 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2781 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2782 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2783 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
2784 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
2785 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
2786 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
2787 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
2788 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2789 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
2792 if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2793 torture_assert(tctx,
2794 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2795 "failed to get added form");
2797 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2798 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2799 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2800 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2801 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2802 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2803 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2805 if (winreg_handle && hive_handle) {
2807 struct spoolss_FormInfo1 i1;
2809 i1.size.width = IVAL(w_data, 0);
2810 i1.size.height = IVAL(w_data, 4);
2811 i1.area.left = IVAL(w_data, 8);
2812 i1.area.top = IVAL(w_data, 12);
2813 i1.area.right = IVAL(w_data, 16);
2814 i1.area.bottom = IVAL(w_data, 20);
2815 /* skip index here */
2816 i1.flags = IVAL(w_data, 28);
2818 torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
2819 torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
2820 torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
2821 torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
2822 torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
2823 torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
2824 torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
2827 add_info.info1->size.width = 1234;
2829 torture_assert(tctx,
2830 test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2831 "failed to set form");
2832 torture_assert(tctx,
2833 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2834 "failed to get setted form");
2836 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2839 if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2840 torture_assert(tctx,
2841 test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2842 "Newly added form not found in enum call");
2845 torture_assert(tctx,
2846 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2847 "failed to delete form");
2849 return true;
2852 static bool test_Forms(struct torture_context *tctx,
2853 struct dcerpc_binding_handle *b,
2854 struct policy_handle *handle,
2855 bool print_server,
2856 const char *printer_name,
2857 struct dcerpc_binding_handle *winreg_handle,
2858 struct policy_handle *hive_handle)
2860 const struct spoolss_FormSize size = {
2861 .width = 50,
2862 .height = 25
2864 const struct spoolss_FormArea area = {
2865 .left = 5,
2866 .top = 10,
2867 .right = 45,
2868 .bottom = 15
2870 int i;
2872 struct {
2873 struct spoolss_AddFormInfo1 info1;
2874 WERROR expected_add_result;
2875 WERROR expected_delete_result;
2876 } forms[] = {
2878 .info1 = {
2879 .flags = SPOOLSS_FORM_USER,
2880 .form_name = "testform_user",
2881 .size = size,
2882 .area = area,
2884 .expected_add_result = WERR_OK,
2885 .expected_delete_result = WERR_OK
2888 weird, we can add a builtin form but we can never remove it
2889 again - gd
2892 .info1 = {
2893 .flags = SPOOLSS_FORM_BUILTIN,
2894 .form_name = "testform_builtin",
2895 .size = size,
2896 .area = area,
2898 .expected_add_result = WERR_OK,
2899 .expected_delete_result = WERR_INVALID_PARAM,
2903 .info1 = {
2904 .flags = SPOOLSS_FORM_PRINTER,
2905 .form_name = "testform_printer",
2906 .size = size,
2907 .area = area,
2909 .expected_add_result = WERR_OK,
2910 .expected_delete_result = WERR_OK
2913 .info1 = {
2914 .flags = SPOOLSS_FORM_USER,
2915 .form_name = "Letter",
2916 .size = size,
2917 .area = area,
2919 .expected_add_result = WERR_FILE_EXISTS,
2920 .expected_delete_result = WERR_INVALID_PARAM
2923 .info1 = {
2924 .flags = SPOOLSS_FORM_BUILTIN,
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_PRINTER,
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 = 12345,
2945 .form_name = "invalid_flags",
2946 .size = size,
2947 .area = area,
2949 .expected_add_result = WERR_INVALID_PARAM,
2950 .expected_delete_result = WERR_INVALID_FORM_NAME
2955 for (i=0; i < ARRAY_SIZE(forms); i++) {
2956 torture_assert(tctx,
2957 test_Forms_args(tctx, b, handle, print_server, printer_name,
2958 winreg_handle, hive_handle,
2959 forms[i].info1.form_name,
2960 &forms[i].info1,
2961 forms[i].expected_add_result,
2962 forms[i].expected_delete_result),
2963 talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2966 return true;
2969 static bool test_EnumPorts_old(struct torture_context *tctx,
2970 void *private_data)
2972 struct test_spoolss_context *ctx =
2973 talloc_get_type_abort(private_data, struct test_spoolss_context);
2975 NTSTATUS status;
2976 struct spoolss_EnumPorts r;
2977 uint32_t needed;
2978 uint32_t count;
2979 union spoolss_PortInfo *info;
2980 struct dcerpc_pipe *p = ctx->spoolss_pipe;
2981 struct dcerpc_binding_handle *b = p->binding_handle;
2983 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2984 dcerpc_server_name(p));
2985 r.in.level = 2;
2986 r.in.buffer = NULL;
2987 r.in.offered = 0;
2988 r.out.needed = &needed;
2989 r.out.count = &count;
2990 r.out.info = &info;
2992 torture_comment(tctx, "Testing EnumPorts\n");
2994 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2996 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
2998 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2999 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3000 r.in.buffer = &blob;
3001 r.in.offered = needed;
3003 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3004 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3005 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3007 torture_assert(tctx, info, "No ports returned");
3010 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3012 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
3014 return true;
3017 static bool test_AddPort(struct torture_context *tctx,
3018 void *private_data)
3020 struct test_spoolss_context *ctx =
3021 talloc_get_type_abort(private_data, struct test_spoolss_context);
3023 NTSTATUS status;
3024 struct spoolss_AddPort r;
3025 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3026 struct dcerpc_binding_handle *b = p->binding_handle;
3028 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
3029 dcerpc_server_name(p));
3030 r.in.unknown = 0;
3031 r.in.monitor_name = "foo";
3033 torture_comment(tctx, "Testing AddPort\n");
3035 status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
3037 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
3039 /* win2k3 returns WERR_NOT_SUPPORTED */
3041 #if 0
3043 if (!W_ERROR_IS_OK(r.out.result)) {
3044 printf("AddPort failed - %s\n", win_errstr(r.out.result));
3045 return false;
3048 #endif
3050 return true;
3053 static bool test_GetJob_args(struct torture_context *tctx,
3054 struct dcerpc_binding_handle *b,
3055 struct policy_handle *handle,
3056 uint32_t job_id,
3057 uint32_t level,
3058 union spoolss_JobInfo *info_p)
3060 NTSTATUS status;
3061 struct spoolss_GetJob r;
3062 union spoolss_JobInfo info;
3063 uint32_t needed;
3065 r.in.handle = handle;
3066 r.in.job_id = job_id;
3067 r.in.level = level;
3068 r.in.buffer = NULL;
3069 r.in.offered = 0;
3070 r.out.needed = &needed;
3071 r.out.info = &info;
3073 torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
3075 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3076 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3077 if (level == 0) {
3078 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
3081 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3082 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3083 r.in.buffer = &blob;
3084 r.in.offered = needed;
3086 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3087 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3090 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
3091 torture_assert(tctx, r.out.info, "No job info returned");
3093 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
3095 if (info_p) {
3096 *info_p = *r.out.info;
3099 return true;
3102 static bool test_GetJob(struct torture_context *tctx,
3103 struct dcerpc_binding_handle *b,
3104 struct policy_handle *handle,
3105 uint32_t job_id)
3107 uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
3108 uint32_t i;
3110 for (i=0; i < ARRAY_SIZE(levels); i++) {
3111 torture_assert(tctx,
3112 test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
3113 "GetJob failed");
3116 return true;
3119 static bool test_SetJob(struct torture_context *tctx,
3120 struct dcerpc_binding_handle *b,
3121 struct policy_handle *handle,
3122 uint32_t job_id,
3123 struct spoolss_JobInfoContainer *ctr,
3124 enum spoolss_JobControl command)
3126 NTSTATUS status;
3127 struct spoolss_SetJob r;
3129 r.in.handle = handle;
3130 r.in.job_id = job_id;
3131 r.in.ctr = ctr;
3132 r.in.command = command;
3134 switch (command) {
3135 case SPOOLSS_JOB_CONTROL_PAUSE:
3136 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3137 break;
3138 case SPOOLSS_JOB_CONTROL_RESUME:
3139 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3140 break;
3141 case SPOOLSS_JOB_CONTROL_CANCEL:
3142 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3143 break;
3144 case SPOOLSS_JOB_CONTROL_RESTART:
3145 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3146 break;
3147 case SPOOLSS_JOB_CONTROL_DELETE:
3148 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3149 break;
3150 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3151 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3152 break;
3153 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3154 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3155 break;
3156 case SPOOLSS_JOB_CONTROL_RETAIN:
3157 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3158 break;
3159 case SPOOLSS_JOB_CONTROL_RELEASE:
3160 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3161 break;
3162 default:
3163 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3164 break;
3167 status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3168 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3169 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3171 return true;
3174 static bool test_AddJob(struct torture_context *tctx,
3175 struct dcerpc_binding_handle *b,
3176 struct policy_handle *handle)
3178 NTSTATUS status;
3179 struct spoolss_AddJob r;
3180 uint32_t needed;
3182 r.in.level = 0;
3183 r.in.handle = handle;
3184 r.in.offered = 0;
3185 r.out.needed = &needed;
3186 r.in.buffer = r.out.buffer = NULL;
3188 torture_comment(tctx, "Testing AddJob\n");
3190 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3191 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3193 r.in.level = 1;
3195 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3196 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3198 return true;
3202 static bool test_EnumJobs_args(struct torture_context *tctx,
3203 struct dcerpc_binding_handle *b,
3204 struct policy_handle *handle,
3205 uint32_t level,
3206 uint32_t *count_p,
3207 union spoolss_JobInfo **info_p)
3209 NTSTATUS status;
3210 struct spoolss_EnumJobs r;
3211 uint32_t needed;
3212 uint32_t count;
3213 union spoolss_JobInfo *info;
3215 r.in.handle = handle;
3216 r.in.firstjob = 0;
3217 r.in.numjobs = 0xffffffff;
3218 r.in.level = level;
3219 r.in.buffer = NULL;
3220 r.in.offered = 0;
3221 r.out.needed = &needed;
3222 r.out.count = &count;
3223 r.out.info = &info;
3225 torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3227 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3229 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3231 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3232 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3233 r.in.buffer = &blob;
3234 r.in.offered = needed;
3236 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3238 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3239 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3240 torture_assert(tctx, info, "No jobs returned");
3242 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3244 } else {
3245 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3248 if (count_p) {
3249 *count_p = count;
3251 if (info_p) {
3252 *info_p = info;
3255 return true;
3258 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3259 struct dcerpc_binding_handle *b,
3260 struct policy_handle *handle,
3261 const char *document_name,
3262 uint32_t *job_id)
3264 NTSTATUS status;
3265 struct spoolss_StartDocPrinter s;
3266 struct spoolss_DocumentInfo1 info1;
3267 struct spoolss_StartPagePrinter sp;
3268 struct spoolss_WritePrinter w;
3269 struct spoolss_EndPagePrinter ep;
3270 struct spoolss_EndDocPrinter e;
3271 int i;
3272 uint32_t num_written;
3274 torture_comment(tctx, "Testing StartDocPrinter\n");
3276 s.in.handle = handle;
3277 s.in.level = 1;
3278 s.in.info.info1 = &info1;
3279 s.out.job_id = job_id;
3280 info1.document_name = document_name;
3281 info1.output_file = NULL;
3282 info1.datatype = "RAW";
3284 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3285 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3286 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3288 for (i=1; i < 4; i++) {
3289 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3291 sp.in.handle = handle;
3293 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3294 torture_assert_ntstatus_ok(tctx, status,
3295 "dcerpc_spoolss_StartPagePrinter failed");
3296 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3298 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3300 w.in.handle = handle;
3301 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3302 w.out.num_written = &num_written;
3304 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3305 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3306 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3308 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3310 ep.in.handle = handle;
3312 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3313 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3314 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3317 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3319 e.in.handle = handle;
3321 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3322 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3323 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3325 return true;
3328 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3329 struct dcerpc_binding_handle *b,
3330 struct policy_handle *handle,
3331 uint32_t num_jobs,
3332 uint32_t *job_ids)
3334 uint32_t count;
3335 union spoolss_JobInfo *info = NULL;
3336 int i;
3338 torture_assert(tctx,
3339 test_AddJob(tctx, b, handle),
3340 "AddJob failed");
3342 torture_assert(tctx,
3343 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3344 "EnumJobs level 1 failed");
3346 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3348 for (i=0; i < num_jobs; i++) {
3349 union spoolss_JobInfo ginfo;
3350 const char *document_name;
3351 const char *new_document_name = "any_other_docname";
3352 struct spoolss_JobInfoContainer ctr;
3353 struct spoolss_SetJobInfo1 info1;
3355 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3357 torture_assert(tctx,
3358 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3359 "failed to call test_GetJob");
3361 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3363 document_name = ginfo.info1.document_name;
3365 info1.job_id = ginfo.info1.job_id;
3366 info1.printer_name = ginfo.info1.printer_name;
3367 info1.server_name = ginfo.info1.server_name;
3368 info1.user_name = ginfo.info1.user_name;
3369 info1.document_name = new_document_name;
3370 info1.data_type = ginfo.info1.data_type;
3371 info1.text_status = ginfo.info1.text_status;
3372 info1.status = ginfo.info1.status;
3373 info1.priority = ginfo.info1.priority;
3374 info1.position = ginfo.info1.position;
3375 info1.total_pages = ginfo.info1.total_pages;
3376 info1.pages_printed = ginfo.info1.pages_printed;
3377 info1.submitted = ginfo.info1.submitted;
3379 ctr.level = 1;
3380 ctr.info.info1 = &info1;
3382 torture_assert(tctx,
3383 test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3384 "failed to call test_SetJob level 1");
3386 torture_assert(tctx,
3387 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3388 "failed to call test_GetJob");
3390 if (strequal(ginfo.info1.document_name, document_name)) {
3391 torture_warning(tctx,
3392 "document_name did *NOT* change from '%s' to '%s'\n",
3393 document_name, new_document_name);
3397 for (i=0; i < num_jobs; i++) {
3398 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3399 torture_warning(tctx, "failed to pause printjob\n");
3401 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3402 torture_warning(tctx, "failed to resume printjob\n");
3406 return true;
3409 static bool test_DoPrintTest(struct torture_context *tctx,
3410 struct dcerpc_binding_handle *b,
3411 struct policy_handle *handle)
3413 bool ret = true;
3414 uint32_t num_jobs = 8;
3415 uint32_t *job_ids;
3416 int i;
3418 torture_comment(tctx, "Testing real print operations\n");
3420 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3422 for (i=0; i < num_jobs; i++) {
3423 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3426 for (i=0; i < num_jobs; i++) {
3427 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3430 if (ret == true) {
3431 torture_comment(tctx, "real print operations test succeeded\n\n");
3434 return ret;
3437 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3438 struct dcerpc_binding_handle *b,
3439 struct policy_handle *handle)
3441 bool ret = true;
3442 uint32_t num_jobs = 8;
3443 uint32_t *job_ids;
3444 int i;
3445 torture_comment(tctx, "Testing real print operations (extended)\n");
3447 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3449 for (i=0; i < num_jobs; i++) {
3450 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3453 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3455 for (i=0; i < num_jobs; i++) {
3456 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3459 if (ret == true) {
3460 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3463 return ret;
3466 static bool test_PausePrinter(struct torture_context *tctx,
3467 struct dcerpc_binding_handle *b,
3468 struct policy_handle *handle)
3470 NTSTATUS status;
3471 struct spoolss_SetPrinter r;
3472 struct spoolss_SetPrinterInfoCtr info_ctr;
3473 struct spoolss_DevmodeContainer devmode_ctr;
3474 struct sec_desc_buf secdesc_ctr;
3476 info_ctr.level = 0;
3477 info_ctr.info.info0 = NULL;
3479 ZERO_STRUCT(devmode_ctr);
3480 ZERO_STRUCT(secdesc_ctr);
3482 r.in.handle = handle;
3483 r.in.info_ctr = &info_ctr;
3484 r.in.devmode_ctr = &devmode_ctr;
3485 r.in.secdesc_ctr = &secdesc_ctr;
3486 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3488 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3490 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3492 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3494 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3496 return true;
3499 static bool test_ResumePrinter(struct torture_context *tctx,
3500 struct dcerpc_binding_handle *b,
3501 struct policy_handle *handle)
3503 NTSTATUS status;
3504 struct spoolss_SetPrinter r;
3505 struct spoolss_SetPrinterInfoCtr info_ctr;
3506 struct spoolss_DevmodeContainer devmode_ctr;
3507 struct sec_desc_buf secdesc_ctr;
3509 info_ctr.level = 0;
3510 info_ctr.info.info0 = NULL;
3512 ZERO_STRUCT(devmode_ctr);
3513 ZERO_STRUCT(secdesc_ctr);
3515 r.in.handle = handle;
3516 r.in.info_ctr = &info_ctr;
3517 r.in.devmode_ctr = &devmode_ctr;
3518 r.in.secdesc_ctr = &secdesc_ctr;
3519 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3521 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3523 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3525 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3527 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3529 return true;
3532 static bool test_GetPrinterData_checktype(struct torture_context *tctx,
3533 struct dcerpc_binding_handle *b,
3534 struct policy_handle *handle,
3535 const char *value_name,
3536 enum winreg_Type *expected_type,
3537 enum winreg_Type *type_p,
3538 uint8_t **data_p,
3539 uint32_t *needed_p)
3541 NTSTATUS status;
3542 struct spoolss_GetPrinterData r;
3543 uint32_t needed;
3544 enum winreg_Type type;
3545 union spoolss_PrinterData data;
3547 r.in.handle = handle;
3548 r.in.value_name = value_name;
3549 r.in.offered = 0;
3550 r.out.needed = &needed;
3551 r.out.type = &type;
3552 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3554 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3556 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3557 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3559 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3560 if (expected_type) {
3561 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3563 r.in.offered = needed;
3564 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3565 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3566 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3569 torture_assert_werr_ok(tctx, r.out.result,
3570 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3572 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3574 if (type_p) {
3575 *type_p = type;
3578 if (data_p) {
3579 *data_p = r.out.data;
3582 if (needed_p) {
3583 *needed_p = needed;
3586 return true;
3589 static bool test_GetPrinterData(struct torture_context *tctx,
3590 struct dcerpc_binding_handle *b,
3591 struct policy_handle *handle,
3592 const char *value_name,
3593 enum winreg_Type *type_p,
3594 uint8_t **data_p,
3595 uint32_t *needed_p)
3597 return test_GetPrinterData_checktype(tctx, b, handle, value_name,
3598 NULL, type_p, data_p, needed_p);
3601 static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
3602 struct dcerpc_pipe *p,
3603 struct policy_handle *handle,
3604 const char *key_name,
3605 const char *value_name,
3606 enum winreg_Type *expected_type,
3607 enum winreg_Type *type_p,
3608 uint8_t **data_p,
3609 uint32_t *needed_p)
3611 NTSTATUS status;
3612 struct spoolss_GetPrinterDataEx r;
3613 enum winreg_Type type;
3614 uint32_t needed;
3615 union spoolss_PrinterData data;
3616 struct dcerpc_binding_handle *b = p->binding_handle;
3618 r.in.handle = handle;
3619 r.in.key_name = key_name;
3620 r.in.value_name = value_name;
3621 r.in.offered = 0;
3622 r.out.type = &type;
3623 r.out.needed = &needed;
3624 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3626 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3627 r.in.key_name, r.in.value_name);
3629 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3630 if (!NT_STATUS_IS_OK(status)) {
3631 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3632 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3634 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3637 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3638 if (expected_type) {
3639 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3641 r.in.offered = needed;
3642 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3643 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3644 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3647 torture_assert_werr_ok(tctx, r.out.result,
3648 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3650 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3652 if (type_p) {
3653 *type_p = type;
3656 if (data_p) {
3657 *data_p = r.out.data;
3660 if (needed_p) {
3661 *needed_p = needed;
3664 return true;
3667 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3668 struct dcerpc_pipe *p,
3669 struct policy_handle *handle,
3670 const char *key_name,
3671 const char *value_name,
3672 enum winreg_Type *type_p,
3673 uint8_t **data_p,
3674 uint32_t *needed_p)
3676 return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
3677 NULL, type_p, data_p, needed_p);
3680 static bool test_get_environment(struct torture_context *tctx,
3681 struct dcerpc_binding_handle *b,
3682 struct policy_handle *handle,
3683 const char **architecture)
3685 DATA_BLOB blob;
3686 enum winreg_Type type;
3687 uint8_t *data;
3688 uint32_t needed;
3690 torture_assert(tctx,
3691 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3692 "failed to get Architecture");
3694 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3696 blob = data_blob_const(data, needed);
3697 *architecture = reg_val_data_string(tctx, REG_SZ, blob);
3699 return true;
3702 static bool test_GetPrinterData_list(struct torture_context *tctx,
3703 void *private_data)
3705 struct test_spoolss_context *ctx =
3706 talloc_get_type_abort(private_data, struct test_spoolss_context);
3707 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3708 struct dcerpc_binding_handle *b = p->binding_handle;
3709 const char *list[] = {
3710 "W3SvcInstalled",
3711 "BeepEnabled",
3712 "EventLog",
3713 /* "NetPopup", not on w2k8 */
3714 /* "NetPopupToComputer", not on w2k8 */
3715 "MajorVersion",
3716 "MinorVersion",
3717 "DefaultSpoolDirectory",
3718 "Architecture",
3719 "DsPresent",
3720 "OSVersion",
3721 /* "OSVersionEx", not on s3 */
3722 "DNSMachineName"
3724 int i;
3726 for (i=0; i < ARRAY_SIZE(list); i++) {
3727 enum winreg_Type type, type_ex;
3728 uint8_t *data, *data_ex;
3729 uint32_t needed, needed_ex;
3731 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
3732 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
3733 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
3734 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
3735 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
3736 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
3737 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3740 return true;
3743 static bool test_EnumPrinterData(struct torture_context *tctx,
3744 struct dcerpc_pipe *p,
3745 struct policy_handle *handle,
3746 uint32_t enum_index,
3747 uint32_t value_offered,
3748 uint32_t data_offered,
3749 enum winreg_Type *type_p,
3750 uint32_t *value_needed_p,
3751 uint32_t *data_needed_p,
3752 const char **value_name_p,
3753 uint8_t **data_p,
3754 WERROR *result_p)
3756 struct spoolss_EnumPrinterData r;
3757 uint32_t data_needed;
3758 uint32_t value_needed;
3759 enum winreg_Type type;
3760 struct dcerpc_binding_handle *b = p->binding_handle;
3762 r.in.handle = handle;
3763 r.in.enum_index = enum_index;
3764 r.in.value_offered = value_offered;
3765 r.in.data_offered = data_offered;
3766 r.out.data_needed = &data_needed;
3767 r.out.value_needed = &value_needed;
3768 r.out.type = &type;
3769 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3770 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3772 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3774 torture_assert_ntstatus_ok(tctx,
3775 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
3776 "EnumPrinterData failed");
3778 if (type_p) {
3779 *type_p = type;
3781 if (value_needed_p) {
3782 *value_needed_p = value_needed;
3784 if (data_needed_p) {
3785 *data_needed_p = data_needed;
3787 if (value_name_p) {
3788 *value_name_p = r.out.value_name;
3790 if (data_p) {
3791 *data_p = r.out.data;
3793 if (result_p) {
3794 *result_p = r.out.result;
3797 return true;
3801 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3802 struct dcerpc_pipe *p,
3803 struct policy_handle *handle)
3805 uint32_t enum_index = 0;
3806 enum winreg_Type type;
3807 uint32_t value_needed;
3808 uint32_t data_needed;
3809 uint8_t *data;
3810 const char *value_name;
3811 WERROR result;
3813 torture_comment(tctx, "Testing EnumPrinterData\n");
3815 do {
3816 torture_assert(tctx,
3817 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3818 &type, &value_needed, &data_needed,
3819 &value_name, &data, &result),
3820 "EnumPrinterData failed");
3822 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3823 break;
3826 torture_assert(tctx,
3827 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3828 &type, &value_needed, &data_needed,
3829 &value_name, &data, &result),
3830 "EnumPrinterData failed");
3832 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3833 break;
3836 enum_index++;
3838 } while (W_ERROR_IS_OK(result));
3840 torture_comment(tctx, "EnumPrinterData test succeeded\n");
3842 return true;
3845 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3846 struct dcerpc_binding_handle *b,
3847 struct policy_handle *handle,
3848 const char *key_name,
3849 uint32_t *count_p,
3850 struct spoolss_PrinterEnumValues **info_p)
3852 struct spoolss_EnumPrinterDataEx r;
3853 struct spoolss_PrinterEnumValues *info;
3854 uint32_t needed;
3855 uint32_t count;
3857 r.in.handle = handle;
3858 r.in.key_name = key_name;
3859 r.in.offered = 0;
3860 r.out.needed = &needed;
3861 r.out.count = &count;
3862 r.out.info = &info;
3864 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3866 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3867 "EnumPrinterDataEx failed");
3868 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3869 r.in.offered = needed;
3870 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3871 "EnumPrinterDataEx failed");
3874 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3876 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
3878 if (count_p) {
3879 *count_p = count;
3881 if (info_p) {
3882 *info_p = info;
3885 return true;
3888 static bool test_SetPrinterData(struct torture_context *tctx,
3889 struct dcerpc_binding_handle *b,
3890 struct policy_handle *handle,
3891 const char *value_name,
3892 enum winreg_Type type,
3893 uint8_t *data,
3894 uint32_t offered);
3895 static bool test_DeletePrinterData(struct torture_context *tctx,
3896 struct dcerpc_binding_handle *b,
3897 struct policy_handle *handle,
3898 const char *value_name);
3900 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3901 struct dcerpc_pipe *p,
3902 struct policy_handle *handle)
3904 uint32_t count;
3905 struct spoolss_PrinterEnumValues *info;
3906 int i;
3907 uint32_t value_needed, data_needed;
3908 uint32_t value_offered, data_offered;
3909 WERROR result;
3910 struct dcerpc_binding_handle *b = p->binding_handle;
3912 enum winreg_Type type;
3913 DATA_BLOB blob;
3915 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3917 torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
3918 type = REG_SZ;
3920 torture_assert(tctx,
3921 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
3922 "SetPrinterData failed");
3924 blob = data_blob_string_const("torture_data2");
3926 torture_assert(tctx,
3927 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3928 "SetPrinterData failed");
3930 blob = data_blob_talloc(tctx, NULL, 4);
3931 SIVAL(blob.data, 0, 0x11223344);
3933 torture_assert(tctx,
3934 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
3935 "SetPrinterData failed");
3937 torture_assert(tctx,
3938 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
3939 "failed to call EnumPrinterDataEx");
3941 /* get the max sizes for value and data */
3943 torture_assert(tctx,
3944 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3945 NULL, &value_needed, &data_needed,
3946 NULL, NULL, &result),
3947 "EnumPrinterData failed");
3948 torture_assert_werr_ok(tctx, result, "unexpected result");
3950 /* check if the reply from the EnumPrinterData really matches max values */
3952 for (i=0; i < count; i++) {
3953 if (info[i].value_name_len > value_needed) {
3954 torture_fail(tctx,
3955 talloc_asprintf(tctx,
3956 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3957 info[i].value_name_len, value_needed));
3959 if (info[i].data_length > data_needed) {
3960 torture_fail(tctx,
3961 talloc_asprintf(tctx,
3962 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3963 info[i].data_length, data_needed));
3967 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3968 * sort or not sort the replies by value name, we should be able to do
3969 * the following entry comparison */
3971 data_offered = data_needed;
3972 value_offered = value_needed;
3974 for (i=0; i < count; i++) {
3976 const char *value_name;
3977 uint8_t *data;
3979 torture_assert(tctx,
3980 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3981 &type, &value_needed, &data_needed,
3982 &value_name, &data, &result),
3983 "EnumPrinterData failed");
3985 if (i -1 == count) {
3986 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3987 "unexpected result");
3988 break;
3989 } else {
3990 torture_assert_werr_ok(tctx, result, "unexpected result");
3993 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3994 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3995 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
3996 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
3997 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
4000 torture_assert(tctx,
4001 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
4002 "DeletePrinterData failed");
4003 torture_assert(tctx,
4004 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
4005 "DeletePrinterData failed");
4006 torture_assert(tctx,
4007 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
4008 "DeletePrinterData failed");
4010 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4012 return true;
4015 static bool test_DeletePrinterData(struct torture_context *tctx,
4016 struct dcerpc_binding_handle *b,
4017 struct policy_handle *handle,
4018 const char *value_name)
4020 NTSTATUS status;
4021 struct spoolss_DeletePrinterData r;
4023 r.in.handle = handle;
4024 r.in.value_name = value_name;
4026 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
4027 r.in.value_name);
4029 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
4031 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
4032 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
4034 return true;
4037 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
4038 struct dcerpc_binding_handle *b,
4039 struct policy_handle *handle,
4040 const char *key_name,
4041 const char *value_name)
4043 struct spoolss_DeletePrinterDataEx r;
4045 r.in.handle = handle;
4046 r.in.key_name = key_name;
4047 r.in.value_name = value_name;
4049 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
4050 r.in.key_name, r.in.value_name);
4052 torture_assert_ntstatus_ok(tctx,
4053 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
4054 "DeletePrinterDataEx failed");
4055 torture_assert_werr_ok(tctx, r.out.result,
4056 "DeletePrinterDataEx failed");
4058 return true;
4061 static bool test_DeletePrinterKey(struct torture_context *tctx,
4062 struct dcerpc_binding_handle *b,
4063 struct policy_handle *handle,
4064 const char *key_name)
4066 struct spoolss_DeletePrinterKey r;
4068 r.in.handle = handle;
4069 r.in.key_name = key_name;
4071 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
4073 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
4074 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
4075 return true;
4078 torture_assert_ntstatus_ok(tctx,
4079 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
4080 "DeletePrinterKey failed");
4081 torture_assert_werr_ok(tctx, r.out.result,
4082 "DeletePrinterKey failed");
4084 return true;
4087 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4088 struct dcerpc_binding_handle *b,
4089 struct policy_handle *handle)
4091 struct winreg_OpenHKLM r;
4093 r.in.system_name = NULL;
4094 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4095 r.out.handle = handle;
4097 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4099 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4100 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4102 return true;
4105 static void init_winreg_String(struct winreg_String *name, const char *s)
4107 name->name = s;
4108 if (s) {
4109 name->name_len = 2 * (strlen_m(s) + 1);
4110 name->name_size = name->name_len;
4111 } else {
4112 name->name_len = 0;
4113 name->name_size = 0;
4117 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4118 struct dcerpc_binding_handle *b,
4119 struct policy_handle *hive_handle,
4120 const char *keyname,
4121 uint32_t options,
4122 struct policy_handle *key_handle)
4124 struct winreg_OpenKey r;
4126 r.in.parent_handle = hive_handle;
4127 init_winreg_String(&r.in.keyname, keyname);
4128 r.in.options = options;
4129 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4130 r.out.handle = key_handle;
4132 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4134 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4135 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4137 return true;
4140 static bool test_winreg_OpenKey(struct torture_context *tctx,
4141 struct dcerpc_binding_handle *b,
4142 struct policy_handle *hive_handle,
4143 const char *keyname,
4144 struct policy_handle *key_handle)
4146 return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4147 REG_OPTION_NON_VOLATILE, key_handle);
4150 static bool test_winreg_CloseKey(struct torture_context *tctx,
4151 struct dcerpc_binding_handle *b,
4152 struct policy_handle *handle)
4154 struct winreg_CloseKey r;
4156 r.in.handle = handle;
4157 r.out.handle = handle;
4159 torture_comment(tctx, "Testing winreg_CloseKey\n");
4161 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4162 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4164 return true;
4167 bool test_winreg_QueryValue(struct torture_context *tctx,
4168 struct dcerpc_binding_handle *b,
4169 struct policy_handle *handle,
4170 const char *value_name,
4171 enum winreg_Type *type_p,
4172 uint32_t *data_size_p,
4173 uint32_t *data_length_p,
4174 uint8_t **data_p)
4176 struct winreg_QueryValue r;
4177 enum winreg_Type type = REG_NONE;
4178 uint32_t data_size = 0;
4179 uint32_t data_length = 0;
4180 struct winreg_String valuename;
4181 uint8_t *data = NULL;
4183 init_winreg_String(&valuename, value_name);
4185 data = talloc_zero_array(tctx, uint8_t, 0);
4187 r.in.handle = handle;
4188 r.in.value_name = &valuename;
4189 r.in.type = &type;
4190 r.in.data_size = &data_size;
4191 r.in.data_length = &data_length;
4192 r.in.data = data;
4193 r.out.type = &type;
4194 r.out.data = data;
4195 r.out.data_size = &data_size;
4196 r.out.data_length = &data_length;
4198 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4200 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4201 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4202 *r.in.data_size = *r.out.data_size;
4203 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4204 r.in.data = data;
4205 r.out.data = data;
4206 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4208 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4210 if (type_p) {
4211 *type_p = *r.out.type;
4213 if (data_size_p) {
4214 *data_size_p = *r.out.data_size;
4216 if (data_length_p) {
4217 *data_length_p = *r.out.data_length;
4219 if (data_p) {
4220 *data_p = r.out.data;
4223 return true;
4226 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4227 struct dcerpc_binding_handle *b,
4228 struct policy_handle *handle,
4229 const char *printer_name,
4230 const char *key_name,
4231 const char *value_name,
4232 enum winreg_Type *w_type,
4233 uint32_t *w_size,
4234 uint32_t *w_length,
4235 uint8_t **w_data)
4237 const char *printer_key;
4238 struct policy_handle key_handle;
4240 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4241 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4243 torture_assert(tctx,
4244 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4246 torture_assert(tctx,
4247 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4249 torture_assert(tctx,
4250 test_winreg_CloseKey(tctx, b, &key_handle), "");
4252 return true;
4255 static bool test_GetForm_winreg(struct torture_context *tctx,
4256 struct dcerpc_binding_handle *b,
4257 struct policy_handle *handle,
4258 const char *key_name,
4259 const char *form_name,
4260 enum winreg_Type *w_type,
4261 uint32_t *w_size,
4262 uint32_t *w_length,
4263 uint8_t **w_data)
4265 struct policy_handle key_handle;
4267 torture_assert(tctx,
4268 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4270 torture_assert(tctx,
4271 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4273 torture_assert(tctx,
4274 test_winreg_CloseKey(tctx, b, &key_handle), "");
4276 return true;
4279 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4280 struct dcerpc_binding_handle *b,
4281 struct policy_handle *handle,
4282 const char *symlink_keyname,
4283 const char *symlink_destination)
4285 /* check if the first key is a symlink to the second key */
4287 enum winreg_Type w_type;
4288 uint32_t w_size;
4289 uint32_t w_length;
4290 uint8_t *w_data;
4291 struct policy_handle key_handle;
4292 DATA_BLOB blob;
4293 const char *str;
4295 if (torture_setting_bool(tctx, "samba3", false)) {
4296 torture_skip(tctx, "skip winreg symlink test against samba");
4299 torture_assert(tctx,
4300 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4301 "failed to open key link");
4303 torture_assert(tctx,
4304 test_winreg_QueryValue(tctx, b, &key_handle,
4305 "SymbolicLinkValue",
4306 &w_type, &w_size, &w_length, &w_data),
4307 "failed to query for 'SymbolicLinkValue' attribute");
4309 torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4311 blob = data_blob(w_data, w_size);
4312 str = reg_val_data_string(tctx, REG_SZ, blob);
4314 torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4316 torture_assert(tctx,
4317 test_winreg_CloseKey(tctx, b, &key_handle),
4318 "failed to close key link");
4320 return true;
4323 static const char *strip_unc(const char *unc)
4325 char *name;
4327 if (!unc) {
4328 return NULL;
4331 if (unc[0] == '\\' && unc[1] == '\\') {
4332 unc +=2;
4335 name = strchr(unc, '\\');
4336 if (name) {
4337 return name+1;
4340 return unc;
4343 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4344 struct dcerpc_binding_handle *b,
4345 struct policy_handle *handle,
4346 const char *printer_name,
4347 struct dcerpc_binding_handle *winreg_handle,
4348 struct policy_handle *hive_handle)
4350 union spoolss_PrinterInfo info;
4351 const char *keys[] = {
4352 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4353 TOP_LEVEL_PRINT_PRINTERS_KEY
4355 int i;
4356 const char *printername, *sharename;
4358 torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4360 torture_assert(tctx,
4361 test_GetPrinter_level(tctx, b, handle, 2, &info),
4362 "failed to get printer info level 2");
4364 printername = strip_unc(info.info2.printername);
4365 sharename = strip_unc(info.info2.sharename);
4367 #define test_sz(wname, iname) \
4368 do {\
4369 DATA_BLOB blob;\
4370 const char *str;\
4371 enum winreg_Type w_type;\
4372 uint32_t w_size;\
4373 uint32_t w_length;\
4374 uint8_t *w_data;\
4375 torture_assert(tctx,\
4376 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4377 &w_type, &w_size, &w_length, &w_data),\
4378 "failed to query winreg");\
4379 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4380 blob = data_blob(w_data, w_size);\
4381 str = reg_val_data_string(tctx, REG_SZ, blob);\
4382 if (w_size == 2 && iname == NULL) {\
4383 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4384 } else {\
4385 torture_assert_str_equal(tctx, str, iname,\
4386 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4388 } while(0);
4390 #define test_dword(wname, iname) \
4391 do {\
4392 uint32_t value;\
4393 enum winreg_Type w_type;\
4394 uint32_t w_size;\
4395 uint32_t w_length;\
4396 uint8_t *w_data;\
4397 torture_assert(tctx,\
4398 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4399 &w_type, &w_size, &w_length, &w_data),\
4400 "failed to query winreg");\
4401 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4402 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4403 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4404 value = IVAL(w_data, 0);\
4405 torture_assert_int_equal(tctx, value, iname,\
4406 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4407 } while(0);
4409 #define test_binary(wname, iname) \
4410 do {\
4411 enum winreg_Type w_type;\
4412 uint32_t w_size;\
4413 uint32_t w_length;\
4414 uint8_t *w_data;\
4415 torture_assert(tctx,\
4416 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4417 &w_type, &w_size, &w_length, &w_data),\
4418 "failed to query winreg");\
4419 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4420 torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4421 torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4422 "binary unequal");\
4423 } while(0);
4426 #define test_dm(wname, iname) \
4427 do {\
4428 DATA_BLOB blob;\
4429 struct spoolss_DeviceMode dm;\
4430 enum ndr_err_code ndr_err;\
4431 enum winreg_Type w_type;\
4432 uint32_t w_size;\
4433 uint32_t w_length;\
4434 uint8_t *w_data;\
4435 torture_assert(tctx,\
4436 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4437 &w_type, &w_size, &w_length, &w_data),\
4438 "failed to query winreg");\
4439 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4440 blob = data_blob(w_data, w_size);\
4441 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4442 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4443 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4444 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4445 "dm unequal");\
4446 } while(0);
4448 #define test_sd(wname, iname) \
4449 do {\
4450 DATA_BLOB blob;\
4451 struct security_descriptor sd;\
4452 enum ndr_err_code ndr_err;\
4453 enum winreg_Type w_type;\
4454 uint32_t w_size;\
4455 uint32_t w_length;\
4456 uint8_t *w_data;\
4457 torture_assert(tctx,\
4458 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4459 &w_type, &w_size, &w_length, &w_data),\
4460 "failed to query winreg");\
4461 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4462 blob = data_blob(w_data, w_size);\
4463 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4464 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4465 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4466 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4467 "sd unequal");\
4468 } while(0);
4470 #define test_multi_sz(wname, iname) \
4471 do {\
4472 DATA_BLOB blob;\
4473 const char **array;\
4474 enum winreg_Type w_type;\
4475 uint32_t w_size;\
4476 uint32_t w_length;\
4477 uint8_t *w_data;\
4478 int i;\
4479 torture_assert(tctx,\
4480 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4481 &w_type, &w_size, &w_length, &w_data),\
4482 "failed to query winreg");\
4483 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4484 blob = data_blob(w_data, w_size);\
4485 torture_assert(tctx, \
4486 pull_reg_multi_sz(tctx, &blob, &array),\
4487 "failed to pull multi sz");\
4488 for (i=0; array[i] != NULL; i++) {\
4489 torture_assert_str_equal(tctx, array[i], iname[i],\
4490 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4492 } while(0);
4494 if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4495 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4496 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4498 torture_warning(tctx, "failed to check for winreg symlink");
4501 for (i=0; i < ARRAY_SIZE(keys); i++) {
4503 const char *printer_key;
4504 struct policy_handle key_handle;
4506 printer_key = talloc_asprintf(tctx, "%s\\%s",
4507 keys[i], printer_name);
4509 torture_assert(tctx,
4510 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4512 test_sz("Name", printername);
4513 test_sz("Share Name", sharename);
4514 test_sz("Port", info.info2.portname);
4515 test_sz("Printer Driver", info.info2.drivername);
4516 test_sz("Description", info.info2.comment);
4517 test_sz("Location", info.info2.location);
4518 test_sz("Separator File", info.info2.sepfile);
4519 test_sz("Print Processor", info.info2.printprocessor);
4520 test_sz("Datatype", info.info2.datatype);
4521 test_sz("Parameters", info.info2.parameters);
4522 /* winreg: 0, spoolss not */
4523 /* test_dword("Attributes", info.info2.attributes); */
4524 test_dword("Priority", info.info2.priority);
4525 test_dword("Default Priority", info.info2.defaultpriority);
4526 /* winreg: 60, spoolss: 0 */
4527 /* test_dword("StartTime", info.info2.starttime); */
4528 /* test_dword("UntilTime", info.info2.untiltime); */
4529 /* winreg != spoolss */
4530 /* test_dword("Status", info.info2.status); */
4531 test_dm("Default DevMode", info.info2.devmode);
4532 test_sd("Security", info.info2.secdesc);
4534 torture_assert(tctx,
4535 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4538 #undef test_dm
4539 #undef test_sd
4541 torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4543 return true;
4546 static bool test_PrintProcessors(struct torture_context *tctx,
4547 struct dcerpc_binding_handle *b,
4548 const char *environment,
4549 struct dcerpc_binding_handle *winreg_handle,
4550 struct policy_handle *hive_handle)
4552 union spoolss_PrintProcessorInfo *info;
4553 uint32_t count;
4554 int i;
4556 torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4558 torture_assert(tctx,
4559 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
4560 "failed to enum print processors level 1");
4562 for (i=0; i < count; i++) {
4564 const char *processor_key;
4565 struct policy_handle key_handle;
4567 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4568 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4569 environment,
4570 info[i].info1.print_processor_name);
4572 torture_assert(tctx,
4573 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4575 /* nothing to check in there so far */
4577 torture_assert(tctx,
4578 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4581 torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4583 return true;
4586 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4587 struct dcerpc_binding_handle *b,
4588 struct policy_handle *handle,
4589 const char *driver_name,
4590 const char *architecture,
4591 uint32_t level,
4592 uint32_t client_major_version,
4593 uint32_t client_minor_version,
4594 union spoolss_DriverInfo *info_p,
4595 WERROR *result);
4597 static const char *strip_path(const char *path)
4599 char *p;
4601 if (path == NULL) {
4602 return NULL;
4605 p = strrchr(path, '\\');
4606 if (p) {
4607 return p+1;
4610 return path;
4613 static const char **strip_paths(const char **path_array)
4615 int i;
4617 if (path_array == NULL) {
4618 return NULL;
4621 for (i=0; path_array[i] != NULL; i++) {
4622 path_array[i] = strip_path(path_array[i]);
4625 return path_array;
4628 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4630 time_t t;
4631 struct tm *tm;
4633 if (nt == 0) {
4634 return talloc_strdup(mem_ctx, "01/01/1601");
4637 t = nt_time_to_unix(nt);
4638 tm = localtime(&t);
4640 return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4641 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4644 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4646 return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4647 (unsigned)((v >> 48) & 0xFFFF),
4648 (unsigned)((v >> 32) & 0xFFFF),
4649 (unsigned)((v >> 16) & 0xFFFF),
4650 (unsigned)(v & 0xFFFF));
4653 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4654 struct dcerpc_binding_handle *b,
4655 struct policy_handle *handle,
4656 const char *printer_name,
4657 const char *driver_name,
4658 const char *environment,
4659 enum spoolss_DriverOSVersion version,
4660 struct dcerpc_binding_handle *winreg_handle,
4661 struct policy_handle *hive_handle,
4662 const char *server_name_slash)
4664 WERROR result;
4665 union spoolss_DriverInfo info;
4666 const char *driver_key;
4667 struct policy_handle key_handle;
4669 const char *driver_path;
4670 const char *data_file;
4671 const char *config_file;
4672 const char *help_file;
4673 const char **dependent_files;
4675 const char *driver_date;
4676 const char *inbox_driver_date;
4678 const char *driver_version;
4679 const char *inbox_driver_version;
4681 torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4683 driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4684 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4685 environment,
4686 version,
4687 driver_name);
4689 torture_assert(tctx,
4690 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4691 "failed to open driver key");
4693 if (torture_setting_bool(tctx, "samba3", false) ||
4694 torture_setting_bool(tctx, "w2k3", false)) {
4695 goto try_level6;
4698 if (handle) {
4699 torture_assert(tctx,
4700 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
4701 "failed to get driver info level 8");
4702 } else {
4703 torture_assert(tctx,
4704 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
4705 "failed to get driver info level 8");
4708 if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4709 goto try_level6;
4712 driver_path = strip_path(info.info8.driver_path);
4713 data_file = strip_path(info.info8.data_file);
4714 config_file = strip_path(info.info8.config_file);
4715 help_file = strip_path(info.info8.help_file);
4716 dependent_files = strip_paths(info.info8.dependent_files);
4718 driver_date = driver_winreg_date(tctx, info.info8.driver_date);
4719 inbox_driver_date = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
4721 driver_version = driver_winreg_version(tctx, info.info8.driver_version);
4722 inbox_driver_version = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
4724 test_sz("Configuration File", config_file);
4725 test_sz("Data File", data_file);
4726 test_sz("Datatype", info.info8.default_datatype);
4727 test_sz("Driver", driver_path);
4728 test_sz("DriverDate", driver_date);
4729 test_sz("DriverVersion", driver_version);
4730 test_sz("HardwareID", info.info8.hardware_id);
4731 test_sz("Help File", help_file);
4732 test_sz("InfPath", info.info8.inf_path);
4733 test_sz("Manufacturer", info.info8.manufacturer_name);
4734 test_sz("MinInboxDriverVerDate", inbox_driver_date);
4735 test_sz("MinInboxDriverVerVersion", inbox_driver_version);
4736 test_sz("Monitor", info.info8.monitor_name);
4737 test_sz("OEM URL", info.info8.manufacturer_url);
4738 test_sz("Print Processor", info.info8.print_processor);
4739 test_sz("Provider", info.info8.provider);
4740 test_sz("VendorSetup", info.info8.vendor_setup);
4741 test_multi_sz("ColorProfiles", info.info8.color_profiles);
4742 test_multi_sz("Dependent Files", dependent_files);
4743 test_multi_sz("CoreDependencies", info.info8.core_driver_dependencies);
4744 test_multi_sz("Previous Names", info.info8.previous_names);
4745 /* test_dword("Attributes", ?); */
4746 test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
4747 test_dword("Version", info.info8.version);
4748 /* test_dword("TempDir", ?); */
4750 try_level6:
4752 if (handle) {
4753 torture_assert(tctx,
4754 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
4755 "failed to get driver info level 6");
4756 } else {
4757 torture_assert(tctx,
4758 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
4759 "failed to get driver info level 6");
4762 driver_path = strip_path(info.info6.driver_path);
4763 data_file = strip_path(info.info6.data_file);
4764 config_file = strip_path(info.info6.config_file);
4765 help_file = strip_path(info.info6.help_file);
4766 dependent_files = strip_paths(info.info6.dependent_files);
4768 driver_date = driver_winreg_date(tctx, info.info6.driver_date);
4770 driver_version = driver_winreg_version(tctx, info.info6.driver_version);
4772 test_sz("Configuration File", config_file);
4773 test_sz("Data File", data_file);
4774 test_sz("Datatype", info.info6.default_datatype);
4775 test_sz("Driver", driver_path);
4776 if (torture_setting_bool(tctx, "w2k3", false)) {
4777 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
4778 push_nttime(blob.data, 0, info.info6.driver_date);
4779 test_binary("DriverDate", blob);
4780 SBVAL(blob.data, 0, info.info6.driver_version);
4781 test_binary("DriverVersion", blob);
4782 } else {
4783 test_sz("DriverDate", driver_date);
4784 test_sz("DriverVersion", driver_version);
4786 test_sz("HardwareID", info.info6.hardware_id);
4787 test_sz("Help File", help_file);
4788 test_sz("Manufacturer", info.info6.manufacturer_name);
4789 test_sz("Monitor", info.info6.monitor_name);
4790 test_sz("OEM URL", info.info6.manufacturer_url);
4791 test_sz("Provider", info.info6.provider);
4792 test_multi_sz("Dependent Files", dependent_files);
4793 test_multi_sz("Previous Names", info.info6.previous_names);
4794 /* test_dword("Attributes", ?); */
4795 test_dword("Version", info.info6.version);
4796 /* test_dword("TempDir", ?); */
4798 if (handle) {
4799 torture_assert(tctx,
4800 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
4801 "failed to get driver info level 3");
4802 } else {
4803 torture_assert(tctx,
4804 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
4805 "failed to get driver info level 3");
4808 driver_path = strip_path(info.info3.driver_path);
4809 data_file = strip_path(info.info3.data_file);
4810 config_file = strip_path(info.info3.config_file);
4811 help_file = strip_path(info.info3.help_file);
4812 dependent_files = strip_paths(info.info3.dependent_files);
4814 test_sz("Configuration File", config_file);
4815 test_sz("Data File", data_file);
4816 test_sz("Datatype", info.info3.default_datatype);
4817 test_sz("Driver", driver_path);
4818 test_sz("Help File", help_file);
4819 test_sz("Monitor", info.info3.monitor_name);
4820 test_multi_sz("Dependent Files", dependent_files);
4821 /* test_dword("Attributes", ?); */
4822 test_dword("Version", info.info3.version);
4823 /* test_dword("TempDir", ?); */
4826 torture_assert(tctx,
4827 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4829 torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
4831 return true;
4834 #undef test_sz
4835 #undef test_dword
4837 static bool test_SetPrinterData(struct torture_context *tctx,
4838 struct dcerpc_binding_handle *b,
4839 struct policy_handle *handle,
4840 const char *value_name,
4841 enum winreg_Type type,
4842 uint8_t *data,
4843 uint32_t offered)
4845 struct spoolss_SetPrinterData r;
4847 r.in.handle = handle;
4848 r.in.value_name = value_name;
4849 r.in.type = type;
4850 r.in.data = data;
4851 r.in.offered = offered;
4853 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
4854 r.in.value_name);
4856 torture_assert_ntstatus_ok(tctx,
4857 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
4858 "SetPrinterData failed");
4859 torture_assert_werr_ok(tctx, r.out.result,
4860 "SetPrinterData failed");
4862 return true;
4865 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
4866 struct dcerpc_binding_handle *b,
4867 struct policy_handle *handle,
4868 const char *printer_name,
4869 struct dcerpc_binding_handle *winreg_handle,
4870 struct policy_handle *hive_handle)
4872 const char *values[] = {
4873 "spootyfoot",
4874 "spooty\\foot",
4875 #if 0
4876 /* FIXME: not working with s3 atm. */
4877 "spooty,foot",
4878 "spooty,fo,ot",
4879 #endif
4880 "spooty foot",
4881 #if 0
4882 /* FIXME: not working with s3 atm. */
4883 "spooty\\fo,ot",
4884 "spooty,fo\\ot"
4885 #endif
4887 int i;
4889 for (i=0; i < ARRAY_SIZE(values); i++) {
4891 enum winreg_Type type, expected_type = REG_SZ;
4892 DATA_BLOB blob;
4893 uint8_t *data;
4894 uint32_t needed;
4896 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
4897 type = REG_SZ;
4899 torture_assert(tctx,
4900 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
4901 "SetPrinterData failed");
4903 torture_assert(tctx,
4904 test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
4905 "GetPrinterData failed");
4907 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
4908 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
4909 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
4911 if (winreg_handle && hive_handle) {
4913 enum winreg_Type w_type;
4914 uint32_t w_size;
4915 uint32_t w_length;
4916 uint8_t *w_data;
4918 torture_assert(tctx,
4919 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4920 printer_name, "PrinterDriverData", values[i],
4921 &w_type, &w_size, &w_length, &w_data), "");
4923 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
4924 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
4925 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
4926 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
4929 torture_assert(tctx,
4930 test_DeletePrinterData(tctx, b, handle, values[i]),
4931 "DeletePrinterData failed");
4934 return true;
4938 static bool test_EnumPrinterKey(struct torture_context *tctx,
4939 struct dcerpc_binding_handle *b,
4940 struct policy_handle *handle,
4941 const char *key_name,
4942 const char ***array);
4944 static bool test_SetPrinterDataEx(struct torture_context *tctx,
4945 struct dcerpc_binding_handle *b,
4946 struct policy_handle *handle,
4947 const char *key_name,
4948 const char *value_name,
4949 enum winreg_Type type,
4950 uint8_t *data,
4951 uint32_t offered)
4953 NTSTATUS status;
4954 struct spoolss_SetPrinterDataEx r;
4956 r.in.handle = handle;
4957 r.in.key_name = key_name;
4958 r.in.value_name = value_name;
4959 r.in.type = type;
4960 r.in.data = data;
4961 r.in.offered = offered;
4963 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
4964 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
4966 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
4968 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
4969 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
4971 return true;
4974 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
4975 struct dcerpc_pipe *p,
4976 struct policy_handle *handle)
4978 struct dcerpc_binding_handle *b = p->binding_handle;
4979 const char *value_name = "dog";
4980 const char *keys[] = {
4981 "torturedataex",
4982 "torture data ex",
4983 "torturedataex_with_subkey\\subkey",
4984 "torturedataex_with_subkey\\subkey:0",
4985 "torturedataex_with_subkey\\subkey:1",
4986 "torturedataex_with_subkey\\subkey\\subsubkey",
4987 "torturedataex_with_subkey\\subkey\\subsubkey:0",
4988 "torturedataex_with_subkey\\subkey\\subsubkey:1",
4989 "torture,data",
4990 "torture,data,ex",
4991 "torture,data\\ex",
4992 "torture\\data,ex",
4993 "torture/data",
4994 "torture/data ex",
4995 "torture/data ex/sub",
4996 "torture//data",
4997 "torture//data ex",
4998 "torture//data ex/sub",
4999 "torture//data ex//sub",
5001 int i;
5003 for (i=0; i < ARRAY_SIZE(keys); i++) {
5005 char *c;
5006 const char *key;
5007 enum winreg_Type type;
5008 DATA_BLOB blob_in, blob_out;
5009 const char **subkeys;
5010 uint32_t ecount;
5011 struct spoolss_PrinterEnumValues *einfo;
5012 uint32_t needed;
5014 blob_in = data_blob_talloc(tctx, NULL, 42);
5016 generate_random_buffer(blob_in.data, blob_in.length);
5018 torture_assert(tctx,
5019 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
5020 "failed to call SetPrinterDataEx");
5022 torture_assert(tctx,
5023 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
5024 "failed to call GetPrinterDataEx");
5026 blob_out.length = needed;
5027 torture_assert(tctx,
5028 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
5029 "failed to call EnumPrinterDataEx");
5031 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5032 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5033 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5035 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5036 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5037 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5038 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5039 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5040 if (einfo[0].data_length > 0) {
5041 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5044 key = talloc_strdup(tctx, keys[i]);
5046 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
5047 return false;
5050 c = strchr(key, '\\');
5051 if (c) {
5052 int k;
5054 /* we have subkeys */
5056 *c = 0;
5058 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
5059 return false;
5062 for (k=0; subkeys && subkeys[k]; k++) {
5064 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
5066 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
5067 return false;
5071 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5072 return false;
5075 } else {
5076 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5077 return false;
5082 return true;
5085 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
5086 struct dcerpc_pipe *p,
5087 struct policy_handle *handle)
5089 struct dcerpc_binding_handle *b = p->binding_handle;
5090 const char *key = "torturedataex";
5091 const char *values[] = {
5092 "torture_value",
5093 "torture value",
5094 "torture,value",
5095 "torture/value",
5096 "torture\\value",
5097 "torture\\\\value"
5099 int i;
5101 for (i=0; i < ARRAY_SIZE(values); i++) {
5103 enum winreg_Type type;
5104 DATA_BLOB blob_in, blob_out;
5105 uint32_t ecount;
5106 struct spoolss_PrinterEnumValues *einfo;
5107 uint32_t needed;
5109 if (torture_setting_bool(tctx, "samba3", false)) {
5110 char *q;
5111 q = strrchr(values[i], ',');
5112 if (q) {
5113 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
5114 values[i]);
5115 continue;
5119 blob_in = data_blob_talloc(tctx, NULL, 42);
5121 generate_random_buffer(blob_in.data, blob_in.length);
5123 torture_assert(tctx,
5124 test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
5125 "failed to call SetPrinterDataEx");
5127 torture_assert(tctx,
5128 test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
5129 "failed to call GetPrinterDataEx");
5131 blob_out.length = needed;
5132 torture_assert(tctx,
5133 test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
5134 "failed to call EnumPrinterDataEx");
5136 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5137 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5138 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5140 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5141 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5142 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5143 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5144 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5145 if (einfo[0].data_length > 0) {
5146 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5149 torture_assert(tctx,
5150 test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5151 "failed to call DeletePrinterDataEx");
5154 return true;
5158 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5159 struct dcerpc_pipe *p,
5160 struct policy_handle *handle,
5161 const char *printername,
5162 struct dcerpc_binding_handle *winreg_handle,
5163 struct policy_handle *hive_handle)
5165 struct dcerpc_binding_handle *b = p->binding_handle;
5166 const char *value_name = "dog";
5167 const char *key_name = "torturedataex";
5168 enum winreg_Type types[] = {
5169 REG_SZ,
5170 REG_MULTI_SZ,
5171 REG_DWORD,
5172 REG_BINARY
5174 const char *str = "abcdefghi";
5175 int t, s;
5177 for (t=0; t < ARRAY_SIZE(types); t++) {
5178 for (s=0; s < strlen(str); s++) {
5180 enum winreg_Type type;
5181 const char *string = talloc_strndup(tctx, str, s);
5182 const char *array[2];
5183 DATA_BLOB blob = data_blob_string_const(string);
5184 DATA_BLOB data;
5185 uint8_t *data_out;
5186 uint32_t needed, offered = 0;
5187 uint32_t ecount;
5188 struct spoolss_PrinterEnumValues *einfo;
5190 array[0] = talloc_strdup(tctx, string);
5191 array[1] = NULL;
5193 if (types[t] == REG_DWORD) {
5194 s = 0xffff;
5197 switch (types[t]) {
5198 case REG_BINARY:
5199 data = blob;
5200 offered = blob.length;
5201 break;
5202 case REG_DWORD:
5203 data = data_blob_talloc(tctx, NULL, 4);
5204 SIVAL(data.data, 0, 0x12345678);
5205 offered = 4;
5206 break;
5207 case REG_SZ:
5208 torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5209 type = REG_SZ;
5210 offered = data.length;
5211 /*strlen_m_term(data.string)*2;*/
5212 break;
5213 case REG_MULTI_SZ:
5214 torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5215 type = REG_MULTI_SZ;
5216 offered = data.length;
5217 break;
5218 default:
5219 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5222 torture_assert(tctx,
5223 test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5224 "failed to call SetPrinterDataEx");
5226 torture_assert(tctx,
5227 test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
5228 "failed to call GetPrinterDataEx");
5230 torture_assert(tctx,
5231 test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5232 "failed to call EnumPrinterDataEx");
5234 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5235 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5236 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5238 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5239 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5240 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5241 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5242 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5243 if (einfo[0].data_length > 0) {
5244 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5247 if (winreg_handle && hive_handle) {
5248 enum winreg_Type w_type;
5249 uint32_t w_size;
5250 uint32_t w_length;
5251 uint8_t *w_data;
5253 torture_assert(tctx,
5254 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5255 printername, key_name, value_name,
5256 &w_type, &w_size, &w_length, &w_data), "");
5258 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5259 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5260 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5261 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5264 torture_assert(tctx,
5265 test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5266 "failed to call DeletePrinterDataEx");
5270 return true;
5273 static bool test_PrinterData_winreg(struct torture_context *tctx,
5274 struct dcerpc_pipe *p,
5275 struct policy_handle *handle,
5276 const char *printer_name)
5278 struct dcerpc_binding_handle *b = p->binding_handle;
5279 struct dcerpc_pipe *p2;
5280 bool ret = true;
5281 struct policy_handle hive_handle;
5282 struct dcerpc_binding_handle *b2;
5284 torture_assert_ntstatus_ok(tctx,
5285 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5286 "could not open winreg pipe");
5287 b2 = p2->binding_handle;
5289 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5291 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5292 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5294 test_winreg_CloseKey(tctx, b2, &hive_handle);
5296 talloc_free(p2);
5298 return ret;
5301 static bool test_Forms_winreg(struct torture_context *tctx,
5302 struct dcerpc_binding_handle *b,
5303 struct policy_handle *handle,
5304 bool print_server,
5305 const char *printer_name)
5307 struct dcerpc_pipe *p2;
5308 bool ret = true;
5309 struct policy_handle hive_handle;
5310 struct dcerpc_binding_handle *b2;
5312 torture_assert_ntstatus_ok(tctx,
5313 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5314 "could not open winreg pipe");
5315 b2 = p2->binding_handle;
5317 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5319 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5321 test_winreg_CloseKey(tctx, b2, &hive_handle);
5323 talloc_free(p2);
5325 return ret;
5328 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5329 struct dcerpc_pipe *p,
5330 struct policy_handle *handle,
5331 const char *printer_name)
5333 struct dcerpc_binding_handle *b = p->binding_handle;
5334 struct dcerpc_pipe *p2;
5335 bool ret = true;
5336 struct policy_handle hive_handle;
5337 struct dcerpc_binding_handle *b2;
5339 torture_assert_ntstatus_ok(tctx,
5340 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5341 "could not open winreg pipe");
5342 b2 = p2->binding_handle;
5344 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5346 ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5348 test_winreg_CloseKey(tctx, b2, &hive_handle);
5350 talloc_free(p2);
5352 return ret;
5355 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5356 struct dcerpc_pipe *p,
5357 struct policy_handle *handle,
5358 const char *printer_name,
5359 const char *driver_name,
5360 const char *environment,
5361 enum spoolss_DriverOSVersion version)
5363 struct dcerpc_binding_handle *b = p->binding_handle;
5364 struct dcerpc_pipe *p2;
5365 bool ret = true;
5366 struct policy_handle hive_handle;
5367 struct dcerpc_binding_handle *b2;
5369 torture_assert_ntstatus_ok(tctx,
5370 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5371 "could not open winreg pipe");
5372 b2 = p2->binding_handle;
5374 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5376 ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
5378 test_winreg_CloseKey(tctx, b2, &hive_handle);
5380 talloc_free(p2);
5382 return ret;
5385 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5386 struct dcerpc_binding_handle *b,
5387 const char *environment)
5389 struct dcerpc_pipe *p2;
5390 bool ret = true;
5391 struct policy_handle hive_handle;
5392 struct dcerpc_binding_handle *b2;
5394 torture_assert_ntstatus_ok(tctx,
5395 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5396 "could not open winreg pipe");
5397 b2 = p2->binding_handle;
5399 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5401 ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5403 test_winreg_CloseKey(tctx, b2, &hive_handle);
5405 talloc_free(p2);
5407 return ret;
5410 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5411 struct dcerpc_pipe *p,
5412 struct policy_handle *handle,
5413 const char *printer_name)
5415 struct spoolss_SetPrinterInfoCtr info_ctr;
5416 struct spoolss_DevmodeContainer devmode_ctr;
5417 struct sec_desc_buf secdesc_ctr;
5418 union spoolss_SetPrinterInfo sinfo;
5419 union spoolss_PrinterInfo info;
5420 struct dcerpc_binding_handle *b = p->binding_handle;
5421 const char *pname;
5423 ZERO_STRUCT(info_ctr);
5424 ZERO_STRUCT(devmode_ctr);
5425 ZERO_STRUCT(secdesc_ctr);
5427 torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5429 torture_assert(tctx,
5430 test_GetPrinter_level(tctx, b, handle, 2, &info),
5431 "failed to query Printer level 2");
5433 torture_assert(tctx,
5434 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5435 "failed to convert");
5437 info_ctr.level = 2;
5438 info_ctr.info = sinfo;
5440 #define TEST_SZ(wname, iname) \
5441 do {\
5442 enum winreg_Type type;\
5443 uint8_t *data;\
5444 uint32_t needed;\
5445 DATA_BLOB blob;\
5446 const char *str;\
5447 torture_assert(tctx,\
5448 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5449 "failed to query");\
5450 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5451 blob = data_blob_const(data, needed);\
5452 torture_assert(tctx,\
5453 pull_reg_sz(tctx, &blob, &str),\
5454 "failed to pull REG_SZ");\
5455 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5456 } while(0);
5459 #define TEST_SET_SZ(wname, iname, val) \
5460 do {\
5461 enum winreg_Type type;\
5462 uint8_t *data;\
5463 uint32_t needed;\
5464 DATA_BLOB blob;\
5465 const char *str;\
5466 sinfo.info2->iname = val;\
5467 torture_assert(tctx,\
5468 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5469 "failed to call SetPrinter");\
5470 torture_assert(tctx,\
5471 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5472 "failed to query");\
5473 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5474 blob = data_blob_const(data, needed);\
5475 torture_assert(tctx,\
5476 pull_reg_sz(tctx, &blob, &str),\
5477 "failed to pull REG_SZ");\
5478 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5479 } while(0);
5481 #define TEST_SET_DWORD(wname, iname, val) \
5482 do {\
5483 enum winreg_Type type;\
5484 uint8_t *data;\
5485 uint32_t needed;\
5486 uint32_t value;\
5487 sinfo.info2->iname = val;\
5488 torture_assert(tctx,\
5489 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5490 "failed to call SetPrinter");\
5491 torture_assert(tctx,\
5492 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5493 "failed to query");\
5494 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5495 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5496 value = IVAL(data, 0); \
5497 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5498 } while(0);
5500 TEST_SET_SZ("description", comment, "newval");
5501 TEST_SET_SZ("location", location, "newval");
5502 /* TEST_SET_DWORD("priority", priority, 25); */
5504 torture_assert(tctx,
5505 test_GetPrinter_level(tctx, b, handle, 2, &info),
5506 "failed to query Printer level 2");
5508 TEST_SZ("description", info.info2.comment);
5509 TEST_SZ("driverName", info.info2.drivername);
5510 TEST_SZ("location", info.info2.location);
5512 pname = strrchr(info.info2.printername, '\\');
5513 if (pname == NULL) {
5514 pname = info.info2.printername;
5515 } else {
5516 pname++;
5518 TEST_SZ("printerName", pname);
5519 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5520 /* TEST_SZ("printShareName", info.info2.sharename); */
5522 /* FIXME gd: complete the list */
5524 #undef TEST_SZ
5525 #undef TEST_SET_SZ
5526 #undef TEST_DWORD
5528 torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5530 return true;
5533 static bool test_print_processors_winreg(struct torture_context *tctx,
5534 void *private_data)
5536 struct test_spoolss_context *ctx =
5537 talloc_get_type_abort(private_data, struct test_spoolss_context);
5538 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5539 struct dcerpc_binding_handle *b = p->binding_handle;
5541 return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5544 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5545 struct dcerpc_binding_handle *b,
5546 struct policy_handle *handle,
5547 uint32_t *change_id)
5549 enum winreg_Type type;
5550 uint8_t *data;
5551 uint32_t needed;
5553 torture_assert(tctx,
5554 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5555 "failed to call GetPrinterData");
5557 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5558 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5560 *change_id = IVAL(data, 0);
5562 return true;
5565 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5566 struct dcerpc_pipe *p,
5567 struct policy_handle *handle,
5568 uint32_t *change_id)
5570 enum winreg_Type type;
5571 uint8_t *data;
5572 uint32_t needed;
5574 torture_assert(tctx,
5575 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5576 "failed to call GetPrinterData");
5578 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5579 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5581 *change_id = IVAL(data, 0);
5583 return true;
5586 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5587 struct dcerpc_binding_handle *b,
5588 struct policy_handle *handle,
5589 uint32_t *change_id)
5591 union spoolss_PrinterInfo info;
5593 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5594 "failed to query Printer level 0");
5596 *change_id = info.info0.change_id;
5598 return true;
5601 static bool test_ChangeID(struct torture_context *tctx,
5602 struct dcerpc_pipe *p,
5603 struct policy_handle *handle)
5605 uint32_t change_id, change_id_ex, change_id_info;
5606 uint32_t change_id2, change_id_ex2, change_id_info2;
5607 union spoolss_PrinterInfo info;
5608 const char *comment;
5609 struct dcerpc_binding_handle *b = p->binding_handle;
5611 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5613 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5614 "failed to query for ChangeID");
5615 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5616 "failed to query for ChangeID");
5617 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5618 "failed to query for ChangeID");
5620 torture_assert_int_equal(tctx, change_id, change_id_ex,
5621 "change_ids should all be equal");
5622 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5623 "change_ids should all be equal");
5626 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
5628 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5629 "failed to query for ChangeID");
5630 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5631 "failed to query Printer level 2");
5632 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5633 "failed to query for ChangeID");
5634 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5635 "failed to query for ChangeID");
5636 torture_assert_int_equal(tctx, change_id, change_id_ex,
5637 "change_id should not have changed");
5638 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5639 "change_id should not have changed");
5642 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
5644 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5645 "failed to query for ChangeID");
5646 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5647 "failed to query for ChangeID");
5648 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5649 "failed to query for ChangeID");
5650 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5651 "failed to query Printer level 2");
5652 comment = talloc_strdup(tctx, info.info2.comment);
5655 struct spoolss_SetPrinterInfoCtr info_ctr;
5656 struct spoolss_DevmodeContainer devmode_ctr;
5657 struct sec_desc_buf secdesc_ctr;
5658 union spoolss_SetPrinterInfo sinfo;
5660 ZERO_STRUCT(info_ctr);
5661 ZERO_STRUCT(devmode_ctr);
5662 ZERO_STRUCT(secdesc_ctr);
5665 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5666 sinfo.info2->comment = "torture_comment";
5668 info_ctr.level = 2;
5669 info_ctr.info = sinfo;
5671 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5672 "failed to call SetPrinter");
5674 sinfo.info2->comment = comment;
5676 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5677 "failed to call SetPrinter");
5681 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5682 "failed to query for ChangeID");
5683 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5684 "failed to query for ChangeID");
5685 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5686 "failed to query for ChangeID");
5688 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5689 "change_ids should all be equal");
5690 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5691 "change_ids should all be equal");
5693 torture_assert(tctx, (change_id < change_id2),
5694 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5695 change_id2, change_id));
5696 torture_assert(tctx, (change_id_ex < change_id_ex2),
5697 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5698 change_id_ex2, change_id_ex));
5699 torture_assert(tctx, (change_id_info < change_id_info2),
5700 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5701 change_id_info2, change_id_info));
5703 torture_comment(tctx, "ChangeID tests succeeded\n\n");
5705 return true;
5708 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5709 struct dcerpc_pipe *p,
5710 struct policy_handle *handle)
5712 NTSTATUS status;
5713 struct dcerpc_binding *b;
5714 struct dcerpc_pipe *p2;
5715 struct spoolss_ClosePrinter cp;
5717 /* only makes sense on SMB */
5718 if (p->conn->transport.transport != NCACN_NP) {
5719 return true;
5722 torture_comment(tctx, "Testing close on secondary pipe\n");
5724 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
5725 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
5727 status = dcerpc_secondary_connection(p, &p2, b);
5728 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
5730 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
5731 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
5733 cp.in.handle = handle;
5734 cp.out.handle = handle;
5736 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
5737 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
5738 "ERROR: Allowed close on secondary connection");
5740 talloc_free(p2);
5742 return true;
5745 static bool test_OpenPrinter_badname(struct torture_context *tctx,
5746 struct dcerpc_binding_handle *b, const char *name)
5748 NTSTATUS status;
5749 struct spoolss_OpenPrinter op;
5750 struct spoolss_OpenPrinterEx opEx;
5751 struct policy_handle handle;
5752 bool ret = true;
5754 op.in.printername = name;
5755 op.in.datatype = NULL;
5756 op.in.devmode_ctr.devmode= NULL;
5757 op.in.access_mask = 0;
5758 op.out.handle = &handle;
5760 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
5762 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
5763 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5764 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
5765 "unexpected result");
5767 if (W_ERROR_IS_OK(op.out.result)) {
5768 ret &=test_ClosePrinter(tctx, b, &handle);
5771 opEx.in.printername = name;
5772 opEx.in.datatype = NULL;
5773 opEx.in.devmode_ctr.devmode = NULL;
5774 opEx.in.access_mask = 0;
5775 opEx.in.level = 1;
5776 opEx.in.userlevel.level1 = NULL;
5777 opEx.out.handle = &handle;
5779 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
5781 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
5782 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5783 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
5784 "unexpected result");
5786 if (W_ERROR_IS_OK(opEx.out.result)) {
5787 ret &=test_ClosePrinter(tctx, b, &handle);
5790 return ret;
5793 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
5794 void *private_data)
5796 struct test_spoolss_context *ctx =
5797 talloc_get_type_abort(private_data, struct test_spoolss_context);
5799 const char *badnames[] = {
5800 "__INVALID_PRINTER__",
5801 "\\\\__INVALID_HOST__",
5803 "\\\\\\",
5804 "\\\\\\__INVALID_PRINTER__"
5806 const char *badname;
5807 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5808 const char *server_name = dcerpc_server_name(p);
5809 struct dcerpc_binding_handle *b = p->binding_handle;
5810 int i;
5812 for (i=0; i < ARRAY_SIZE(badnames); i++) {
5813 torture_assert(tctx,
5814 test_OpenPrinter_badname(tctx, b, badnames[i]),
5815 "");
5818 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
5819 torture_assert(tctx,
5820 test_OpenPrinter_badname(tctx, b, badname),
5821 "");
5823 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
5824 torture_assert(tctx,
5825 test_OpenPrinter_badname(tctx, b, badname),
5826 "");
5828 return true;
5831 static bool test_OpenPrinter(struct torture_context *tctx,
5832 struct dcerpc_pipe *p,
5833 const char *name,
5834 const char *environment,
5835 bool open_only)
5837 NTSTATUS status;
5838 struct spoolss_OpenPrinter r;
5839 struct policy_handle handle;
5840 bool ret = true;
5841 struct dcerpc_binding_handle *b = p->binding_handle;
5843 r.in.printername = name;
5844 r.in.datatype = NULL;
5845 r.in.devmode_ctr.devmode= NULL;
5846 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5847 r.out.handle = &handle;
5849 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5851 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5853 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5855 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5857 if (open_only) {
5858 goto close_printer;
5861 if (!test_GetPrinter(tctx, b, &handle, environment)) {
5862 ret = false;
5865 if (!torture_setting_bool(tctx, "samba3", false)) {
5866 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5867 ret = false;
5871 close_printer:
5872 if (!test_ClosePrinter(tctx, b, &handle)) {
5873 ret = false;
5876 return ret;
5879 static bool test_OpenPrinterEx(struct torture_context *tctx,
5880 struct dcerpc_binding_handle *b,
5881 const char *printername,
5882 const char *datatype,
5883 struct spoolss_DeviceMode *devmode,
5884 uint32_t access_mask,
5885 uint32_t level,
5886 union spoolss_UserLevel *userlevel,
5887 struct policy_handle *handle,
5888 WERROR expected_result)
5890 struct spoolss_OpenPrinterEx r;
5892 r.in.printername = printername;
5893 r.in.datatype = datatype;
5894 r.in.devmode_ctr.devmode= devmode;
5895 r.in.access_mask = access_mask;
5896 r.in.level = level;
5897 r.in.userlevel = *userlevel;
5898 r.out.handle = handle;
5900 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5902 torture_assert_ntstatus_ok(tctx,
5903 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
5904 "OpenPrinterEx failed");
5906 torture_assert_werr_equal(tctx, r.out.result, expected_result,
5907 "OpenPrinterEx failed");
5909 return true;
5912 static bool call_OpenPrinterEx(struct torture_context *tctx,
5913 struct dcerpc_pipe *p,
5914 const char *name,
5915 struct spoolss_DeviceMode *devmode,
5916 struct policy_handle *handle)
5918 union spoolss_UserLevel userlevel;
5919 struct spoolss_UserLevel1 userlevel1;
5920 struct dcerpc_binding_handle *b = p->binding_handle;
5922 userlevel1.size = 1234;
5923 userlevel1.client = "hello";
5924 userlevel1.user = "spottyfoot!";
5925 userlevel1.build = 1;
5926 userlevel1.major = 2;
5927 userlevel1.minor = 3;
5928 userlevel1.processor = 4;
5930 userlevel.level1 = &userlevel1;
5932 return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
5933 SEC_FLAG_MAXIMUM_ALLOWED,
5935 &userlevel,
5936 handle,
5937 WERR_OK);
5940 static bool test_printer_rename(struct torture_context *tctx,
5941 void *private_data)
5943 struct torture_printer_context *t =
5944 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
5945 struct dcerpc_pipe *p = t->spoolss_pipe;
5947 bool ret = true;
5948 union spoolss_PrinterInfo info;
5949 union spoolss_SetPrinterInfo sinfo;
5950 struct spoolss_SetPrinterInfoCtr info_ctr;
5951 struct spoolss_DevmodeContainer devmode_ctr;
5952 struct sec_desc_buf secdesc_ctr;
5953 const char *printer_name;
5954 const char *printer_name_orig;
5955 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5956 struct policy_handle new_handle;
5957 const char *q;
5958 struct dcerpc_binding_handle *b = p->binding_handle;
5960 ZERO_STRUCT(devmode_ctr);
5961 ZERO_STRUCT(secdesc_ctr);
5963 torture_comment(tctx, "Testing Printer rename operations\n");
5965 torture_assert(tctx,
5966 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5967 "failed to call GetPrinter level 2");
5969 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5971 q = strrchr(info.info2.printername, '\\');
5972 if (q) {
5973 torture_warning(tctx,
5974 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5977 torture_assert(tctx,
5978 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5980 sinfo.info2->printername = printer_name_new;
5982 info_ctr.level = 2;
5983 info_ctr.info = sinfo;
5985 torture_assert(tctx,
5986 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5987 "failed to call SetPrinter level 2");
5989 torture_assert(tctx,
5990 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5991 "failed to call GetPrinter level 2");
5993 printer_name = talloc_strdup(tctx, info.info2.printername);
5995 q = strrchr(info.info2.printername, '\\');
5996 if (q) {
5997 torture_warning(tctx,
5998 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5999 q++;
6000 printer_name = q;
6003 torture_assert_str_equal(tctx, printer_name, printer_name_new,
6004 "new printer name was not set");
6006 /* samba currently cannot fully rename printers */
6007 if (!torture_setting_bool(tctx, "samba3", false)) {
6008 torture_assert(tctx,
6009 test_OpenPrinter_badname(tctx, b, printer_name_orig),
6010 "still can open printer with oldname after rename");
6011 } else {
6012 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
6015 torture_assert(tctx,
6016 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
6017 "failed to open printer with new name");
6019 torture_assert(tctx,
6020 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
6021 "failed to call GetPrinter level 2");
6023 torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
6024 "new printer name was not set");
6026 torture_assert(tctx,
6027 test_ClosePrinter(tctx, b, &new_handle),
6028 "failed to close printer");
6030 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
6032 return ret;
6035 static bool test_openprinter(struct torture_context *tctx,
6036 struct dcerpc_binding_handle *b,
6037 const char *real_printername)
6039 union spoolss_UserLevel userlevel;
6040 struct policy_handle handle;
6041 struct spoolss_UserLevel1 userlevel1;
6042 const char *printername = NULL;
6043 int i;
6045 struct {
6046 const char *suffix;
6047 WERROR expected_result;
6048 } tests[] = {
6050 .suffix = "rubbish",
6051 .expected_result = WERR_INVALID_PRINTER_NAME
6053 .suffix = ", LocalOnl",
6054 .expected_result = WERR_INVALID_PRINTER_NAME
6056 .suffix = ", localOnly",
6057 .expected_result = WERR_INVALID_PRINTER_NAME
6059 .suffix = ", localonl",
6060 .expected_result = WERR_INVALID_PRINTER_NAME
6062 .suffix = ",LocalOnl",
6063 .expected_result = WERR_INVALID_PRINTER_NAME
6065 .suffix = ",localOnl2",
6066 .expected_result = WERR_INVALID_PRINTER_NAME
6068 .suffix = ", DrvConver2t",
6069 .expected_result = WERR_INVALID_PRINTER_NAME
6071 .suffix = ", drvconvert",
6072 .expected_result = WERR_INVALID_PRINTER_NAME
6074 .suffix = ",drvconvert",
6075 .expected_result = WERR_INVALID_PRINTER_NAME
6077 .suffix = ", DrvConvert",
6078 .expected_result = WERR_OK
6080 .suffix = " , DrvConvert",
6081 .expected_result = WERR_INVALID_PRINTER_NAME
6083 .suffix = ",DrvConvert",
6084 .expected_result = WERR_OK
6086 .suffix = ", DrvConvertsadfasdf",
6087 .expected_result = WERR_OK
6089 .suffix = ",DrvConvertasdfasd",
6090 .expected_result = WERR_OK
6092 .suffix = ", LocalOnly",
6093 .expected_result = WERR_OK
6095 .suffix = " , LocalOnly",
6096 .expected_result = WERR_INVALID_PRINTER_NAME
6098 .suffix = ",LocalOnly",
6099 .expected_result = WERR_OK
6101 .suffix = ", LocalOnlysagi4gjfkd",
6102 .expected_result = WERR_OK
6104 .suffix = ",LocalOnlysagi4gjfkd",
6105 .expected_result = WERR_OK
6109 userlevel1.size = 1234;
6110 userlevel1.client = "hello";
6111 userlevel1.user = "spottyfoot!";
6112 userlevel1.build = 1;
6113 userlevel1.major = 2;
6114 userlevel1.minor = 3;
6115 userlevel1.processor = 4;
6117 userlevel.level1 = &userlevel1;
6119 torture_comment(tctx, "Testing openprinterex printername pattern\n");
6121 torture_assert(tctx,
6122 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0, 1,
6123 &userlevel, &handle,
6124 WERR_OK),
6125 "OpenPrinterEx failed");
6126 test_ClosePrinter(tctx, b, &handle);
6128 for (i=0; i < ARRAY_SIZE(tests); i++) {
6130 printername = talloc_asprintf(tctx, "%s%s",
6131 real_printername,
6132 tests[i].suffix);
6134 torture_assert(tctx,
6135 test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0, 1,
6136 &userlevel, &handle,
6137 tests[i].expected_result),
6138 "OpenPrinterEx failed");
6139 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6140 test_ClosePrinter(tctx, b, &handle);
6144 return true;
6148 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6149 struct dcerpc_pipe *p,
6150 const char *name,
6151 const char *environment)
6153 struct policy_handle handle;
6154 bool ret = true;
6155 struct dcerpc_binding_handle *b = p->binding_handle;
6157 if (!test_openprinter(tctx, b, name)) {
6158 return false;
6161 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6162 return false;
6165 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6166 ret = false;
6169 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6170 ret = false;
6173 if (!test_EnumForms_all(tctx, b, &handle, false)) {
6174 ret = false;
6177 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6178 ret = false;
6181 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6182 ret = false;
6185 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6186 ret = false;
6189 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6190 ret = false;
6193 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6194 ret = false;
6197 if (!test_printer_all_keys(tctx, b, &handle)) {
6198 ret = false;
6201 if (!test_PausePrinter(tctx, b, &handle)) {
6202 ret = false;
6205 if (!test_DoPrintTest(tctx, b, &handle)) {
6206 ret = false;
6209 if (!test_ResumePrinter(tctx, b, &handle)) {
6210 ret = false;
6213 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
6214 ret = false;
6217 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
6218 ret = false;
6221 if (!torture_setting_bool(tctx, "samba3", false)) {
6222 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6223 ret = false;
6227 if (!test_ClosePrinter(tctx, b, &handle)) {
6228 ret = false;
6231 return ret;
6234 static bool test_EnumPrinters_old(struct torture_context *tctx,
6235 void *private_data)
6237 struct test_spoolss_context *ctx =
6238 talloc_get_type_abort(private_data, struct test_spoolss_context);
6239 struct spoolss_EnumPrinters r;
6240 NTSTATUS status;
6241 uint16_t levels[] = {1, 2, 4, 5};
6242 int i;
6243 bool ret = true;
6244 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6245 struct dcerpc_binding_handle *b = p->binding_handle;
6247 for (i=0;i<ARRAY_SIZE(levels);i++) {
6248 union spoolss_PrinterInfo *info;
6249 int j;
6250 uint32_t needed;
6251 uint32_t count;
6253 r.in.flags = PRINTER_ENUM_LOCAL;
6254 r.in.server = "";
6255 r.in.level = levels[i];
6256 r.in.buffer = NULL;
6257 r.in.offered = 0;
6258 r.out.needed = &needed;
6259 r.out.count = &count;
6260 r.out.info = &info;
6262 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6264 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6265 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6267 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6268 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6269 r.in.buffer = &blob;
6270 r.in.offered = needed;
6271 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6274 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6276 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6278 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6280 if (!info) {
6281 torture_comment(tctx, "No printers returned\n");
6282 return true;
6285 for (j=0;j<count;j++) {
6286 if (r.in.level == 1) {
6287 char *unc = talloc_strdup(tctx, info[j].info1.name);
6288 char *slash, *name, *full_name;
6289 name = unc;
6290 if (unc[0] == '\\' && unc[1] == '\\') {
6291 unc +=2;
6293 slash = strchr(unc, '\\');
6294 if (slash) {
6295 slash++;
6296 name = slash;
6298 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6299 dcerpc_server_name(p), name);
6300 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6301 ret = false;
6303 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6304 ret = false;
6306 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6307 ret = false;
6309 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6310 ret = false;
6316 return ret;
6319 static bool test_EnumPrinters_level(struct torture_context *tctx,
6320 struct dcerpc_binding_handle *b,
6321 uint32_t flags,
6322 const char *servername,
6323 uint32_t level,
6324 uint32_t *count_p,
6325 union spoolss_PrinterInfo **info_p)
6327 struct spoolss_EnumPrinters r;
6328 union spoolss_PrinterInfo *info;
6329 uint32_t needed;
6330 uint32_t count;
6332 r.in.flags = flags;
6333 r.in.server = servername;
6334 r.in.level = level;
6335 r.in.buffer = NULL;
6336 r.in.offered = 0;
6337 r.out.needed = &needed;
6338 r.out.count = &count;
6339 r.out.info = &info;
6341 torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6342 r.in.server, r.in.level);
6344 torture_assert_ntstatus_ok(tctx,
6345 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6346 "EnumPrinters failed");
6347 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6348 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6349 r.in.buffer = &blob;
6350 r.in.offered = needed;
6351 torture_assert_ntstatus_ok(tctx,
6352 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6353 "EnumPrinters failed");
6356 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6358 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6360 if (count_p) {
6361 *count_p = count;
6363 if (info_p) {
6364 *info_p = info;
6367 return true;
6370 static const char *get_short_printername(struct torture_context *tctx,
6371 const char *name)
6373 const char *short_name;
6375 if (name[0] == '\\' && name[1] == '\\') {
6376 name += 2;
6377 short_name = strchr(name, '\\');
6378 if (short_name) {
6379 return talloc_strdup(tctx, short_name+1);
6383 return name;
6386 static const char *get_full_printername(struct torture_context *tctx,
6387 const char *name)
6389 const char *full_name = talloc_strdup(tctx, name);
6390 char *p;
6392 if (name && name[0] == '\\' && name[1] == '\\') {
6393 name += 2;
6394 p = strchr(name, '\\');
6395 if (p) {
6396 return full_name;
6400 return NULL;
6403 static bool test_OnePrinter_servername(struct torture_context *tctx,
6404 struct dcerpc_pipe *p,
6405 struct dcerpc_binding_handle *b,
6406 const char *servername,
6407 const char *printername)
6409 union spoolss_PrinterInfo info;
6410 const char *short_name = get_short_printername(tctx, printername);
6411 const char *full_name = get_full_printername(tctx, printername);
6413 if (short_name) {
6414 struct policy_handle handle;
6415 torture_assert(tctx,
6416 call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
6417 "failed to open printer");
6419 torture_assert(tctx,
6420 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6421 "failed to get printer info");
6423 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
6424 "unexpected servername");
6425 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
6426 "unexpected printername");
6428 if (info.info2.devmode) {
6429 const char *expected_devicename;
6430 expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
6431 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6432 "unexpected devicemode devicename");
6435 torture_assert(tctx,
6436 test_ClosePrinter(tctx, b, &handle),
6437 "failed to close printer");
6440 if (full_name) {
6441 struct policy_handle handle;
6443 torture_assert(tctx,
6444 call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
6445 "failed to open printer");
6447 torture_assert(tctx,
6448 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6449 "failed to get printer info");
6451 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
6452 "unexpected servername");
6453 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
6454 "unexpected printername");
6456 if (info.info2.devmode) {
6457 const char *expected_devicename;
6458 expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
6459 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6460 "unexpected devicemode devicename");
6463 torture_assert(tctx,
6464 test_ClosePrinter(tctx, b, &handle),
6465 "failed to close printer");
6468 return true;
6471 static bool test_EnumPrinters_servername(struct torture_context *tctx,
6472 void *private_data)
6474 struct test_spoolss_context *ctx =
6475 talloc_get_type_abort(private_data, struct test_spoolss_context);
6476 int i;
6477 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6478 struct dcerpc_binding_handle *b = p->binding_handle;
6479 uint32_t count;
6480 union spoolss_PrinterInfo *info;
6481 const char *servername;
6482 uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
6484 torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6486 servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6488 torture_assert(tctx,
6489 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6490 "failed to enumerate printers");
6492 for (i=0; i < count; i++) {
6494 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
6495 "unexpected servername");
6497 torture_assert(tctx,
6498 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6499 "failed to check printer");
6502 servername = "";
6504 torture_assert(tctx,
6505 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6506 "failed to enumerate printers");
6508 for (i=0; i < count; i++) {
6510 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
6511 "unexpected servername");
6513 torture_assert(tctx,
6514 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6515 "failed to check printer");
6519 return true;
6523 static bool test_GetPrinterDriver(struct torture_context *tctx,
6524 struct dcerpc_binding_handle *b,
6525 struct policy_handle *handle,
6526 const char *driver_name)
6528 struct spoolss_GetPrinterDriver r;
6529 uint32_t needed;
6531 r.in.handle = handle;
6532 r.in.architecture = "W32X86";
6533 r.in.level = 1;
6534 r.in.buffer = NULL;
6535 r.in.offered = 0;
6536 r.out.needed = &needed;
6538 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
6540 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6541 "failed to call GetPrinterDriver");
6542 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6543 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6544 r.in.buffer = &blob;
6545 r.in.offered = needed;
6546 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6547 "failed to call GetPrinterDriver");
6550 torture_assert_werr_ok(tctx, r.out.result,
6551 "failed to call GetPrinterDriver");
6553 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6555 return true;
6558 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
6559 struct dcerpc_binding_handle *b,
6560 struct policy_handle *handle,
6561 const char *driver_name,
6562 const char *architecture,
6563 uint32_t level,
6564 uint32_t client_major_version,
6565 uint32_t client_minor_version,
6566 union spoolss_DriverInfo *info_p,
6567 WERROR *result_p)
6570 struct spoolss_GetPrinterDriver2 r;
6571 uint32_t needed;
6572 uint32_t server_major_version;
6573 uint32_t server_minor_version;
6575 r.in.handle = handle;
6576 r.in.architecture = architecture;
6577 r.in.client_major_version = client_major_version;
6578 r.in.client_minor_version = client_minor_version;
6579 r.in.buffer = NULL;
6580 r.in.offered = 0;
6581 r.in.level = level;
6582 r.out.needed = &needed;
6583 r.out.server_major_version = &server_major_version;
6584 r.out.server_minor_version = &server_minor_version;
6586 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
6587 driver_name, r.in.level);
6589 torture_assert_ntstatus_ok(tctx,
6590 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6591 "failed to call GetPrinterDriver2");
6592 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6593 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6594 r.in.buffer = &blob;
6595 r.in.offered = needed;
6596 torture_assert_ntstatus_ok(tctx,
6597 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6598 "failed to call GetPrinterDriver2");
6601 if (result_p) {
6602 *result_p = r.out.result;
6605 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
6606 switch (r.in.level) {
6607 case 101:
6608 case 8:
6609 torture_comment(tctx,
6610 "level %d not implemented, not considering as an error\n",
6611 r.in.level);
6612 return true;
6613 default:
6614 break;
6618 torture_assert_werr_ok(tctx, r.out.result,
6619 "failed to call GetPrinterDriver2");
6621 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6623 if (info_p) {
6624 *info_p = *r.out.info;
6627 return true;
6630 static bool test_GetPrinterDriver2(struct torture_context *tctx,
6631 struct dcerpc_binding_handle *b,
6632 struct policy_handle *handle,
6633 const char *driver_name,
6634 const char *architecture)
6636 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
6637 int i;
6640 for (i=0;i<ARRAY_SIZE(levels);i++) {
6642 torture_assert(tctx,
6643 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
6644 "");
6647 return true;
6650 static bool test_EnumPrinterDrivers_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 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
6656 int i;
6657 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6658 struct dcerpc_binding_handle *b = p->binding_handle;
6659 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6661 for (i=0;i<ARRAY_SIZE(levels);i++) {
6663 uint32_t count;
6664 union spoolss_DriverInfo *info;
6666 torture_assert(tctx,
6667 test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
6668 "failed to enumerate drivers");
6670 if (!info) {
6671 torture_comment(tctx, "No printer drivers returned\n");
6672 break;
6676 return true;
6679 static bool test_DeletePrinter(struct torture_context *tctx,
6680 struct dcerpc_binding_handle *b,
6681 struct policy_handle *handle)
6683 struct spoolss_DeletePrinter r;
6685 torture_comment(tctx, "Testing DeletePrinter\n");
6687 r.in.handle = handle;
6689 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
6690 "failed to delete printer");
6691 torture_assert_werr_ok(tctx, r.out.result,
6692 "failed to delete printer");
6694 return true;
6697 static bool test_EnumPrinters_findname(struct torture_context *tctx,
6698 struct dcerpc_binding_handle *b,
6699 uint32_t flags,
6700 uint32_t level,
6701 const char *name,
6702 bool *found)
6704 struct spoolss_EnumPrinters e;
6705 uint32_t count;
6706 union spoolss_PrinterInfo *info;
6707 uint32_t needed;
6708 int i;
6710 *found = false;
6712 e.in.flags = flags;
6713 e.in.server = NULL;
6714 e.in.level = level;
6715 e.in.buffer = NULL;
6716 e.in.offered = 0;
6717 e.out.count = &count;
6718 e.out.info = &info;
6719 e.out.needed = &needed;
6721 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6722 "failed to enum printers");
6724 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
6725 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6726 e.in.buffer = &blob;
6727 e.in.offered = needed;
6729 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6730 "failed to enum printers");
6733 torture_assert_werr_ok(tctx, e.out.result,
6734 "failed to enum printers");
6736 for (i=0; i < count; i++) {
6738 const char *current = NULL;
6739 const char *q;
6741 switch (level) {
6742 case 1:
6743 current = info[i].info1.name;
6744 break;
6747 if (strequal(current, name)) {
6748 *found = true;
6749 break;
6752 q = strrchr(current, '\\');
6753 if (q) {
6754 if (!e.in.server) {
6755 torture_warning(tctx,
6756 "server returns printername %s incl. servername although we did not set servername", current);
6758 q++;
6759 if (strequal(q, name)) {
6760 *found = true;
6761 break;
6766 return true;
6769 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
6770 struct dcerpc_pipe *p,
6771 const char *printername,
6772 bool ex)
6774 WERROR result;
6775 struct spoolss_AddPrinter r;
6776 struct spoolss_AddPrinterEx rex;
6777 struct spoolss_SetPrinterInfoCtr info_ctr;
6778 struct spoolss_SetPrinterInfo1 info1;
6779 struct spoolss_DevmodeContainer devmode_ctr;
6780 struct sec_desc_buf secdesc_ctr;
6781 struct spoolss_UserLevelCtr userlevel_ctr;
6782 struct policy_handle handle;
6783 bool found = false;
6784 struct dcerpc_binding_handle *b = p->binding_handle;
6786 ZERO_STRUCT(devmode_ctr);
6787 ZERO_STRUCT(secdesc_ctr);
6788 ZERO_STRUCT(userlevel_ctr);
6789 ZERO_STRUCT(info1);
6791 torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
6792 ex ? "Ex":"", printername);
6794 /* try to add printer to wellknown printer list (level 1) */
6796 userlevel_ctr.level = 1;
6798 info_ctr.info.info1 = &info1;
6799 info_ctr.level = 1;
6801 rex.in.server = NULL;
6802 rex.in.info_ctr = &info_ctr;
6803 rex.in.devmode_ctr = &devmode_ctr;
6804 rex.in.secdesc_ctr = &secdesc_ctr;
6805 rex.in.userlevel_ctr = &userlevel_ctr;
6806 rex.out.handle = &handle;
6808 r.in.server = NULL;
6809 r.in.info_ctr = &info_ctr;
6810 r.in.devmode_ctr = &devmode_ctr;
6811 r.in.secdesc_ctr = &secdesc_ctr;
6812 r.out.handle = &handle;
6814 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6815 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6816 "failed to add printer");
6817 result = ex ? rex.out.result : r.out.result;
6818 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6819 "unexpected result code");
6821 info1.name = printername;
6822 info1.flags = PRINTER_ATTRIBUTE_SHARED;
6824 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6825 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6826 "failed to add printer");
6827 result = ex ? rex.out.result : r.out.result;
6828 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6829 "unexpected result code");
6831 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6832 better do a real check to see the printer is really there */
6834 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6835 PRINTER_ENUM_NETWORK, 1,
6836 printername,
6837 &found),
6838 "failed to enum printers");
6840 torture_assert(tctx, found, "failed to find newly added printer");
6842 info1.flags = 0;
6844 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6845 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6846 "failed to add printer");
6847 result = ex ? rex.out.result : r.out.result;
6848 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6849 "unexpected result code");
6851 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6852 better do a real check to see the printer has really been removed
6853 from the well known printer list */
6855 found = false;
6857 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6858 PRINTER_ENUM_NETWORK, 1,
6859 printername,
6860 &found),
6861 "failed to enum printers");
6862 #if 0
6863 torture_assert(tctx, !found, "printer still in well known printer list");
6864 #endif
6865 return true;
6868 static bool test_AddPrinter_normal(struct torture_context *tctx,
6869 struct dcerpc_pipe *p,
6870 struct policy_handle *handle_p,
6871 const char *printername,
6872 const char *drivername,
6873 const char *portname,
6874 struct spoolss_DeviceMode *devmode,
6875 bool ex)
6877 WERROR result;
6878 struct spoolss_AddPrinter r;
6879 struct spoolss_AddPrinterEx rex;
6880 struct spoolss_SetPrinterInfoCtr info_ctr;
6881 struct spoolss_SetPrinterInfo2 info2;
6882 struct spoolss_DevmodeContainer devmode_ctr;
6883 struct sec_desc_buf secdesc_ctr;
6884 struct spoolss_UserLevelCtr userlevel_ctr;
6885 struct policy_handle handle;
6886 bool found = false;
6887 bool existing_printer_deleted = false;
6888 struct dcerpc_binding_handle *b = p->binding_handle;
6890 ZERO_STRUCT(devmode_ctr);
6891 ZERO_STRUCT(secdesc_ctr);
6892 ZERO_STRUCT(userlevel_ctr);
6894 torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
6895 ex ? "Ex":"", printername);
6897 devmode_ctr.devmode = devmode;
6899 userlevel_ctr.level = 1;
6901 rex.in.server = NULL;
6902 rex.in.info_ctr = &info_ctr;
6903 rex.in.devmode_ctr = &devmode_ctr;
6904 rex.in.secdesc_ctr = &secdesc_ctr;
6905 rex.in.userlevel_ctr = &userlevel_ctr;
6906 rex.out.handle = &handle;
6908 r.in.server = NULL;
6909 r.in.info_ctr = &info_ctr;
6910 r.in.devmode_ctr = &devmode_ctr;
6911 r.in.secdesc_ctr = &secdesc_ctr;
6912 r.out.handle = &handle;
6914 again:
6916 /* try to add printer to printer list (level 2) */
6918 ZERO_STRUCT(info2);
6920 info_ctr.info.info2 = &info2;
6921 info_ctr.level = 2;
6923 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6924 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6925 "failed to add printer");
6926 result = ex ? rex.out.result : r.out.result;
6927 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6928 "unexpected result code");
6930 info2.printername = printername;
6932 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6933 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6934 "failed to add printer");
6935 result = ex ? rex.out.result : r.out.result;
6937 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
6938 struct policy_handle printer_handle;
6940 if (existing_printer_deleted) {
6941 torture_fail(tctx, "already deleted printer still existing?");
6944 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
6945 "failed to open printer handle");
6947 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
6948 "failed to delete printer");
6950 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
6951 "failed to close server handle");
6953 existing_printer_deleted = true;
6955 goto again;
6958 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
6959 "unexpected result code");
6961 info2.portname = portname;
6963 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6964 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6965 "failed to add printer");
6966 result = ex ? rex.out.result : r.out.result;
6967 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
6968 "unexpected result code");
6970 info2.drivername = drivername;
6972 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6973 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6974 "failed to add printer");
6975 result = ex ? rex.out.result : r.out.result;
6977 /* w2k8r2 allows to add printer w/o defining printprocessor */
6979 if (!W_ERROR_IS_OK(result)) {
6980 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
6981 "unexpected result code");
6983 info2.printprocessor = "winprint";
6985 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6986 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6987 "failed to add printer");
6988 result = ex ? rex.out.result : r.out.result;
6989 torture_assert_werr_ok(tctx, result,
6990 "failed to add printer");
6993 *handle_p = handle;
6995 /* we are paranoid, really check if the printer is there now */
6997 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6998 PRINTER_ENUM_LOCAL, 1,
6999 printername,
7000 &found),
7001 "failed to enum printers");
7002 torture_assert(tctx, found, "failed to find newly added printer");
7004 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7005 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7006 "failed to add printer");
7007 result = ex ? rex.out.result : r.out.result;
7008 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7009 "unexpected result code");
7011 return true;
7014 static bool test_printer_info(struct torture_context *tctx,
7015 void *private_data)
7017 struct torture_printer_context *t =
7018 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7019 struct dcerpc_pipe *p = t->spoolss_pipe;
7020 struct dcerpc_binding_handle *b = p->binding_handle;
7022 bool ret = true;
7024 if (torture_setting_bool(tctx, "samba3", false)) {
7025 torture_skip(tctx, "skipping printer info cross tests against samba 3");
7028 if (!test_PrinterInfo(tctx, b, &t->handle)) {
7029 ret = false;
7032 if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
7033 ret = false;
7036 return ret;
7039 static bool test_EnumPrinterKey(struct torture_context *tctx,
7040 struct dcerpc_binding_handle *b,
7041 struct policy_handle *handle,
7042 const char *key_name,
7043 const char ***array)
7045 struct spoolss_EnumPrinterKey r;
7046 uint32_t needed = 0;
7047 union spoolss_KeyNames key_buffer;
7048 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7049 uint32_t _ndr_size;
7050 int i;
7052 r.in.handle = handle;
7053 r.in.key_name = key_name;
7054 r.out.key_buffer = &key_buffer;
7055 r.out.needed = &needed;
7056 r.out._ndr_size = &_ndr_size;
7058 for (i=0; i < ARRAY_SIZE(offered); i++) {
7060 if (offered[i] < 0 && needed) {
7061 if (needed <= 4) {
7062 continue;
7064 r.in.offered = needed + offered[i];
7065 } else {
7066 r.in.offered = offered[i];
7069 ZERO_STRUCT(key_buffer);
7071 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
7073 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7074 "failed to call EnumPrinterKey");
7075 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
7077 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7078 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7079 _ndr_size, r.in.offered/2));
7081 r.in.offered = needed;
7082 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7083 "failed to call EnumPrinterKey");
7086 if (offered[i] > 0) {
7087 torture_assert_werr_ok(tctx, r.out.result,
7088 "failed to call EnumPrinterKey");
7091 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7092 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7093 _ndr_size, r.in.offered/2));
7095 torture_assert(tctx, (*r.out.needed <= r.in.offered),
7096 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
7098 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
7099 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
7101 if (key_buffer.string_array) {
7102 uint32_t calc_needed = 0;
7103 int s;
7104 for (s=0; key_buffer.string_array[s]; s++) {
7105 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7107 if (!key_buffer.string_array[0]) {
7108 calc_needed += 2;
7110 calc_needed += 2;
7112 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7113 "EnumPrinterKey unexpected size");
7117 if (array) {
7118 *array = key_buffer.string_array;
7121 return true;
7124 bool test_printer_all_keys(struct torture_context *tctx,
7125 struct dcerpc_binding_handle *b,
7126 struct policy_handle *handle)
7128 const char **key_array = NULL;
7129 int i;
7131 torture_comment(tctx, "Testing Printer Keys\n");
7133 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7134 "failed to call test_EnumPrinterKey");
7136 for (i=0; key_array && key_array[i]; i++) {
7137 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7138 "failed to call test_EnumPrinterKey");
7140 for (i=0; key_array && key_array[i]; i++) {
7141 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7142 "failed to call test_EnumPrinterDataEx");
7145 torture_comment(tctx, "Printer Keys test succeeded\n\n");
7147 return true;
7150 static bool test_openprinter_wrap(struct torture_context *tctx,
7151 void *private_data)
7153 struct torture_printer_context *t =
7154 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7155 struct dcerpc_pipe *p = t->spoolss_pipe;
7156 struct dcerpc_binding_handle *b = p->binding_handle;
7157 const char *printername = t->info2.printername;
7159 return test_openprinter(tctx, b, printername);
7162 static bool test_csetprinter(struct torture_context *tctx,
7163 void *private_data)
7165 struct torture_printer_context *t =
7166 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7167 struct dcerpc_pipe *p = t->spoolss_pipe;
7169 const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7170 const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7171 const char *portname = t->info2.portname;
7173 union spoolss_PrinterInfo info;
7174 struct policy_handle new_handle, new_handle2;
7175 struct dcerpc_binding_handle *b = p->binding_handle;
7177 torture_comment(tctx, "Testing c_setprinter\n");
7179 torture_assert(tctx,
7180 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7181 "failed to get level 0 printer info");
7182 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7183 info.info0.c_setprinter);
7185 /* check if c_setprinter on 1st handle increases after a printer has
7186 * been added */
7188 torture_assert(tctx,
7189 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7190 "failed to add new printer");
7191 torture_assert(tctx,
7192 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7193 "failed to get level 0 printer info");
7194 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7195 info.info0.c_setprinter);
7197 /* check if c_setprinter on new handle increases after a printer has
7198 * been added */
7200 torture_assert(tctx,
7201 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7202 "failed to get level 0 printer info");
7203 torture_comment(tctx, "csetprinter on created handle: %d\n",
7204 info.info0.c_setprinter);
7206 /* open the new printer and check if c_setprinter increases */
7208 torture_assert(tctx,
7209 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7210 "failed to open created printer");
7211 torture_assert(tctx,
7212 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
7213 "failed to get level 0 printer info");
7214 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
7215 info.info0.c_setprinter);
7217 /* cleanup */
7219 torture_assert(tctx,
7220 test_ClosePrinter(tctx, b, &new_handle2),
7221 "failed to close printer");
7222 torture_assert(tctx,
7223 test_DeletePrinter(tctx, b, &new_handle),
7224 "failed to delete new printer");
7226 return true;
7229 static bool compose_local_driver_directory(struct torture_context *tctx,
7230 const char *environment,
7231 const char *local_dir,
7232 const char **path)
7234 char *p;
7236 p = strrchr(local_dir, '/');
7237 if (!p) {
7238 return NULL;
7240 p++;
7242 if (strequal(environment, "Windows x64")) {
7243 if (!strequal(p, "x64")) {
7244 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
7246 } else if (strequal(environment, "Windows NT x86")) {
7247 if (!strequal(p, "i386")) {
7248 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
7250 } else {
7251 torture_assert(tctx, "unknown environment: '%s'\n", environment);
7254 return true;
7257 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
7258 const char *devicename)
7260 struct spoolss_DeviceMode *r;
7262 r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
7263 if (r == NULL) {
7264 return NULL;
7267 r->devicename = talloc_strdup(r, devicename);
7268 r->specversion = DMSPEC_NT4_AND_ABOVE;
7269 r->driverversion = 0x0600;
7270 r->size = 0x00dc;
7271 r->__driverextra_length = 0;
7272 r->fields = DEVMODE_FORMNAME |
7273 DEVMODE_TTOPTION |
7274 DEVMODE_PRINTQUALITY |
7275 DEVMODE_DEFAULTSOURCE |
7276 DEVMODE_COPIES |
7277 DEVMODE_SCALE |
7278 DEVMODE_PAPERSIZE |
7279 DEVMODE_ORIENTATION;
7280 r->orientation = DMORIENT_PORTRAIT;
7281 r->papersize = DMPAPER_LETTER;
7282 r->paperlength = 0;
7283 r->paperwidth = 0;
7284 r->scale = 100;
7285 r->copies = 55;
7286 r->defaultsource = DMBIN_FORMSOURCE;
7287 r->printquality = DMRES_HIGH;
7288 r->color = DMRES_MONOCHROME;
7289 r->duplex = DMDUP_SIMPLEX;
7290 r->yresolution = 0;
7291 r->ttoption = DMTT_SUBDEV;
7292 r->collate = DMCOLLATE_FALSE;
7293 r->formname = talloc_strdup(r, "Letter");
7295 return r;
7298 static bool test_architecture_buffer(struct torture_context *tctx,
7299 void *private_data)
7301 struct test_spoolss_context *ctx =
7302 talloc_get_type_abort(private_data, struct test_spoolss_context);
7304 struct spoolss_OpenPrinterEx r;
7305 struct spoolss_UserLevel1 u1;
7306 struct policy_handle handle;
7307 uint32_t architectures[] = {
7308 PROCESSOR_ARCHITECTURE_INTEL,
7309 PROCESSOR_ARCHITECTURE_IA64,
7310 PROCESSOR_ARCHITECTURE_AMD64
7312 uint32_t needed[3];
7313 int i;
7314 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7315 struct dcerpc_binding_handle *b = p->binding_handle;
7317 for (i=0; i < ARRAY_SIZE(architectures); i++) {
7319 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7321 u1.size = 0;
7322 u1.client = NULL;
7323 u1.user = NULL;
7324 u1.build = 0;
7325 u1.major = 3;
7326 u1.minor = 0;
7327 u1.processor = architectures[i];
7329 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7330 r.in.datatype = NULL;
7331 r.in.devmode_ctr.devmode= NULL;
7332 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7333 r.in.level = 1;
7334 r.in.userlevel.level1 = &u1;
7335 r.out.handle = &handle;
7337 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7338 torture_assert_werr_ok(tctx, r.out.result, "");
7341 struct spoolss_EnumPrinters e;
7342 uint32_t count;
7343 union spoolss_PrinterInfo *info;
7345 e.in.flags = PRINTER_ENUM_LOCAL;
7346 e.in.server = NULL;
7347 e.in.level = 2;
7348 e.in.buffer = NULL;
7349 e.in.offered = 0;
7350 e.out.count = &count;
7351 e.out.info = &info;
7352 e.out.needed = &needed[i];
7354 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7355 #if 0
7356 torture_comment(tctx, "needed was %d\n", needed[i]);
7357 #endif
7360 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7363 for (i=1; i < ARRAY_SIZE(architectures); i++) {
7364 if (needed[i-1] != needed[i]) {
7365 torture_fail(tctx,
7366 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7367 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7371 return true;
7374 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
7375 void *private_data)
7377 struct test_spoolss_context *ctx =
7378 talloc_get_type_abort(private_data, struct test_spoolss_context);
7379 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7380 struct dcerpc_binding_handle *b = p->binding_handle;
7382 return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
7385 static bool test_PrintServer_Forms(struct torture_context *tctx,
7386 void *private_data)
7388 struct test_spoolss_context *ctx =
7389 talloc_get_type_abort(private_data, struct test_spoolss_context);
7390 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7391 struct dcerpc_binding_handle *b = p->binding_handle;
7393 return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
7396 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
7397 void *private_data)
7399 struct test_spoolss_context *ctx =
7400 talloc_get_type_abort(private_data, struct test_spoolss_context);
7401 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7402 struct dcerpc_binding_handle *b = p->binding_handle;
7404 return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
7407 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
7409 NTSTATUS status;
7411 status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
7413 torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
7415 torture_assert(tctx,
7416 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
7417 "failed to open printserver");
7418 torture_assert(tctx,
7419 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
7420 "failed to get environment");
7422 return true;
7425 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
7427 struct test_spoolss_context *t;
7429 *data = t = talloc_zero(tctx, struct test_spoolss_context);
7431 return torture_rpc_spoolss_setup_common(tctx, t);
7434 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
7436 test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
7438 return true;
7441 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
7443 struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
7444 bool ret;
7446 ret = torture_rpc_spoolss_teardown_common(tctx, t);
7447 talloc_free(t);
7449 return ret;
7452 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
7454 struct dcerpc_pipe *p;
7455 struct dcerpc_binding_handle *b;
7456 const char *server_name_slash;
7457 const char *driver_name;
7458 const char *printer_name;
7459 const char *port_name;
7461 torture_assert_ntstatus_ok(tctx,
7462 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
7463 "Error connecting to server");
7465 p = t->spoolss_pipe;
7466 b = p->binding_handle;
7467 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7469 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
7470 t->driver.info8.driver_name = TORTURE_DRIVER;
7471 t->driver.info8.driver_path = "pscript5.dll";
7472 t->driver.info8.data_file = "cups6.ppd";
7473 t->driver.info8.config_file = "ps5ui.dll";
7474 t->driver.info8.help_file = "pscript.hlp";
7475 t->driver.info8.default_datatype = "RAW";
7476 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
7477 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
7478 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
7479 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
7480 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
7481 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
7482 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
7483 t->driver.info8.dependent_files->string[5] = "cups6.ini";
7484 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
7485 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
7487 t->driver.local.driver_directory= "/usr/share/cups/drivers";
7489 t->info2.drivername = "Microsoft XPS Document Writer";
7490 t->info2.portname = "LPT1:";
7492 printer_name = t->info2.printername;
7493 port_name = t->info2.portname;
7495 torture_assert(tctx,
7496 fillup_printserver_info(tctx, p, &t->driver),
7497 "failed to fillup printserver info");
7499 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
7501 torture_assert(tctx,
7502 compose_local_driver_directory(tctx, t->driver.remote.environment,
7503 t->driver.local.driver_directory,
7504 &t->driver.local.driver_directory),
7505 "failed to compose local driver directory");
7507 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7508 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7509 t->info2.drivername, t->driver.remote.environment);
7510 t->have_driver = true;
7511 goto try_add;
7514 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
7515 t->info2.drivername, t->driver.remote.environment);
7516 torture_comment(tctx, "trying to upload own driver\n");
7518 if (!directory_exist(t->driver.local.driver_directory)) {
7519 torture_warning(tctx, "no local driver is available!");
7520 t->have_driver = false;
7521 goto try_add;
7524 torture_assert(tctx,
7525 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
7526 "failed to upload printer driver");
7528 torture_assert(tctx,
7529 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
7530 "failed to add driver");
7532 t->added_driver = true;
7533 t->have_driver = true;
7535 try_add:
7536 driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7538 if (t->wellknown) {
7539 torture_assert(tctx,
7540 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
7541 "failed to add wellknown printer");
7542 } else {
7543 torture_assert(tctx,
7544 test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
7545 "failed to add printer");
7548 return true;
7551 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
7553 struct torture_printer_context *t;
7555 *data = t = talloc_zero(tctx, struct torture_printer_context);
7557 t->ex = false;
7558 t->wellknown = false;
7559 t->info2.printername = TORTURE_PRINTER;
7560 t->devmode = NULL;
7562 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7565 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
7567 struct torture_printer_context *t;
7569 *data = t = talloc_zero(tctx, struct torture_printer_context);
7571 t->ex = true;
7572 t->wellknown = false;
7573 t->info2.printername = TORTURE_PRINTER_EX;
7574 t->devmode = NULL;
7576 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7579 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
7581 struct torture_printer_context *t;
7583 *data = t = talloc_zero(tctx, struct torture_printer_context);
7585 t->ex = false;
7586 t->wellknown = true;
7587 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
7588 t->devmode = NULL;
7590 /* FIXME */
7591 if (t->wellknown) {
7592 torture_skip(tctx, "skipping AddPrinter level 1");
7595 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7598 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
7600 struct torture_printer_context *t;
7602 *data = t = talloc_zero(tctx, struct torture_printer_context);
7604 t->ex = true;
7605 t->wellknown = true;
7606 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
7607 t->devmode = NULL;
7609 /* FIXME */
7610 if (t->wellknown) {
7611 torture_skip(tctx, "skipping AddPrinterEx level 1");
7614 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7617 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
7619 struct torture_printer_context *t;
7621 *data = t = talloc_zero(tctx, struct torture_printer_context);
7623 t->ex = true;
7624 t->wellknown = false;
7625 t->info2.printername = TORTURE_PRINTER_EX;
7626 t->devmode = torture_devicemode(t, TORTURE_PRINTER_EX);
7628 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7631 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
7633 bool found = false;
7634 struct dcerpc_pipe *p = t->spoolss_pipe;
7635 struct dcerpc_binding_handle *b;
7636 const char *printer_name = t->info2.printername;
7638 if (t->added_driver) {
7639 torture_assert(tctx,
7640 remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
7641 "failed to remove printer driver");
7644 if (p) {
7645 b = p->binding_handle;
7648 if (!t->wellknown) {
7649 torture_assert(tctx,
7650 test_DeletePrinter(tctx, b, &t->handle),
7651 "failed to delete printer");
7653 torture_assert(tctx,
7654 test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
7655 printer_name, &found),
7656 "failed to enumerate printers");
7658 torture_assert(tctx, !found, "deleted printer still there");
7661 return true;
7664 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
7666 struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
7667 bool ret;
7669 ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
7670 talloc_free(t);
7672 return ret;
7675 static bool test_print_test(struct torture_context *tctx,
7676 void *private_data)
7678 struct torture_printer_context *t =
7679 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7680 struct dcerpc_pipe *p = t->spoolss_pipe;
7681 struct dcerpc_binding_handle *b = p->binding_handle;
7683 torture_assert(tctx,
7684 test_PausePrinter(tctx, b, &t->handle),
7685 "failed to pause printer");
7687 torture_assert(tctx,
7688 test_DoPrintTest(tctx, b, &t->handle),
7689 "failed to do print test");
7691 torture_assert(tctx,
7692 test_ResumePrinter(tctx, b, &t->handle),
7693 "failed to resume printer");
7695 return true;
7698 static bool test_print_test_extended(struct torture_context *tctx,
7699 void *private_data)
7701 struct torture_printer_context *t =
7702 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7703 struct dcerpc_pipe *p = t->spoolss_pipe;
7704 struct dcerpc_binding_handle *b = p->binding_handle;
7705 bool ret = true;
7707 torture_assert(tctx,
7708 test_PausePrinter(tctx, b, &t->handle),
7709 "failed to pause printer");
7711 ret = test_DoPrintTest_extended(tctx, b, &t->handle);
7712 if (ret == false) {
7713 torture_comment(tctx, "WARNING! failed to do extended print test\n");
7714 if (torture_setting_bool(tctx, "samba3", false)) {
7715 torture_comment(tctx, "non-critical for samba3\n");
7716 ret = true;
7717 tctx->last_result = TORTURE_SKIP;
7721 torture_assert(tctx,
7722 test_ResumePrinter(tctx, b, &t->handle),
7723 "failed to resume printer");
7725 return ret;
7728 static bool test_printer_sd(struct torture_context *tctx,
7729 void *private_data)
7731 struct torture_printer_context *t =
7732 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7733 struct dcerpc_pipe *p = t->spoolss_pipe;
7734 struct dcerpc_binding_handle *b = p->binding_handle;
7736 torture_assert(tctx,
7737 test_PrinterInfo_SD(tctx, b, &t->handle),
7738 "failed to test security descriptors");
7740 return true;
7743 static bool test_printer_dm(struct torture_context *tctx,
7744 void *private_data)
7746 struct torture_printer_context *t =
7747 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7748 struct dcerpc_pipe *p = t->spoolss_pipe;
7750 torture_assert(tctx,
7751 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
7752 "failed to test devicemodes");
7754 return true;
7757 static bool test_printer_info_winreg(struct torture_context *tctx,
7758 void *private_data)
7760 struct torture_printer_context *t =
7761 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7762 struct dcerpc_pipe *p = t->spoolss_pipe;
7764 torture_assert(tctx,
7765 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
7766 "failed to test printer info winreg");
7768 return true;
7771 static bool test_printer_change_id(struct torture_context *tctx,
7772 void *private_data)
7774 struct torture_printer_context *t =
7775 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7776 struct dcerpc_pipe *p = t->spoolss_pipe;
7778 torture_assert(tctx,
7779 test_ChangeID(tctx, p, &t->handle),
7780 "failed to test change id");
7782 return true;
7785 static bool test_printer_keys(struct torture_context *tctx,
7786 void *private_data)
7788 struct torture_printer_context *t =
7789 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7790 struct dcerpc_pipe *p = t->spoolss_pipe;
7791 struct dcerpc_binding_handle *b = p->binding_handle;
7793 torture_assert(tctx,
7794 test_printer_all_keys(tctx, b, &t->handle),
7795 "failed to test printer keys");
7797 return true;
7800 static bool test_printer_data_consistency(struct torture_context *tctx,
7801 void *private_data)
7803 struct torture_printer_context *t =
7804 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7805 struct dcerpc_pipe *p = t->spoolss_pipe;
7807 torture_assert(tctx,
7808 test_EnumPrinterData_consistency(tctx, p, &t->handle),
7809 "failed to test printer data consistency");
7811 return true;
7814 static bool test_printer_data_keys(struct torture_context *tctx,
7815 void *private_data)
7817 struct torture_printer_context *t =
7818 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7819 struct dcerpc_pipe *p = t->spoolss_pipe;
7821 torture_assert(tctx,
7822 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
7823 "failed to test printer data keys");
7825 return true;
7828 static bool test_printer_data_values(struct torture_context *tctx,
7829 void *private_data)
7831 struct torture_printer_context *t =
7832 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7833 struct dcerpc_pipe *p = t->spoolss_pipe;
7835 torture_assert(tctx,
7836 test_SetPrinterDataEx_values(tctx, p, &t->handle),
7837 "failed to test printer data values");
7839 return true;
7842 static bool test_printer_data_set(struct torture_context *tctx,
7843 void *private_data)
7845 struct torture_printer_context *t =
7846 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7847 struct dcerpc_pipe *p = t->spoolss_pipe;
7849 torture_assert(tctx,
7850 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
7851 "failed to test printer data set");
7853 return true;
7856 static bool test_printer_data_winreg(struct torture_context *tctx,
7857 void *private_data)
7859 struct torture_printer_context *t =
7860 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7861 struct dcerpc_pipe *p = t->spoolss_pipe;
7863 torture_assert(tctx,
7864 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
7865 "failed to test printer data winreg");
7867 return true;
7870 static bool test_printer_data_dsspooler(struct torture_context *tctx,
7871 void *private_data)
7873 struct torture_printer_context *t =
7874 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7875 struct dcerpc_pipe *p = t->spoolss_pipe;
7877 torture_assert(tctx,
7878 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
7879 "failed to test printer data winreg dsspooler");
7881 return true;
7884 static bool test_driver_info_winreg(struct torture_context *tctx,
7885 void *private_data)
7887 struct torture_printer_context *t =
7888 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7889 struct dcerpc_pipe *p = t->spoolss_pipe;
7890 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7892 if (!t->have_driver) {
7893 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
7896 torture_assert(tctx,
7897 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
7898 "failed to test driver info winreg");
7900 return true;
7903 void torture_tcase_printer(struct torture_tcase *tcase)
7905 torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
7906 torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
7907 torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
7908 torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
7909 torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
7910 torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
7911 torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
7912 torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
7913 torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
7914 torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
7915 torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
7916 torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
7917 torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
7918 torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
7919 torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
7920 torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
7921 torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
7922 torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
7925 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
7927 struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
7928 struct torture_tcase *tcase;
7930 tcase = torture_suite_add_tcase(suite, "addprinter");
7932 torture_tcase_set_fixture(tcase,
7933 torture_rpc_spoolss_printer_setup,
7934 torture_rpc_spoolss_printer_teardown);
7936 torture_tcase_printer(tcase);
7938 tcase = torture_suite_add_tcase(suite, "addprinterex");
7940 torture_tcase_set_fixture(tcase,
7941 torture_rpc_spoolss_printerex_setup,
7942 torture_rpc_spoolss_printer_teardown);
7944 torture_tcase_printer(tcase);
7946 tcase = torture_suite_add_tcase(suite, "addprinterwkn");
7948 torture_tcase_set_fixture(tcase,
7949 torture_rpc_spoolss_printerwkn_setup,
7950 torture_rpc_spoolss_printer_teardown);
7952 tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
7954 torture_tcase_set_fixture(tcase,
7955 torture_rpc_spoolss_printerexwkn_setup,
7956 torture_rpc_spoolss_printer_teardown);
7958 #if 0
7959 /* test is not correct */
7960 tcase = torture_suite_add_tcase(suite, "addprinterdm");
7962 torture_tcase_set_fixture(tcase,
7963 torture_rpc_spoolss_printerdm_setup,
7964 torture_rpc_spoolss_printer_teardown);
7966 torture_tcase_printer(tcase);
7967 #endif
7968 return suite;
7971 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
7973 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
7974 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
7976 torture_tcase_set_fixture(tcase,
7977 torture_rpc_spoolss_setup,
7978 torture_rpc_spoolss_teardown);
7980 torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
7981 torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
7982 torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
7983 torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
7984 torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
7985 torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
7986 torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
7987 torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
7988 torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
7989 torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
7990 torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
7991 torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
7992 torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
7993 torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
7994 torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
7995 torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
7996 torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
7997 torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
7998 torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
7999 torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
8001 torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
8003 return suite;
8006 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
8007 struct dcerpc_binding_handle *b,
8008 const char *server,
8009 const char *environment,
8010 const char **dir_p)
8012 struct spoolss_GetPrinterDriverDirectory r;
8013 uint32_t needed;
8015 r.in.server = server;
8016 r.in.environment = environment;
8017 r.in.level = 1;
8018 r.in.buffer = NULL;
8019 r.in.offered = 0;
8020 r.out.needed = &needed;
8022 torture_assert_ntstatus_ok(tctx,
8023 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8024 "failed to query driver directory");
8026 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
8027 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
8028 r.in.buffer = &blob;
8029 r.in.offered = needed;
8031 torture_assert_ntstatus_ok(tctx,
8032 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8033 "failed to query driver directory");
8036 torture_assert_werr_ok(tctx, r.out.result,
8037 "failed to query driver directory");
8039 if (dir_p) {
8040 *dir_p = r.out.info->info1.directory_name;
8043 return true;
8046 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8048 if (info_ctr == NULL) {
8049 return NULL;
8052 switch (info_ctr->level) {
8053 case 1:
8054 return info_ctr->info.info1->driver_name;
8055 case 2:
8056 return info_ctr->info.info2->driver_name;
8057 case 3:
8058 return info_ctr->info.info3->driver_name;
8059 case 4:
8060 return info_ctr->info.info4->driver_name;
8061 case 6:
8062 return info_ctr->info.info6->driver_name;
8063 case 8:
8064 return info_ctr->info.info8->driver_name;
8065 default:
8066 return NULL;
8070 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8072 if (info_ctr == NULL) {
8073 return NULL;
8076 switch (info_ctr->level) {
8077 case 2:
8078 return info_ctr->info.info2->architecture;
8079 case 3:
8080 return info_ctr->info.info3->architecture;
8081 case 4:
8082 return info_ctr->info.info4->architecture;
8083 case 6:
8084 return info_ctr->info.info6->architecture;
8085 case 8:
8086 return info_ctr->info.info8->architecture;
8087 default:
8088 return NULL;
8093 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
8094 struct dcerpc_binding_handle *b,
8095 const char *servername,
8096 struct spoolss_AddDriverInfoCtr *info_ctr,
8097 WERROR expected_result)
8099 struct spoolss_AddPrinterDriver r;
8100 const char *drivername = get_driver_from_info(info_ctr);
8101 const char *environment = get_environment_from_info(info_ctr);
8103 r.in.servername = servername;
8104 r.in.info_ctr = info_ctr;
8106 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
8107 drivername, info_ctr->level, environment);
8109 torture_assert_ntstatus_ok(tctx,
8110 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
8111 "spoolss_AddPrinterDriver failed");
8112 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8113 "spoolss_AddPrinterDriver failed with unexpected result");
8115 return true;
8119 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
8120 struct dcerpc_binding_handle *b,
8121 const char *servername,
8122 struct spoolss_AddDriverInfoCtr *info_ctr,
8123 uint32_t flags,
8124 WERROR expected_result)
8126 struct spoolss_AddPrinterDriverEx r;
8127 const char *drivername = get_driver_from_info(info_ctr);
8128 const char *environment = get_environment_from_info(info_ctr);
8130 r.in.servername = servername;
8131 r.in.info_ctr = info_ctr;
8132 r.in.flags = flags;
8134 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
8135 drivername, info_ctr->level, environment);
8137 torture_assert_ntstatus_ok(tctx,
8138 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
8139 "AddPrinterDriverEx failed");
8140 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8141 "AddPrinterDriverEx failed with unexpected result");
8143 return true;
8146 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
8147 if (path && strlen(path)) {\
8148 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
8151 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
8152 struct dcerpc_binding_handle *b,
8153 const char *server_name,
8154 struct spoolss_AddDriverInfo8 *r,
8155 uint32_t flags,
8156 bool ex,
8157 const char *remote_driver_dir)
8159 struct spoolss_AddDriverInfoCtr info_ctr;
8160 struct spoolss_AddDriverInfo1 info1;
8162 ZERO_STRUCT(info1);
8164 info_ctr.level = 1;
8165 info_ctr.info.info1 = &info1;
8167 if (ex) {
8168 torture_assert(tctx,
8169 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8170 "failed to test AddPrinterDriverEx level 1");
8171 } else {
8172 torture_assert(tctx,
8173 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8174 "failed to test AddPrinterDriver level 1");
8177 info1.driver_name = r->driver_name;
8179 if (ex) {
8180 torture_assert(tctx,
8181 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8182 "failed to test AddPrinterDriverEx level 1");
8183 } else {
8184 torture_assert(tctx,
8185 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8186 "failed to test AddPrinterDriver level 1");
8189 return true;
8192 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
8193 struct dcerpc_binding_handle *b,
8194 const char *server_name,
8195 struct spoolss_AddDriverInfo8 *r,
8196 uint32_t flags,
8197 bool ex,
8198 const char *remote_driver_dir)
8200 struct spoolss_AddDriverInfoCtr info_ctr;
8201 struct spoolss_AddDriverInfo2 info2;
8202 union spoolss_DriverInfo info;
8204 ZERO_STRUCT(info2);
8206 info_ctr.level = 2;
8207 info_ctr.info.info2 = &info2;
8209 if (ex) {
8210 torture_assert(tctx,
8211 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8212 "failed to test AddPrinterDriverEx level 2");
8213 } else {
8214 torture_assert(tctx,
8215 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8216 "failed to test AddPrinterDriver level 2");
8219 info2.driver_name = r->driver_name;
8221 if (ex) {
8222 torture_assert(tctx,
8223 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8224 "failed to test AddPrinterDriverEx level 2");
8225 } else {
8226 torture_assert(tctx,
8227 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8228 "failed to test AddPrinterDriver level 2");
8231 info2.version = r->version;
8233 if (ex) {
8234 torture_assert(tctx,
8235 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8236 "failed to test AddPrinterDriverEx level 2");
8237 } else {
8238 torture_assert(tctx,
8239 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8240 "failed to test AddPrinterDriver level 2");
8243 info2.architecture = r->architecture;
8245 if (ex) {
8246 torture_assert(tctx,
8247 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8248 "failed to test AddPrinterDriverEx level 2");
8249 } else {
8250 torture_assert(tctx,
8251 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8252 "failed to test AddPrinterDriver level 2");
8255 info2.driver_path = r->driver_path;
8257 if (ex) {
8258 torture_assert(tctx,
8259 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8260 "failed to test AddPrinterDriverEx level 2");
8261 } else {
8262 torture_assert(tctx,
8263 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8264 "failed to test AddPrinterDriver level 2");
8267 info2.data_file = r->data_file;
8269 if (ex) {
8270 torture_assert(tctx,
8271 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8272 "failed to test AddPrinterDriverEx level 2");
8273 } else {
8274 torture_assert(tctx,
8275 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8276 "failed to test AddPrinterDriver level 2");
8279 info2.config_file = r->config_file;
8281 if (ex) {
8282 torture_assert(tctx,
8283 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
8284 "failed to test AddPrinterDriverEx");
8287 if (ex) {
8288 torture_assert(tctx,
8289 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8290 "failed to test AddPrinterDriverEx level 2");
8291 } else {
8292 torture_assert(tctx,
8293 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8294 "failed to test AddPrinterDriver level 2");
8297 torture_assert(tctx,
8298 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
8299 "failed to find added printer driver");
8301 if (remote_driver_dir) {
8302 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
8303 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
8304 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
8307 return true;
8310 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
8311 struct dcerpc_binding_handle *b,
8312 const char *server_name,
8313 struct spoolss_AddDriverInfo8 *r,
8314 uint32_t flags,
8315 bool ex,
8316 const char *remote_driver_dir)
8318 struct spoolss_AddDriverInfoCtr info_ctr;
8319 struct spoolss_AddDriverInfo3 info3;
8320 union spoolss_DriverInfo info;
8322 info3.driver_name = r->driver_name;
8323 info3.version = r->version;
8324 info3.architecture = r->architecture;
8325 info3.driver_path = r->driver_path;
8326 info3.data_file = r->data_file;
8327 info3.config_file = r->config_file;
8328 info3.help_file = r->help_file;
8329 info3.monitor_name = r->monitor_name;
8330 info3.default_datatype = r->default_datatype;
8331 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8332 info3.dependent_files = r->dependent_files;
8334 info_ctr.level = 3;
8335 info_ctr.info.info3 = &info3;
8337 if (ex) {
8338 torture_assert(tctx,
8339 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8340 "failed to test AddPrinterDriverEx level 3");
8341 } else {
8342 torture_assert(tctx,
8343 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8344 "failed to test AddPrinterDriver level 3");
8347 torture_assert(tctx,
8348 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
8349 "failed to find added printer driver");
8351 if (remote_driver_dir) {
8352 int i;
8353 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
8354 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
8355 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
8356 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
8357 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
8358 ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
8362 return true;
8365 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
8366 struct dcerpc_binding_handle *b,
8367 const char *server_name,
8368 struct spoolss_AddDriverInfo8 *r,
8369 uint32_t flags,
8370 bool ex,
8371 const char *remote_driver_dir)
8373 struct spoolss_AddDriverInfoCtr info_ctr;
8374 struct spoolss_AddDriverInfo4 info4;
8375 union spoolss_DriverInfo info;
8377 info4.version = r->version;
8378 info4.driver_name = r->driver_name;
8379 info4.architecture = r->architecture;
8380 info4.driver_path = r->driver_path;
8381 info4.data_file = r->data_file;
8382 info4.config_file = r->config_file;
8383 info4.help_file = r->help_file;
8384 info4.monitor_name = r->monitor_name;
8385 info4.default_datatype = r->default_datatype;
8386 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8387 info4.dependent_files = r->dependent_files;
8388 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
8389 info4.previous_names = r->previous_names;
8391 info_ctr.level = 4;
8392 info_ctr.info.info4 = &info4;
8394 if (ex) {
8395 torture_assert(tctx,
8396 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8397 "failed to test AddPrinterDriverEx level 4");
8398 } else {
8399 torture_assert(tctx,
8400 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8401 "failed to test AddPrinterDriver level 4");
8404 torture_assert(tctx,
8405 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
8406 "failed to find added printer driver");
8408 if (remote_driver_dir) {
8409 int i;
8410 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
8411 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
8412 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
8413 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
8414 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
8415 ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
8419 return true;
8422 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
8423 struct dcerpc_binding_handle *b,
8424 const char *server_name,
8425 struct spoolss_AddDriverInfo8 *r,
8426 uint32_t flags,
8427 bool ex,
8428 const char *remote_driver_dir)
8430 struct spoolss_AddDriverInfoCtr info_ctr;
8431 struct spoolss_AddDriverInfo6 info6;
8432 union spoolss_DriverInfo info;
8434 info6.version = r->version;
8435 info6.driver_name = r->driver_name;
8436 info6.architecture = r->architecture;
8437 info6.driver_path = r->driver_path;
8438 info6.data_file = r->data_file;
8439 info6.config_file = r->config_file;
8440 info6.help_file = r->help_file;
8441 info6.monitor_name = r->monitor_name;
8442 info6.default_datatype = r->default_datatype;
8443 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8444 info6.dependent_files = r->dependent_files;
8445 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
8446 info6.previous_names = r->previous_names;
8447 info6.driver_date = r->driver_date;
8448 info6.driver_version = r->driver_version;
8449 info6.manufacturer_name = r->manufacturer_name;
8450 info6.manufacturer_url = r->manufacturer_url;
8451 info6.hardware_id = r->hardware_id;
8452 info6.provider = r->provider;
8454 info_ctr.level = 6;
8455 info_ctr.info.info6 = &info6;
8457 if (ex) {
8458 torture_assert(tctx,
8459 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8460 "failed to test AddPrinterDriverEx level 6");
8461 } else {
8462 torture_assert(tctx,
8463 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8464 "failed to test AddPrinterDriver level 6");
8467 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8469 if (!ex) {
8470 return true;
8473 torture_assert(tctx,
8474 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
8475 "failed to find added printer driver");
8477 if (remote_driver_dir) {
8478 int i;
8479 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
8480 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
8481 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
8482 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
8483 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
8484 ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
8488 torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
8489 torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
8491 return true;
8494 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
8495 struct dcerpc_binding_handle *b,
8496 const char *server_name,
8497 struct spoolss_AddDriverInfo8 *r,
8498 uint32_t flags,
8499 bool ex,
8500 const char *remote_driver_dir)
8502 struct spoolss_AddDriverInfoCtr info_ctr;
8503 union spoolss_DriverInfo info;
8505 info_ctr.level = 8;
8506 info_ctr.info.info8 = r;
8508 if (ex) {
8509 torture_assert(tctx,
8510 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8511 "failed to test AddPrinterDriverEx level 8");
8512 } else {
8513 torture_assert(tctx,
8514 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8515 "failed to test AddPrinterDriver level 8");
8518 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8520 if (!ex) {
8521 return true;
8524 torture_assert(tctx,
8525 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
8526 "failed to find added printer driver");
8528 if (remote_driver_dir) {
8529 int i;
8530 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
8531 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
8532 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
8533 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
8534 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
8535 ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
8539 torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
8540 torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
8542 return true;
8545 #undef ASSERT_DRIVER_PATH
8547 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
8548 struct dcerpc_binding_handle *b,
8549 const char *server,
8550 const char *driver,
8551 const char *environment,
8552 WERROR expected_result)
8554 struct spoolss_DeletePrinterDriver r;
8556 r.in.server = server;
8557 r.in.architecture = environment;
8558 r.in.driver = driver;
8560 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
8562 torture_assert_ntstatus_ok(tctx,
8563 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
8564 "DeletePrinterDriver failed");
8565 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8566 "DeletePrinterDriver failed with unexpected result");
8568 return true;
8571 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
8572 struct dcerpc_binding_handle *b,
8573 const char *server,
8574 const char *driver,
8575 const char *environment,
8576 uint32_t delete_flags,
8577 uint32_t version,
8578 WERROR expected_result)
8580 struct spoolss_DeletePrinterDriverEx r;
8582 r.in.server = server;
8583 r.in.architecture = environment;
8584 r.in.driver = driver;
8585 r.in.delete_flags = delete_flags;
8586 r.in.version = version;
8588 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
8590 torture_assert_ntstatus_ok(tctx,
8591 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
8592 "DeletePrinterDriverEx failed");
8593 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8594 "DeletePrinterDriverEx failed with unexpected result");
8596 return true;
8599 static bool test_DeletePrinterDriver(struct torture_context *tctx,
8600 struct dcerpc_binding_handle *b,
8601 const char *server_name,
8602 const char *driver,
8603 const char *environment)
8605 torture_assert(tctx,
8606 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
8607 "failed to delete driver");
8609 torture_assert(tctx,
8610 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
8611 "failed to delete driver");
8613 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8614 torture_fail(tctx, "deleted driver still enumerated");
8617 torture_assert(tctx,
8618 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
8619 "2nd delete failed");
8621 return true;
8624 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
8625 struct dcerpc_binding_handle *b,
8626 const char *server_name,
8627 const char *driver,
8628 const char *environment,
8629 uint32_t delete_flags,
8630 uint32_t version)
8632 torture_assert(tctx,
8633 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
8634 "failed to delete driver");
8636 torture_assert(tctx,
8637 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
8638 "failed to delete driver");
8640 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8641 torture_fail(tctx, "deleted driver still enumerated");
8644 torture_assert(tctx,
8645 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
8646 "2nd delete failed");
8648 return true;
8651 static bool test_PrinterDriver_args(struct torture_context *tctx,
8652 struct dcerpc_binding_handle *b,
8653 const char *server_name,
8654 uint32_t level,
8655 struct spoolss_AddDriverInfo8 *r,
8656 uint32_t add_flags,
8657 uint32_t delete_flags,
8658 uint32_t delete_version,
8659 bool ex,
8660 const char *remote_driver_dir)
8662 bool ret = true;
8664 switch (level) {
8665 case 1:
8666 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8667 break;
8668 case 2:
8669 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8670 break;
8671 case 3:
8672 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8673 break;
8674 case 4:
8675 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8676 break;
8677 case 6:
8678 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8679 break;
8680 case 8:
8681 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8682 break;
8683 default:
8684 return false;
8687 if (ret == false) {
8688 return ret;
8691 if (level == 1) {
8692 return ret;
8695 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8697 if (!ex && (level == 6 || level == 8)) {
8698 return ret;
8702 struct dcerpc_pipe *p2;
8703 struct policy_handle hive_handle;
8704 struct dcerpc_binding_handle *b2;
8706 torture_assert_ntstatus_ok(tctx,
8707 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
8708 "could not open winreg pipe");
8709 b2 = p2->binding_handle;
8711 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
8713 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
8715 test_winreg_CloseKey(tctx, b2, &hive_handle);
8717 talloc_free(p2);
8720 if (ex) {
8721 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
8722 } else {
8723 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
8727 static bool fillup_printserver_info(struct torture_context *tctx,
8728 struct dcerpc_pipe *p,
8729 struct torture_driver_context *d)
8731 struct policy_handle server_handle;
8732 struct dcerpc_binding_handle *b = p->binding_handle;
8733 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8735 torture_assert(tctx,
8736 test_OpenPrinter_server(tctx, p, &server_handle),
8737 "failed to open printserver");
8738 torture_assert(tctx,
8739 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
8740 "failed to get environment");
8741 torture_assert(tctx,
8742 test_ClosePrinter(tctx, b, &server_handle),
8743 "failed to close printserver");
8745 torture_assert(tctx,
8746 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
8747 d->local.environment ? d->local.environment : d->remote.environment,
8748 &d->remote.driver_directory),
8749 "failed to get driver directory");
8751 return true;
8754 static const char *driver_directory_dir(const char *driver_directory)
8756 char *p;
8758 p = strrchr(driver_directory, '\\');
8759 if (p) {
8760 return p+1;
8763 return NULL;
8766 static const char *driver_directory_share(struct torture_context *tctx,
8767 const char *driver_directory)
8769 const char *p;
8770 char *tok;
8772 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
8773 driver_directory += 2;
8776 p = talloc_strdup(tctx, driver_directory);
8778 torture_assert(tctx,
8779 next_token_talloc(tctx, &p, &tok, "\\"),
8780 "cannot explode uri");
8781 torture_assert(tctx,
8782 next_token_talloc(tctx, &p, &tok, "\\"),
8783 "cannot explode uri");
8785 return tok;
8788 static bool upload_printer_driver_file(struct torture_context *tctx,
8789 struct smbcli_state *cli,
8790 struct torture_driver_context *d,
8791 const char *file_name)
8793 XFILE *f;
8794 int fnum;
8795 uint8_t *buf;
8796 int maxwrite = 64512;
8797 off_t nread = 0;
8798 size_t start = 0;
8799 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
8800 const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
8801 const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8803 if (!file_name || strlen(file_name) == 0) {
8804 return true;
8807 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
8809 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
8810 if (fnum == -1) {
8811 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
8814 f = x_fopen(local_name, O_RDONLY, 0);
8815 if (f == NULL) {
8816 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
8819 buf = talloc_array(tctx, uint8_t, maxwrite);
8820 if (!buf) {
8821 return false;
8824 while (!x_feof(f)) {
8825 int n = maxwrite;
8826 int ret;
8828 if ((n = x_fread(buf, 1, n, f)) < 1) {
8829 if((n == 0) && x_feof(f))
8830 break; /* Empty local file. */
8832 torture_warning(tctx,
8833 "failed to read file: %s\n", strerror(errno));
8834 break;
8837 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
8839 if (n != ret) {
8840 torture_warning(tctx,
8841 "failed to write file: %s\n", smbcli_errstr(cli->tree));
8842 break;
8845 nread += n;
8848 x_fclose(f);
8850 torture_assert_ntstatus_ok(tctx,
8851 smbcli_close(cli->tree, fnum),
8852 "failed to close file");
8854 return true;
8857 static bool connect_printer_driver_share(struct torture_context *tctx,
8858 const char *server_name,
8859 const char *share_name,
8860 struct smbcli_state **cli)
8862 struct smbcli_options smb_options;
8863 struct smbcli_session_options smb_session_options;
8865 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
8866 share_name, server_name);
8868 lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
8869 lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
8871 torture_assert_ntstatus_ok(tctx,
8872 smbcli_full_connection(tctx, cli, server_name,
8873 lpcfg_smb_ports(tctx->lp_ctx),
8874 share_name, NULL,
8875 lpcfg_socket_options(tctx->lp_ctx),
8876 cmdline_credentials,
8877 lpcfg_resolve_context(tctx->lp_ctx),
8878 tctx->ev,
8879 &smb_options,
8880 &smb_session_options,
8881 lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
8882 "failed to open driver share");
8884 return true;
8887 static bool upload_printer_driver(struct torture_context *tctx,
8888 const char *server_name,
8889 struct torture_driver_context *d)
8891 struct smbcli_state *cli;
8892 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8893 int i;
8895 torture_assert(tctx,
8896 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8897 "failed to connect to driver share");
8899 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
8900 server_name, share_name);
8902 torture_assert(tctx,
8903 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8904 "failed to upload driver_path");
8905 torture_assert(tctx,
8906 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
8907 "failed to upload data_file");
8908 torture_assert(tctx,
8909 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
8910 "failed to upload config_file");
8911 torture_assert(tctx,
8912 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
8913 "failed to upload help_file");
8914 if (d->info8.dependent_files) {
8915 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8916 torture_assert(tctx,
8917 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8918 "failed to upload dependent_files");
8922 talloc_free(cli);
8924 return true;
8927 static bool check_printer_driver_file(struct torture_context *tctx,
8928 struct smbcli_state *cli,
8929 struct torture_driver_context *d,
8930 const char *file_name)
8932 const char *remote_arch_dir = driver_directory_dir(d->remote.driver_directory);
8933 const char *remote_name = talloc_asprintf(tctx, "%s\\%d\\%s",
8934 remote_arch_dir,
8935 d->info8.version,
8936 file_name);
8937 int fnum;
8939 torture_assert(tctx, (file_name && strlen(file_name) != 0), "invalid filename");
8941 torture_comment(tctx, "checking for driver file at %s\n", remote_name);
8943 fnum = smbcli_open(cli->tree, remote_name, O_RDONLY, DENY_NONE);
8944 if (fnum == -1) {
8945 return false;
8948 torture_assert_ntstatus_ok(tctx,
8949 smbcli_close(cli->tree, fnum),
8950 "failed to close driver file");
8952 return true;
8955 static bool check_printer_driver_files(struct torture_context *tctx,
8956 const char *server_name,
8957 struct torture_driver_context *d,
8958 bool expect_exist)
8960 struct smbcli_state *cli;
8961 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8962 int i;
8964 torture_assert(tctx,
8965 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8966 "failed to connect to driver share");
8968 torture_comment(tctx, "checking %sexistent driver files at \\\\%s\\%s\n",
8969 (expect_exist ? "": "non-"),
8970 server_name, share_name);
8972 if (d->info8.driver_path && d->info8.driver_path[0]) {
8973 torture_assert(tctx,
8974 check_printer_driver_file(tctx, cli, d, d->info8.driver_path) == expect_exist,
8975 "failed driver_path check");
8977 if (d->info8.data_file && d->info8.data_file[0]) {
8978 torture_assert(tctx,
8979 check_printer_driver_file(tctx, cli, d, d->info8.data_file) == expect_exist,
8980 "failed data_file check");
8982 if (d->info8.config_file && d->info8.config_file[0]) {
8983 torture_assert(tctx,
8984 check_printer_driver_file(tctx, cli, d, d->info8.config_file) == expect_exist,
8985 "failed config_file check");
8987 if (d->info8.help_file && d->info8.help_file[0]) {
8988 torture_assert(tctx,
8989 check_printer_driver_file(tctx, cli, d, d->info8.help_file) == expect_exist,
8990 "failed help_file check");
8992 if (d->info8.dependent_files) {
8993 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8994 torture_assert(tctx,
8995 check_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]) == expect_exist,
8996 "failed dependent_files check");
9000 talloc_free(cli);
9002 return true;
9005 static bool remove_printer_driver_file(struct torture_context *tctx,
9006 struct smbcli_state *cli,
9007 struct torture_driver_context *d,
9008 const char *file_name)
9010 const char *remote_name;
9011 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
9013 if (!file_name || strlen(file_name) == 0) {
9014 return true;
9017 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
9019 torture_comment(tctx, "Removing %s\n", remote_name);
9021 torture_assert_ntstatus_ok(tctx,
9022 smbcli_unlink(cli->tree, remote_name),
9023 "failed to unlink");
9025 return true;
9028 static bool remove_printer_driver(struct torture_context *tctx,
9029 const char *server_name,
9030 struct torture_driver_context *d)
9032 struct smbcli_state *cli;
9033 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9034 int i;
9036 torture_assert(tctx,
9037 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9038 "failed to connect to driver share");
9040 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
9041 server_name, share_name);
9043 torture_assert(tctx,
9044 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
9045 "failed to remove driver_path");
9046 torture_assert(tctx,
9047 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
9048 "failed to remove data_file");
9049 if (!strequal(d->info8.config_file, d->info8.driver_path)) {
9050 torture_assert(tctx,
9051 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
9052 "failed to remove config_file");
9054 torture_assert(tctx,
9055 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
9056 "failed to remove help_file");
9057 if (d->info8.dependent_files) {
9058 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9059 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
9060 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
9061 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
9062 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
9063 continue;
9065 torture_assert(tctx,
9066 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9067 "failed to remove dependent_files");
9071 talloc_free(cli);
9073 return true;
9077 static bool test_add_driver_arg(struct torture_context *tctx,
9078 struct dcerpc_pipe *p,
9079 struct torture_driver_context *d)
9081 bool ret = true;
9082 struct dcerpc_binding_handle *b = p->binding_handle;
9083 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9084 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
9085 int i;
9086 struct spoolss_AddDriverInfo8 info8;
9087 uint32_t add_flags = APD_COPY_NEW_FILES;
9088 uint32_t delete_flags = 0;
9090 ZERO_STRUCT(info8);
9092 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
9093 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
9095 torture_assert(tctx,
9096 fillup_printserver_info(tctx, p, d),
9097 "failed to fillup printserver info");
9099 if (!directory_exist(d->local.driver_directory)) {
9100 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9103 torture_assert(tctx,
9104 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9105 "failed to upload printer driver");
9107 info8 = d->info8;
9108 if (d->info8.dependent_files) {
9109 info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
9110 if (d->info8.dependent_files->string) {
9111 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9113 info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
9114 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9115 info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
9119 info8.architecture = d->local.environment;
9121 for (i=0; i < ARRAY_SIZE(levels); i++) {
9123 if (torture_setting_bool(tctx, "samba3", false)) {
9124 switch (levels[i]) {
9125 case 2:
9126 case 4:
9127 case 8:
9128 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9129 continue;
9130 default:
9131 break;
9134 if (torture_setting_bool(tctx, "w2k3", false)) {
9135 switch (levels[i]) {
9136 case 8:
9137 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9138 continue;
9139 default:
9140 break;
9144 torture_comment(tctx,
9145 "Testing PrinterDriver%s '%s' add & delete level %d\n",
9146 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9148 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);
9151 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
9152 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
9153 if (d->info8.config_file) {
9154 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
9156 if (d->info8.help_file) {
9157 info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
9159 if (d->info8.dependent_files && d->info8.dependent_files->string) {
9160 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9161 info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
9165 for (i=0; i < ARRAY_SIZE(levels); i++) {
9167 if (torture_setting_bool(tctx, "samba3", false)) {
9168 switch (levels[i]) {
9169 case 2:
9170 case 4:
9171 case 8:
9172 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9173 continue;
9174 default:
9175 break;
9178 if (torture_setting_bool(tctx, "w2k3", false)) {
9179 switch (levels[i]) {
9180 case 8:
9181 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9182 continue;
9183 default:
9184 break;
9188 torture_comment(tctx,
9189 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
9190 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9192 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);
9195 torture_assert(tctx,
9196 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9197 "failed to remove printer driver");
9199 torture_comment(tctx, "\n");
9201 return ret;
9204 static bool test_add_driver_ex_64(struct torture_context *tctx,
9205 struct dcerpc_pipe *p)
9207 struct torture_driver_context *d;
9209 d = talloc_zero(tctx, struct torture_driver_context);
9211 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9212 d->info8.driver_name = TORTURE_DRIVER_EX;
9213 d->info8.architecture = NULL;
9214 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9215 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9216 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9217 d->local.environment = talloc_strdup(d, "Windows x64");
9218 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9219 d->ex = true;
9221 return test_add_driver_arg(tctx, p, d);
9224 static bool test_add_driver_ex_32(struct torture_context *tctx,
9225 struct dcerpc_pipe *p)
9227 struct torture_driver_context *d;
9229 d = talloc_zero(tctx, struct torture_driver_context);
9231 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9232 d->info8.driver_name = TORTURE_DRIVER_EX;
9233 d->info8.architecture = NULL;
9234 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9235 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9236 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9237 d->local.environment = talloc_strdup(d, "Windows NT x86");
9238 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9239 d->ex = true;
9241 return test_add_driver_arg(tctx, p, d);
9244 static bool test_add_driver_64(struct torture_context *tctx,
9245 struct dcerpc_pipe *p)
9247 struct torture_driver_context *d;
9249 d = talloc_zero(tctx, struct torture_driver_context);
9251 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9252 d->info8.driver_name = TORTURE_DRIVER;
9253 d->info8.architecture = NULL;
9254 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9255 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9256 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9257 d->local.environment = talloc_strdup(d, "Windows x64");
9258 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9259 d->ex = false;
9261 return test_add_driver_arg(tctx, p, d);
9264 static bool test_add_driver_32(struct torture_context *tctx,
9265 struct dcerpc_pipe *p)
9267 struct torture_driver_context *d;
9269 d = talloc_zero(tctx, struct torture_driver_context);
9271 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9272 d->info8.driver_name = TORTURE_DRIVER;
9273 d->info8.architecture = NULL;
9274 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9275 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9276 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9277 d->local.environment = talloc_strdup(d, "Windows NT x86");
9278 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9279 d->ex = false;
9281 return test_add_driver_arg(tctx, p, d);
9284 static bool test_add_driver_adobe(struct torture_context *tctx,
9285 struct dcerpc_pipe *p)
9287 struct torture_driver_context *d;
9289 if (!torture_setting_bool(tctx, "samba3", false)) {
9290 torture_skip(tctx, "skipping adobe test which only works against samba3");
9293 d = talloc_zero(tctx, struct torture_driver_context);
9295 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9296 d->info8.driver_name = TORTURE_DRIVER_ADOBE;
9297 d->info8.architecture = NULL;
9298 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9299 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9300 d->info8.config_file = talloc_strdup(d, "ADOBEPS4.DRV");
9301 #if 0
9302 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9303 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9304 #endif
9305 d->local.environment = talloc_strdup(d, "Windows 4.0");
9306 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9307 d->ex = false;
9309 return test_add_driver_arg(tctx, p, d);
9312 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
9313 struct dcerpc_pipe *p)
9315 struct torture_driver_context *d;
9316 struct spoolss_StringArray *a;
9318 if (!torture_setting_bool(tctx, "samba3", false)) {
9319 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
9322 d = talloc_zero(tctx, struct torture_driver_context);
9324 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9325 d->info8.driver_name = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
9326 d->info8.architecture = NULL;
9327 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9328 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9329 d->info8.config_file = NULL;
9330 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9331 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9332 d->info8.default_datatype = talloc_strdup(d, "RAW");
9334 a = talloc_zero(d, struct spoolss_StringArray);
9335 a->string = talloc_zero_array(a, const char *, 7);
9336 a->string[0] = talloc_strdup(a->string, "ADOBEPS4.DRV");
9337 a->string[1] = talloc_strdup(a->string, "DEFPRTR2.PPD");
9338 a->string[2] = talloc_strdup(a->string, "ADOBEPS4.HLP");
9339 a->string[3] = talloc_strdup(a->string, "PSMON.DLL");
9340 a->string[4] = talloc_strdup(a->string, "ADFONTS.MFM");
9341 a->string[5] = talloc_strdup(a->string, "ICONLIB.DLL");
9343 d->info8.dependent_files = a;
9344 d->local.environment = talloc_strdup(d, "Windows 4.0");
9345 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9346 d->ex = false;
9348 return test_add_driver_arg(tctx, p, d);
9351 static bool test_add_driver_timestamps(struct torture_context *tctx,
9352 struct dcerpc_pipe *p)
9354 struct torture_driver_context *d;
9355 struct timeval t = timeval_current();
9357 d = talloc_zero(tctx, struct torture_driver_context);
9359 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9360 d->info8.driver_name = TORTURE_DRIVER_TIMESTAMPS;
9361 d->info8.architecture = NULL;
9362 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9363 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9364 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9365 d->info8.driver_date = timeval_to_nttime(&t);
9366 d->local.environment = talloc_strdup(d, "Windows NT x86");
9367 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9368 d->ex = true;
9370 torture_assert(tctx,
9371 test_add_driver_arg(tctx, p, d),
9372 "");
9374 unix_to_nt_time(&d->info8.driver_date, 1);
9376 torture_assert(tctx,
9377 test_add_driver_arg(tctx, p, d),
9378 "");
9380 return true;
9383 static bool test_multiple_drivers(struct torture_context *tctx,
9384 struct dcerpc_pipe *p)
9386 struct torture_driver_context *d;
9387 struct dcerpc_binding_handle *b = p->binding_handle;
9388 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9389 int i;
9390 struct spoolss_AddDriverInfo8 info8;
9391 uint32_t add_flags = APD_COPY_NEW_FILES;
9392 uint32_t delete_flags = 0;
9394 d = talloc_zero(tctx, struct torture_driver_context);
9396 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9397 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9398 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9399 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9400 d->local.environment = talloc_strdup(d, "Windows NT x86");
9401 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9402 d->ex = true;
9404 torture_assert(tctx,
9405 fillup_printserver_info(tctx, p, d),
9406 "failed to fillup printserver info");
9408 if (!directory_exist(d->local.driver_directory)) {
9409 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9412 torture_assert(tctx,
9413 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9414 "failed to upload printer driver");
9416 info8 = d->info8;
9417 info8.architecture = d->local.environment;
9419 for (i=0; i < 3; i++) {
9420 info8.driver_name = talloc_asprintf(d, "torture_test_driver_%d", i);
9422 torture_assert(tctx,
9423 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &info8, add_flags, true, NULL),
9424 "failed to add driver");
9427 torture_assert(tctx,
9428 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_0", info8.architecture, delete_flags, info8.version),
9429 "failed to delete driver");
9431 torture_assert(tctx,
9432 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_1", NULL),
9433 "torture_test_driver_1 no longer on the server");
9435 torture_assert(tctx,
9436 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
9437 "torture_test_driver_2 no longer on the server");
9439 torture_assert(tctx,
9440 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_1", info8.architecture, delete_flags, info8.version),
9441 "failed to delete driver");
9443 torture_assert(tctx,
9444 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
9445 "torture_test_driver_2 no longer on the server");
9447 torture_assert(tctx,
9448 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_2", info8.architecture, delete_flags, info8.version),
9449 "failed to delete driver");
9451 torture_assert(tctx,
9452 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9453 "failed to remove printer driver");
9455 return true;
9458 static bool test_del_driver_all_files(struct torture_context *tctx,
9459 struct dcerpc_pipe *p)
9461 struct torture_driver_context *d;
9462 struct spoolss_StringArray *a;
9463 uint32_t add_flags = APD_COPY_NEW_FILES;
9464 uint32_t delete_flags = DPD_DELETE_ALL_FILES;
9465 struct dcerpc_binding_handle *b = p->binding_handle;
9466 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9468 d = talloc_zero(tctx, struct torture_driver_context);
9470 d->ex = true;
9471 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9472 d->info8.driver_name = TORTURE_DRIVER_DELETER;
9473 d->info8.architecture = NULL;
9474 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9475 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9476 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9477 d->info8.help_file = talloc_strdup(d, "pscript.hlp");
9478 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
9479 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9481 a = talloc_zero(d, struct spoolss_StringArray);
9482 a->string = talloc_zero_array(a, const char *, 3);
9483 a->string[0] = talloc_strdup(a->string, "cups6.inf");
9484 a->string[1] = talloc_strdup(a->string, "cups6.ini");
9486 d->info8.dependent_files = a;
9487 d->info8.architecture = d->local.environment;
9489 torture_assert(tctx,
9490 fillup_printserver_info(tctx, p, d),
9491 "failed to fillup printserver info");
9493 if (!directory_exist(d->local.driver_directory)) {
9494 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9497 torture_assert(tctx,
9498 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9499 "failed to upload printer driver");
9501 torture_assert(tctx,
9502 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d->info8, add_flags, true, NULL),
9503 "failed to add driver");
9505 torture_assert(tctx,
9506 test_DeletePrinterDriverEx(tctx, b, server_name_slash,
9507 d->info8.driver_name,
9508 d->local.environment,
9509 delete_flags,
9510 d->info8.version),
9511 "failed to delete driver");
9513 torture_assert(tctx,
9514 check_printer_driver_files(tctx, dcerpc_server_name(p), d, false),
9515 "printer driver file check failed");
9517 talloc_free(d);
9518 return true;
9521 static bool test_del_driver_unused_files(struct torture_context *tctx,
9522 struct dcerpc_pipe *p)
9524 struct torture_driver_context *d1;
9525 struct torture_driver_context *d2;
9526 uint32_t add_flags = APD_COPY_NEW_FILES;
9527 struct dcerpc_binding_handle *b = p->binding_handle;
9528 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9530 d1 = talloc_zero(tctx, struct torture_driver_context);
9531 d1->ex = true;
9532 d1->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9533 d1->info8.driver_name = TORTURE_DRIVER_DELETER;
9534 d1->info8.architecture = NULL;
9535 d1->info8.driver_path = talloc_strdup(d1, "pscript5.dll");
9536 d1->info8.data_file = talloc_strdup(d1, "cups6.ppd");
9537 d1->info8.config_file = talloc_strdup(d1, "cupsui6.dll");
9538 d1->info8.help_file = talloc_strdup(d1, "pscript.hlp");
9539 d1->local.environment = talloc_strdup(d1, SPOOLSS_ARCHITECTURE_x64);
9540 d1->local.driver_directory = talloc_strdup(d1, "/usr/share/cups/drivers/x64");
9541 d1->info8.architecture = d1->local.environment;
9543 d2 = talloc_zero(tctx, struct torture_driver_context);
9544 d2->ex = true;
9545 d2->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9546 d2->info8.driver_name = TORTURE_DRIVER_DELETERIN;
9547 d2->info8.architecture = NULL;
9548 d2->info8.driver_path = talloc_strdup(d2, "pscript5.dll"); /* overlapping */
9549 d2->info8.data_file = talloc_strdup(d2, "cupsps6.dll");
9550 d2->info8.config_file = talloc_strdup(d2, "cups6.ini");
9551 d2->info8.help_file = talloc_strdup(d2, "pscript.hlp"); /* overlapping */
9552 d2->local.environment = talloc_strdup(d2, SPOOLSS_ARCHITECTURE_x64);
9553 d2->local.driver_directory = talloc_strdup(d2, "/usr/share/cups/drivers/x64");
9554 d2->info8.architecture = d2->local.environment;
9556 torture_assert(tctx,
9557 fillup_printserver_info(tctx, p, d1),
9558 "failed to fillup printserver info");
9559 torture_assert(tctx,
9560 fillup_printserver_info(tctx, p, d2),
9561 "failed to fillup printserver info");
9563 if (!directory_exist(d1->local.driver_directory)) {
9564 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9567 torture_assert(tctx,
9568 upload_printer_driver(tctx, dcerpc_server_name(p), d1),
9569 "failed to upload printer driver");
9570 torture_assert(tctx,
9571 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d1->info8, add_flags, true, NULL),
9572 "failed to add driver");
9574 torture_assert(tctx,
9575 upload_printer_driver(tctx, dcerpc_server_name(p), d2),
9576 "failed to upload printer driver");
9577 torture_assert(tctx,
9578 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d2->info8, add_flags, true, NULL),
9579 "failed to add driver");
9581 /* some files are in use by a separate driver, should fail */
9582 torture_assert(tctx,
9583 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9584 d1->info8.driver_name,
9585 d1->local.environment,
9586 DPD_DELETE_ALL_FILES,
9587 d1->info8.version,
9588 WERR_PRINTER_DRIVER_IN_USE),
9589 "invalid delete driver response");
9591 /* should only delete files not in use by other driver */
9592 torture_assert(tctx,
9593 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9594 d1->info8.driver_name,
9595 d1->local.environment,
9596 DPD_DELETE_UNUSED_FILES,
9597 d1->info8.version,
9598 WERR_OK),
9599 "failed to delete driver (unused files)");
9601 /* check non-overlapping were deleted */
9602 d1->info8.driver_path = NULL;
9603 d1->info8.help_file = NULL;
9604 torture_assert(tctx,
9605 check_printer_driver_files(tctx, dcerpc_server_name(p), d1, false),
9606 "printer driver file check failed");
9607 /* d2 files should be uneffected */
9608 torture_assert(tctx,
9609 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, true),
9610 "printer driver file check failed");
9612 torture_assert(tctx,
9613 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9614 d2->info8.driver_name,
9615 d2->local.environment,
9616 DPD_DELETE_ALL_FILES,
9617 d2->info8.version,
9618 WERR_OK),
9619 "failed to delete driver");
9621 torture_assert(tctx,
9622 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, false),
9623 "printer driver file check failed");
9625 talloc_free(d1);
9626 talloc_free(d2);
9627 return true;
9630 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
9632 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
9634 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
9635 "driver", &ndr_table_spoolss);
9636 torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
9637 torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
9639 torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
9640 torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
9642 torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
9644 torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
9646 torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
9648 torture_rpc_tcase_add_test(tcase, "multiple_drivers", test_multiple_drivers);
9650 torture_rpc_tcase_add_test(tcase, "del_driver_all_files", test_del_driver_all_files);
9652 torture_rpc_tcase_add_test(tcase, "del_driver_unused_files", test_del_driver_unused_files);
9654 return suite;