s4:torture:rpc:spoolss: also initialize driverName before checking it in test_Printer...
[Samba/gebeck_regimport.git] / source4 / torture / rpc / spoolss.c
blob75adaf447c7274f3a2788db42e36af896b1edff8
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_SZ("driverName", drivername, "newval");
5503 /* TEST_SET_DWORD("priority", priority, 25); */
5505 torture_assert(tctx,
5506 test_GetPrinter_level(tctx, b, handle, 2, &info),
5507 "failed to query Printer level 2");
5509 TEST_SZ("description", info.info2.comment);
5510 TEST_SZ("driverName", info.info2.drivername);
5511 TEST_SZ("location", info.info2.location);
5513 pname = strrchr(info.info2.printername, '\\');
5514 if (pname == NULL) {
5515 pname = info.info2.printername;
5516 } else {
5517 pname++;
5519 TEST_SZ("printerName", pname);
5520 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5521 /* TEST_SZ("printShareName", info.info2.sharename); */
5523 /* FIXME gd: complete the list */
5525 #undef TEST_SZ
5526 #undef TEST_SET_SZ
5527 #undef TEST_DWORD
5529 torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5531 return true;
5534 static bool test_print_processors_winreg(struct torture_context *tctx,
5535 void *private_data)
5537 struct test_spoolss_context *ctx =
5538 talloc_get_type_abort(private_data, struct test_spoolss_context);
5539 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5540 struct dcerpc_binding_handle *b = p->binding_handle;
5542 return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5545 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5546 struct dcerpc_binding_handle *b,
5547 struct policy_handle *handle,
5548 uint32_t *change_id)
5550 enum winreg_Type type;
5551 uint8_t *data;
5552 uint32_t needed;
5554 torture_assert(tctx,
5555 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5556 "failed to call GetPrinterData");
5558 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5559 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5561 *change_id = IVAL(data, 0);
5563 return true;
5566 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5567 struct dcerpc_pipe *p,
5568 struct policy_handle *handle,
5569 uint32_t *change_id)
5571 enum winreg_Type type;
5572 uint8_t *data;
5573 uint32_t needed;
5575 torture_assert(tctx,
5576 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5577 "failed to call GetPrinterData");
5579 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5580 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5582 *change_id = IVAL(data, 0);
5584 return true;
5587 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5588 struct dcerpc_binding_handle *b,
5589 struct policy_handle *handle,
5590 uint32_t *change_id)
5592 union spoolss_PrinterInfo info;
5594 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5595 "failed to query Printer level 0");
5597 *change_id = info.info0.change_id;
5599 return true;
5602 static bool test_ChangeID(struct torture_context *tctx,
5603 struct dcerpc_pipe *p,
5604 struct policy_handle *handle)
5606 uint32_t change_id, change_id_ex, change_id_info;
5607 uint32_t change_id2, change_id_ex2, change_id_info2;
5608 union spoolss_PrinterInfo info;
5609 const char *comment;
5610 struct dcerpc_binding_handle *b = p->binding_handle;
5612 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5614 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5615 "failed to query for ChangeID");
5616 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5617 "failed to query for ChangeID");
5618 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5619 "failed to query for ChangeID");
5621 torture_assert_int_equal(tctx, change_id, change_id_ex,
5622 "change_ids should all be equal");
5623 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5624 "change_ids should all be equal");
5627 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
5629 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5630 "failed to query for ChangeID");
5631 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5632 "failed to query Printer level 2");
5633 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5634 "failed to query for ChangeID");
5635 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5636 "failed to query for ChangeID");
5637 torture_assert_int_equal(tctx, change_id, change_id_ex,
5638 "change_id should not have changed");
5639 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5640 "change_id should not have changed");
5643 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
5645 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5646 "failed to query for ChangeID");
5647 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5648 "failed to query for ChangeID");
5649 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5650 "failed to query for ChangeID");
5651 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5652 "failed to query Printer level 2");
5653 comment = talloc_strdup(tctx, info.info2.comment);
5656 struct spoolss_SetPrinterInfoCtr info_ctr;
5657 struct spoolss_DevmodeContainer devmode_ctr;
5658 struct sec_desc_buf secdesc_ctr;
5659 union spoolss_SetPrinterInfo sinfo;
5661 ZERO_STRUCT(info_ctr);
5662 ZERO_STRUCT(devmode_ctr);
5663 ZERO_STRUCT(secdesc_ctr);
5666 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5667 sinfo.info2->comment = "torture_comment";
5669 info_ctr.level = 2;
5670 info_ctr.info = sinfo;
5672 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5673 "failed to call SetPrinter");
5675 sinfo.info2->comment = comment;
5677 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5678 "failed to call SetPrinter");
5682 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5683 "failed to query for ChangeID");
5684 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5685 "failed to query for ChangeID");
5686 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5687 "failed to query for ChangeID");
5689 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5690 "change_ids should all be equal");
5691 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5692 "change_ids should all be equal");
5694 torture_assert(tctx, (change_id < change_id2),
5695 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5696 change_id2, change_id));
5697 torture_assert(tctx, (change_id_ex < change_id_ex2),
5698 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5699 change_id_ex2, change_id_ex));
5700 torture_assert(tctx, (change_id_info < change_id_info2),
5701 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5702 change_id_info2, change_id_info));
5704 torture_comment(tctx, "ChangeID tests succeeded\n\n");
5706 return true;
5709 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5710 struct dcerpc_pipe *p,
5711 struct policy_handle *handle)
5713 NTSTATUS status;
5714 struct dcerpc_binding *b;
5715 struct dcerpc_pipe *p2;
5716 struct spoolss_ClosePrinter cp;
5718 /* only makes sense on SMB */
5719 if (p->conn->transport.transport != NCACN_NP) {
5720 return true;
5723 torture_comment(tctx, "Testing close on secondary pipe\n");
5725 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
5726 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
5728 status = dcerpc_secondary_connection(p, &p2, b);
5729 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
5731 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
5732 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
5734 cp.in.handle = handle;
5735 cp.out.handle = handle;
5737 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
5738 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
5739 "ERROR: Allowed close on secondary connection");
5741 talloc_free(p2);
5743 return true;
5746 static bool test_OpenPrinter_badname(struct torture_context *tctx,
5747 struct dcerpc_binding_handle *b, const char *name)
5749 NTSTATUS status;
5750 struct spoolss_OpenPrinter op;
5751 struct spoolss_OpenPrinterEx opEx;
5752 struct policy_handle handle;
5753 bool ret = true;
5755 op.in.printername = name;
5756 op.in.datatype = NULL;
5757 op.in.devmode_ctr.devmode= NULL;
5758 op.in.access_mask = 0;
5759 op.out.handle = &handle;
5761 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
5763 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
5764 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5765 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
5766 "unexpected result");
5768 if (W_ERROR_IS_OK(op.out.result)) {
5769 ret &=test_ClosePrinter(tctx, b, &handle);
5772 opEx.in.printername = name;
5773 opEx.in.datatype = NULL;
5774 opEx.in.devmode_ctr.devmode = NULL;
5775 opEx.in.access_mask = 0;
5776 opEx.in.level = 1;
5777 opEx.in.userlevel.level1 = NULL;
5778 opEx.out.handle = &handle;
5780 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
5782 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
5783 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5784 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
5785 "unexpected result");
5787 if (W_ERROR_IS_OK(opEx.out.result)) {
5788 ret &=test_ClosePrinter(tctx, b, &handle);
5791 return ret;
5794 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
5795 void *private_data)
5797 struct test_spoolss_context *ctx =
5798 talloc_get_type_abort(private_data, struct test_spoolss_context);
5800 const char *badnames[] = {
5801 "__INVALID_PRINTER__",
5802 "\\\\__INVALID_HOST__",
5804 "\\\\\\",
5805 "\\\\\\__INVALID_PRINTER__"
5807 const char *badname;
5808 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5809 const char *server_name = dcerpc_server_name(p);
5810 struct dcerpc_binding_handle *b = p->binding_handle;
5811 int i;
5813 for (i=0; i < ARRAY_SIZE(badnames); i++) {
5814 torture_assert(tctx,
5815 test_OpenPrinter_badname(tctx, b, badnames[i]),
5816 "");
5819 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
5820 torture_assert(tctx,
5821 test_OpenPrinter_badname(tctx, b, badname),
5822 "");
5824 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
5825 torture_assert(tctx,
5826 test_OpenPrinter_badname(tctx, b, badname),
5827 "");
5829 return true;
5832 static bool test_OpenPrinter(struct torture_context *tctx,
5833 struct dcerpc_pipe *p,
5834 const char *name,
5835 const char *environment,
5836 bool open_only)
5838 NTSTATUS status;
5839 struct spoolss_OpenPrinter r;
5840 struct policy_handle handle;
5841 bool ret = true;
5842 struct dcerpc_binding_handle *b = p->binding_handle;
5844 r.in.printername = name;
5845 r.in.datatype = NULL;
5846 r.in.devmode_ctr.devmode= NULL;
5847 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5848 r.out.handle = &handle;
5850 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5852 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5854 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5856 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5858 if (open_only) {
5859 goto close_printer;
5862 if (!test_GetPrinter(tctx, b, &handle, environment)) {
5863 ret = false;
5866 if (!torture_setting_bool(tctx, "samba3", false)) {
5867 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5868 ret = false;
5872 close_printer:
5873 if (!test_ClosePrinter(tctx, b, &handle)) {
5874 ret = false;
5877 return ret;
5880 static bool test_OpenPrinterEx(struct torture_context *tctx,
5881 struct dcerpc_binding_handle *b,
5882 const char *printername,
5883 const char *datatype,
5884 struct spoolss_DeviceMode *devmode,
5885 uint32_t access_mask,
5886 uint32_t level,
5887 union spoolss_UserLevel *userlevel,
5888 struct policy_handle *handle,
5889 WERROR expected_result)
5891 struct spoolss_OpenPrinterEx r;
5893 r.in.printername = printername;
5894 r.in.datatype = datatype;
5895 r.in.devmode_ctr.devmode= devmode;
5896 r.in.access_mask = access_mask;
5897 r.in.level = level;
5898 r.in.userlevel = *userlevel;
5899 r.out.handle = handle;
5901 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5903 torture_assert_ntstatus_ok(tctx,
5904 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
5905 "OpenPrinterEx failed");
5907 torture_assert_werr_equal(tctx, r.out.result, expected_result,
5908 "OpenPrinterEx failed");
5910 return true;
5913 static bool call_OpenPrinterEx(struct torture_context *tctx,
5914 struct dcerpc_pipe *p,
5915 const char *name,
5916 struct spoolss_DeviceMode *devmode,
5917 struct policy_handle *handle)
5919 union spoolss_UserLevel userlevel;
5920 struct spoolss_UserLevel1 userlevel1;
5921 struct dcerpc_binding_handle *b = p->binding_handle;
5923 userlevel1.size = 1234;
5924 userlevel1.client = "hello";
5925 userlevel1.user = "spottyfoot!";
5926 userlevel1.build = 1;
5927 userlevel1.major = 2;
5928 userlevel1.minor = 3;
5929 userlevel1.processor = 4;
5931 userlevel.level1 = &userlevel1;
5933 return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
5934 SEC_FLAG_MAXIMUM_ALLOWED,
5936 &userlevel,
5937 handle,
5938 WERR_OK);
5941 static bool test_printer_rename(struct torture_context *tctx,
5942 void *private_data)
5944 struct torture_printer_context *t =
5945 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
5946 struct dcerpc_pipe *p = t->spoolss_pipe;
5948 bool ret = true;
5949 union spoolss_PrinterInfo info;
5950 union spoolss_SetPrinterInfo sinfo;
5951 struct spoolss_SetPrinterInfoCtr info_ctr;
5952 struct spoolss_DevmodeContainer devmode_ctr;
5953 struct sec_desc_buf secdesc_ctr;
5954 const char *printer_name;
5955 const char *printer_name_orig;
5956 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5957 struct policy_handle new_handle;
5958 const char *q;
5959 struct dcerpc_binding_handle *b = p->binding_handle;
5961 ZERO_STRUCT(devmode_ctr);
5962 ZERO_STRUCT(secdesc_ctr);
5964 torture_comment(tctx, "Testing Printer rename operations\n");
5966 torture_assert(tctx,
5967 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5968 "failed to call GetPrinter level 2");
5970 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5972 q = strrchr(info.info2.printername, '\\');
5973 if (q) {
5974 torture_warning(tctx,
5975 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5978 torture_assert(tctx,
5979 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5981 sinfo.info2->printername = printer_name_new;
5983 info_ctr.level = 2;
5984 info_ctr.info = sinfo;
5986 torture_assert(tctx,
5987 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5988 "failed to call SetPrinter level 2");
5990 torture_assert(tctx,
5991 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5992 "failed to call GetPrinter level 2");
5994 printer_name = talloc_strdup(tctx, info.info2.printername);
5996 q = strrchr(info.info2.printername, '\\');
5997 if (q) {
5998 torture_warning(tctx,
5999 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6000 q++;
6001 printer_name = q;
6004 torture_assert_str_equal(tctx, printer_name, printer_name_new,
6005 "new printer name was not set");
6007 /* samba currently cannot fully rename printers */
6008 if (!torture_setting_bool(tctx, "samba3", false)) {
6009 torture_assert(tctx,
6010 test_OpenPrinter_badname(tctx, b, printer_name_orig),
6011 "still can open printer with oldname after rename");
6012 } else {
6013 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
6016 torture_assert(tctx,
6017 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
6018 "failed to open printer with new name");
6020 torture_assert(tctx,
6021 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
6022 "failed to call GetPrinter level 2");
6024 torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
6025 "new printer name was not set");
6027 torture_assert(tctx,
6028 test_ClosePrinter(tctx, b, &new_handle),
6029 "failed to close printer");
6031 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
6033 return ret;
6036 static bool test_openprinter(struct torture_context *tctx,
6037 struct dcerpc_binding_handle *b,
6038 const char *real_printername)
6040 union spoolss_UserLevel userlevel;
6041 struct policy_handle handle;
6042 struct spoolss_UserLevel1 userlevel1;
6043 const char *printername = NULL;
6044 int i;
6046 struct {
6047 const char *suffix;
6048 WERROR expected_result;
6049 } tests[] = {
6051 .suffix = "rubbish",
6052 .expected_result = WERR_INVALID_PRINTER_NAME
6054 .suffix = ", LocalOnl",
6055 .expected_result = WERR_INVALID_PRINTER_NAME
6057 .suffix = ", localOnly",
6058 .expected_result = WERR_INVALID_PRINTER_NAME
6060 .suffix = ", localonl",
6061 .expected_result = WERR_INVALID_PRINTER_NAME
6063 .suffix = ",LocalOnl",
6064 .expected_result = WERR_INVALID_PRINTER_NAME
6066 .suffix = ",localOnl2",
6067 .expected_result = WERR_INVALID_PRINTER_NAME
6069 .suffix = ", DrvConver2t",
6070 .expected_result = WERR_INVALID_PRINTER_NAME
6072 .suffix = ", drvconvert",
6073 .expected_result = WERR_INVALID_PRINTER_NAME
6075 .suffix = ",drvconvert",
6076 .expected_result = WERR_INVALID_PRINTER_NAME
6078 .suffix = ", DrvConvert",
6079 .expected_result = WERR_OK
6081 .suffix = " , DrvConvert",
6082 .expected_result = WERR_INVALID_PRINTER_NAME
6084 .suffix = ",DrvConvert",
6085 .expected_result = WERR_OK
6087 .suffix = ", DrvConvertsadfasdf",
6088 .expected_result = WERR_OK
6090 .suffix = ",DrvConvertasdfasd",
6091 .expected_result = WERR_OK
6093 .suffix = ", LocalOnly",
6094 .expected_result = WERR_OK
6096 .suffix = " , LocalOnly",
6097 .expected_result = WERR_INVALID_PRINTER_NAME
6099 .suffix = ",LocalOnly",
6100 .expected_result = WERR_OK
6102 .suffix = ", LocalOnlysagi4gjfkd",
6103 .expected_result = WERR_OK
6105 .suffix = ",LocalOnlysagi4gjfkd",
6106 .expected_result = WERR_OK
6110 userlevel1.size = 1234;
6111 userlevel1.client = "hello";
6112 userlevel1.user = "spottyfoot!";
6113 userlevel1.build = 1;
6114 userlevel1.major = 2;
6115 userlevel1.minor = 3;
6116 userlevel1.processor = 4;
6118 userlevel.level1 = &userlevel1;
6120 torture_comment(tctx, "Testing openprinterex printername pattern\n");
6122 torture_assert(tctx,
6123 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0, 1,
6124 &userlevel, &handle,
6125 WERR_OK),
6126 "OpenPrinterEx failed");
6127 test_ClosePrinter(tctx, b, &handle);
6129 for (i=0; i < ARRAY_SIZE(tests); i++) {
6131 printername = talloc_asprintf(tctx, "%s%s",
6132 real_printername,
6133 tests[i].suffix);
6135 torture_assert(tctx,
6136 test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0, 1,
6137 &userlevel, &handle,
6138 tests[i].expected_result),
6139 "OpenPrinterEx failed");
6140 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6141 test_ClosePrinter(tctx, b, &handle);
6145 return true;
6149 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6150 struct dcerpc_pipe *p,
6151 const char *name,
6152 const char *environment)
6154 struct policy_handle handle;
6155 bool ret = true;
6156 struct dcerpc_binding_handle *b = p->binding_handle;
6158 if (!test_openprinter(tctx, b, name)) {
6159 return false;
6162 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6163 return false;
6166 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6167 ret = false;
6170 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6171 ret = false;
6174 if (!test_EnumForms_all(tctx, b, &handle, false)) {
6175 ret = false;
6178 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6179 ret = false;
6182 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6183 ret = false;
6186 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6187 ret = false;
6190 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6191 ret = false;
6194 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6195 ret = false;
6198 if (!test_printer_all_keys(tctx, b, &handle)) {
6199 ret = false;
6202 if (!test_PausePrinter(tctx, b, &handle)) {
6203 ret = false;
6206 if (!test_DoPrintTest(tctx, b, &handle)) {
6207 ret = false;
6210 if (!test_ResumePrinter(tctx, b, &handle)) {
6211 ret = false;
6214 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
6215 ret = false;
6218 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
6219 ret = false;
6222 if (!torture_setting_bool(tctx, "samba3", false)) {
6223 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6224 ret = false;
6228 if (!test_ClosePrinter(tctx, b, &handle)) {
6229 ret = false;
6232 return ret;
6235 static bool test_EnumPrinters_old(struct torture_context *tctx,
6236 void *private_data)
6238 struct test_spoolss_context *ctx =
6239 talloc_get_type_abort(private_data, struct test_spoolss_context);
6240 struct spoolss_EnumPrinters r;
6241 NTSTATUS status;
6242 uint16_t levels[] = {1, 2, 4, 5};
6243 int i;
6244 bool ret = true;
6245 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6246 struct dcerpc_binding_handle *b = p->binding_handle;
6248 for (i=0;i<ARRAY_SIZE(levels);i++) {
6249 union spoolss_PrinterInfo *info;
6250 int j;
6251 uint32_t needed;
6252 uint32_t count;
6254 r.in.flags = PRINTER_ENUM_LOCAL;
6255 r.in.server = "";
6256 r.in.level = levels[i];
6257 r.in.buffer = NULL;
6258 r.in.offered = 0;
6259 r.out.needed = &needed;
6260 r.out.count = &count;
6261 r.out.info = &info;
6263 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6265 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6266 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6268 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6269 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6270 r.in.buffer = &blob;
6271 r.in.offered = needed;
6272 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6275 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6277 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6279 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6281 if (!info) {
6282 torture_comment(tctx, "No printers returned\n");
6283 return true;
6286 for (j=0;j<count;j++) {
6287 if (r.in.level == 1) {
6288 char *unc = talloc_strdup(tctx, info[j].info1.name);
6289 char *slash, *name, *full_name;
6290 name = unc;
6291 if (unc[0] == '\\' && unc[1] == '\\') {
6292 unc +=2;
6294 slash = strchr(unc, '\\');
6295 if (slash) {
6296 slash++;
6297 name = slash;
6299 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6300 dcerpc_server_name(p), name);
6301 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6302 ret = false;
6304 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6305 ret = false;
6307 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6308 ret = false;
6310 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6311 ret = false;
6317 return ret;
6320 static bool test_EnumPrinters_level(struct torture_context *tctx,
6321 struct dcerpc_binding_handle *b,
6322 uint32_t flags,
6323 const char *servername,
6324 uint32_t level,
6325 uint32_t *count_p,
6326 union spoolss_PrinterInfo **info_p)
6328 struct spoolss_EnumPrinters r;
6329 union spoolss_PrinterInfo *info;
6330 uint32_t needed;
6331 uint32_t count;
6333 r.in.flags = flags;
6334 r.in.server = servername;
6335 r.in.level = level;
6336 r.in.buffer = NULL;
6337 r.in.offered = 0;
6338 r.out.needed = &needed;
6339 r.out.count = &count;
6340 r.out.info = &info;
6342 torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6343 r.in.server, r.in.level);
6345 torture_assert_ntstatus_ok(tctx,
6346 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6347 "EnumPrinters failed");
6348 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6349 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6350 r.in.buffer = &blob;
6351 r.in.offered = needed;
6352 torture_assert_ntstatus_ok(tctx,
6353 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6354 "EnumPrinters failed");
6357 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6359 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6361 if (count_p) {
6362 *count_p = count;
6364 if (info_p) {
6365 *info_p = info;
6368 return true;
6371 static const char *get_short_printername(struct torture_context *tctx,
6372 const char *name)
6374 const char *short_name;
6376 if (name[0] == '\\' && name[1] == '\\') {
6377 name += 2;
6378 short_name = strchr(name, '\\');
6379 if (short_name) {
6380 return talloc_strdup(tctx, short_name+1);
6384 return name;
6387 static const char *get_full_printername(struct torture_context *tctx,
6388 const char *name)
6390 const char *full_name = talloc_strdup(tctx, name);
6391 char *p;
6393 if (name && name[0] == '\\' && name[1] == '\\') {
6394 name += 2;
6395 p = strchr(name, '\\');
6396 if (p) {
6397 return full_name;
6401 return NULL;
6404 static bool test_OnePrinter_servername(struct torture_context *tctx,
6405 struct dcerpc_pipe *p,
6406 struct dcerpc_binding_handle *b,
6407 const char *servername,
6408 const char *printername)
6410 union spoolss_PrinterInfo info;
6411 const char *short_name = get_short_printername(tctx, printername);
6412 const char *full_name = get_full_printername(tctx, printername);
6414 if (short_name) {
6415 struct policy_handle handle;
6416 torture_assert(tctx,
6417 call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
6418 "failed to open printer");
6420 torture_assert(tctx,
6421 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6422 "failed to get printer info");
6424 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
6425 "unexpected servername");
6426 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
6427 "unexpected printername");
6429 if (info.info2.devmode) {
6430 const char *expected_devicename;
6431 expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
6432 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6433 "unexpected devicemode devicename");
6436 torture_assert(tctx,
6437 test_ClosePrinter(tctx, b, &handle),
6438 "failed to close printer");
6441 if (full_name) {
6442 struct policy_handle handle;
6444 torture_assert(tctx,
6445 call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
6446 "failed to open printer");
6448 torture_assert(tctx,
6449 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6450 "failed to get printer info");
6452 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
6453 "unexpected servername");
6454 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
6455 "unexpected printername");
6457 if (info.info2.devmode) {
6458 const char *expected_devicename;
6459 expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
6460 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6461 "unexpected devicemode devicename");
6464 torture_assert(tctx,
6465 test_ClosePrinter(tctx, b, &handle),
6466 "failed to close printer");
6469 return true;
6472 static bool test_EnumPrinters_servername(struct torture_context *tctx,
6473 void *private_data)
6475 struct test_spoolss_context *ctx =
6476 talloc_get_type_abort(private_data, struct test_spoolss_context);
6477 int i;
6478 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6479 struct dcerpc_binding_handle *b = p->binding_handle;
6480 uint32_t count;
6481 union spoolss_PrinterInfo *info;
6482 const char *servername;
6483 uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
6485 torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6487 servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6489 torture_assert(tctx,
6490 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6491 "failed to enumerate printers");
6493 for (i=0; i < count; i++) {
6495 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
6496 "unexpected servername");
6498 torture_assert(tctx,
6499 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6500 "failed to check printer");
6503 servername = "";
6505 torture_assert(tctx,
6506 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6507 "failed to enumerate printers");
6509 for (i=0; i < count; i++) {
6511 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
6512 "unexpected servername");
6514 torture_assert(tctx,
6515 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6516 "failed to check printer");
6520 return true;
6524 static bool test_GetPrinterDriver(struct torture_context *tctx,
6525 struct dcerpc_binding_handle *b,
6526 struct policy_handle *handle,
6527 const char *driver_name)
6529 struct spoolss_GetPrinterDriver r;
6530 uint32_t needed;
6532 r.in.handle = handle;
6533 r.in.architecture = "W32X86";
6534 r.in.level = 1;
6535 r.in.buffer = NULL;
6536 r.in.offered = 0;
6537 r.out.needed = &needed;
6539 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
6541 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6542 "failed to call GetPrinterDriver");
6543 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6544 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6545 r.in.buffer = &blob;
6546 r.in.offered = needed;
6547 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6548 "failed to call GetPrinterDriver");
6551 torture_assert_werr_ok(tctx, r.out.result,
6552 "failed to call GetPrinterDriver");
6554 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6556 return true;
6559 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
6560 struct dcerpc_binding_handle *b,
6561 struct policy_handle *handle,
6562 const char *driver_name,
6563 const char *architecture,
6564 uint32_t level,
6565 uint32_t client_major_version,
6566 uint32_t client_minor_version,
6567 union spoolss_DriverInfo *info_p,
6568 WERROR *result_p)
6571 struct spoolss_GetPrinterDriver2 r;
6572 uint32_t needed;
6573 uint32_t server_major_version;
6574 uint32_t server_minor_version;
6576 r.in.handle = handle;
6577 r.in.architecture = architecture;
6578 r.in.client_major_version = client_major_version;
6579 r.in.client_minor_version = client_minor_version;
6580 r.in.buffer = NULL;
6581 r.in.offered = 0;
6582 r.in.level = level;
6583 r.out.needed = &needed;
6584 r.out.server_major_version = &server_major_version;
6585 r.out.server_minor_version = &server_minor_version;
6587 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
6588 driver_name, r.in.level);
6590 torture_assert_ntstatus_ok(tctx,
6591 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6592 "failed to call GetPrinterDriver2");
6593 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6594 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6595 r.in.buffer = &blob;
6596 r.in.offered = needed;
6597 torture_assert_ntstatus_ok(tctx,
6598 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6599 "failed to call GetPrinterDriver2");
6602 if (result_p) {
6603 *result_p = r.out.result;
6606 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
6607 switch (r.in.level) {
6608 case 101:
6609 case 8:
6610 torture_comment(tctx,
6611 "level %d not implemented, not considering as an error\n",
6612 r.in.level);
6613 return true;
6614 default:
6615 break;
6619 torture_assert_werr_ok(tctx, r.out.result,
6620 "failed to call GetPrinterDriver2");
6622 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6624 if (info_p) {
6625 *info_p = *r.out.info;
6628 return true;
6631 static bool test_GetPrinterDriver2(struct torture_context *tctx,
6632 struct dcerpc_binding_handle *b,
6633 struct policy_handle *handle,
6634 const char *driver_name,
6635 const char *architecture)
6637 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
6638 int i;
6641 for (i=0;i<ARRAY_SIZE(levels);i++) {
6643 torture_assert(tctx,
6644 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
6645 "");
6648 return true;
6651 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
6652 void *private_data)
6654 struct test_spoolss_context *ctx =
6655 talloc_get_type_abort(private_data, struct test_spoolss_context);
6656 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
6657 int i;
6658 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6659 struct dcerpc_binding_handle *b = p->binding_handle;
6660 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6662 for (i=0;i<ARRAY_SIZE(levels);i++) {
6664 uint32_t count;
6665 union spoolss_DriverInfo *info;
6667 torture_assert(tctx,
6668 test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
6669 "failed to enumerate drivers");
6671 if (!info) {
6672 torture_comment(tctx, "No printer drivers returned\n");
6673 break;
6677 return true;
6680 static bool test_DeletePrinter(struct torture_context *tctx,
6681 struct dcerpc_binding_handle *b,
6682 struct policy_handle *handle)
6684 struct spoolss_DeletePrinter r;
6686 torture_comment(tctx, "Testing DeletePrinter\n");
6688 r.in.handle = handle;
6690 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
6691 "failed to delete printer");
6692 torture_assert_werr_ok(tctx, r.out.result,
6693 "failed to delete printer");
6695 return true;
6698 static bool test_EnumPrinters_findname(struct torture_context *tctx,
6699 struct dcerpc_binding_handle *b,
6700 uint32_t flags,
6701 uint32_t level,
6702 const char *name,
6703 bool *found)
6705 struct spoolss_EnumPrinters e;
6706 uint32_t count;
6707 union spoolss_PrinterInfo *info;
6708 uint32_t needed;
6709 int i;
6711 *found = false;
6713 e.in.flags = flags;
6714 e.in.server = NULL;
6715 e.in.level = level;
6716 e.in.buffer = NULL;
6717 e.in.offered = 0;
6718 e.out.count = &count;
6719 e.out.info = &info;
6720 e.out.needed = &needed;
6722 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6723 "failed to enum printers");
6725 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
6726 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6727 e.in.buffer = &blob;
6728 e.in.offered = needed;
6730 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6731 "failed to enum printers");
6734 torture_assert_werr_ok(tctx, e.out.result,
6735 "failed to enum printers");
6737 for (i=0; i < count; i++) {
6739 const char *current = NULL;
6740 const char *q;
6742 switch (level) {
6743 case 1:
6744 current = info[i].info1.name;
6745 break;
6748 if (strequal(current, name)) {
6749 *found = true;
6750 break;
6753 q = strrchr(current, '\\');
6754 if (q) {
6755 if (!e.in.server) {
6756 torture_warning(tctx,
6757 "server returns printername %s incl. servername although we did not set servername", current);
6759 q++;
6760 if (strequal(q, name)) {
6761 *found = true;
6762 break;
6767 return true;
6770 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
6771 struct dcerpc_pipe *p,
6772 const char *printername,
6773 bool ex)
6775 WERROR result;
6776 struct spoolss_AddPrinter r;
6777 struct spoolss_AddPrinterEx rex;
6778 struct spoolss_SetPrinterInfoCtr info_ctr;
6779 struct spoolss_SetPrinterInfo1 info1;
6780 struct spoolss_DevmodeContainer devmode_ctr;
6781 struct sec_desc_buf secdesc_ctr;
6782 struct spoolss_UserLevelCtr userlevel_ctr;
6783 struct policy_handle handle;
6784 bool found = false;
6785 struct dcerpc_binding_handle *b = p->binding_handle;
6787 ZERO_STRUCT(devmode_ctr);
6788 ZERO_STRUCT(secdesc_ctr);
6789 ZERO_STRUCT(userlevel_ctr);
6790 ZERO_STRUCT(info1);
6792 torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
6793 ex ? "Ex":"", printername);
6795 /* try to add printer to wellknown printer list (level 1) */
6797 userlevel_ctr.level = 1;
6799 info_ctr.info.info1 = &info1;
6800 info_ctr.level = 1;
6802 rex.in.server = NULL;
6803 rex.in.info_ctr = &info_ctr;
6804 rex.in.devmode_ctr = &devmode_ctr;
6805 rex.in.secdesc_ctr = &secdesc_ctr;
6806 rex.in.userlevel_ctr = &userlevel_ctr;
6807 rex.out.handle = &handle;
6809 r.in.server = NULL;
6810 r.in.info_ctr = &info_ctr;
6811 r.in.devmode_ctr = &devmode_ctr;
6812 r.in.secdesc_ctr = &secdesc_ctr;
6813 r.out.handle = &handle;
6815 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6816 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6817 "failed to add printer");
6818 result = ex ? rex.out.result : r.out.result;
6819 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6820 "unexpected result code");
6822 info1.name = printername;
6823 info1.flags = PRINTER_ATTRIBUTE_SHARED;
6825 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6826 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6827 "failed to add printer");
6828 result = ex ? rex.out.result : r.out.result;
6829 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6830 "unexpected result code");
6832 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6833 better do a real check to see the printer is really there */
6835 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6836 PRINTER_ENUM_NETWORK, 1,
6837 printername,
6838 &found),
6839 "failed to enum printers");
6841 torture_assert(tctx, found, "failed to find newly added printer");
6843 info1.flags = 0;
6845 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6846 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6847 "failed to add printer");
6848 result = ex ? rex.out.result : r.out.result;
6849 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6850 "unexpected result code");
6852 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6853 better do a real check to see the printer has really been removed
6854 from the well known printer list */
6856 found = false;
6858 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6859 PRINTER_ENUM_NETWORK, 1,
6860 printername,
6861 &found),
6862 "failed to enum printers");
6863 #if 0
6864 torture_assert(tctx, !found, "printer still in well known printer list");
6865 #endif
6866 return true;
6869 static bool test_AddPrinter_normal(struct torture_context *tctx,
6870 struct dcerpc_pipe *p,
6871 struct policy_handle *handle_p,
6872 const char *printername,
6873 const char *drivername,
6874 const char *portname,
6875 struct spoolss_DeviceMode *devmode,
6876 bool ex)
6878 WERROR result;
6879 struct spoolss_AddPrinter r;
6880 struct spoolss_AddPrinterEx rex;
6881 struct spoolss_SetPrinterInfoCtr info_ctr;
6882 struct spoolss_SetPrinterInfo2 info2;
6883 struct spoolss_DevmodeContainer devmode_ctr;
6884 struct sec_desc_buf secdesc_ctr;
6885 struct spoolss_UserLevelCtr userlevel_ctr;
6886 struct policy_handle handle;
6887 bool found = false;
6888 bool existing_printer_deleted = false;
6889 struct dcerpc_binding_handle *b = p->binding_handle;
6891 ZERO_STRUCT(devmode_ctr);
6892 ZERO_STRUCT(secdesc_ctr);
6893 ZERO_STRUCT(userlevel_ctr);
6895 torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
6896 ex ? "Ex":"", printername);
6898 devmode_ctr.devmode = devmode;
6900 userlevel_ctr.level = 1;
6902 rex.in.server = NULL;
6903 rex.in.info_ctr = &info_ctr;
6904 rex.in.devmode_ctr = &devmode_ctr;
6905 rex.in.secdesc_ctr = &secdesc_ctr;
6906 rex.in.userlevel_ctr = &userlevel_ctr;
6907 rex.out.handle = &handle;
6909 r.in.server = NULL;
6910 r.in.info_ctr = &info_ctr;
6911 r.in.devmode_ctr = &devmode_ctr;
6912 r.in.secdesc_ctr = &secdesc_ctr;
6913 r.out.handle = &handle;
6915 again:
6917 /* try to add printer to printer list (level 2) */
6919 ZERO_STRUCT(info2);
6921 info_ctr.info.info2 = &info2;
6922 info_ctr.level = 2;
6924 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6925 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6926 "failed to add printer");
6927 result = ex ? rex.out.result : r.out.result;
6928 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6929 "unexpected result code");
6931 info2.printername = printername;
6933 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6934 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6935 "failed to add printer");
6936 result = ex ? rex.out.result : r.out.result;
6938 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
6939 struct policy_handle printer_handle;
6941 if (existing_printer_deleted) {
6942 torture_fail(tctx, "already deleted printer still existing?");
6945 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
6946 "failed to open printer handle");
6948 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
6949 "failed to delete printer");
6951 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
6952 "failed to close server handle");
6954 existing_printer_deleted = true;
6956 goto again;
6959 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
6960 "unexpected result code");
6962 info2.portname = portname;
6964 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6965 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6966 "failed to add printer");
6967 result = ex ? rex.out.result : r.out.result;
6968 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
6969 "unexpected result code");
6971 info2.drivername = drivername;
6973 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6974 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6975 "failed to add printer");
6976 result = ex ? rex.out.result : r.out.result;
6978 /* w2k8r2 allows to add printer w/o defining printprocessor */
6980 if (!W_ERROR_IS_OK(result)) {
6981 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
6982 "unexpected result code");
6984 info2.printprocessor = "winprint";
6986 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6987 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6988 "failed to add printer");
6989 result = ex ? rex.out.result : r.out.result;
6990 torture_assert_werr_ok(tctx, result,
6991 "failed to add printer");
6994 *handle_p = handle;
6996 /* we are paranoid, really check if the printer is there now */
6998 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6999 PRINTER_ENUM_LOCAL, 1,
7000 printername,
7001 &found),
7002 "failed to enum printers");
7003 torture_assert(tctx, found, "failed to find newly added printer");
7005 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7006 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7007 "failed to add printer");
7008 result = ex ? rex.out.result : r.out.result;
7009 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7010 "unexpected result code");
7012 return true;
7015 static bool test_printer_info(struct torture_context *tctx,
7016 void *private_data)
7018 struct torture_printer_context *t =
7019 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7020 struct dcerpc_pipe *p = t->spoolss_pipe;
7021 struct dcerpc_binding_handle *b = p->binding_handle;
7023 bool ret = true;
7025 if (torture_setting_bool(tctx, "samba3", false)) {
7026 torture_skip(tctx, "skipping printer info cross tests against samba 3");
7029 if (!test_PrinterInfo(tctx, b, &t->handle)) {
7030 ret = false;
7033 if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
7034 ret = false;
7037 return ret;
7040 static bool test_EnumPrinterKey(struct torture_context *tctx,
7041 struct dcerpc_binding_handle *b,
7042 struct policy_handle *handle,
7043 const char *key_name,
7044 const char ***array)
7046 struct spoolss_EnumPrinterKey r;
7047 uint32_t needed = 0;
7048 union spoolss_KeyNames key_buffer;
7049 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7050 uint32_t _ndr_size;
7051 int i;
7053 r.in.handle = handle;
7054 r.in.key_name = key_name;
7055 r.out.key_buffer = &key_buffer;
7056 r.out.needed = &needed;
7057 r.out._ndr_size = &_ndr_size;
7059 for (i=0; i < ARRAY_SIZE(offered); i++) {
7061 if (offered[i] < 0 && needed) {
7062 if (needed <= 4) {
7063 continue;
7065 r.in.offered = needed + offered[i];
7066 } else {
7067 r.in.offered = offered[i];
7070 ZERO_STRUCT(key_buffer);
7072 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
7074 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7075 "failed to call EnumPrinterKey");
7076 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
7078 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7079 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7080 _ndr_size, r.in.offered/2));
7082 r.in.offered = needed;
7083 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7084 "failed to call EnumPrinterKey");
7087 if (offered[i] > 0) {
7088 torture_assert_werr_ok(tctx, r.out.result,
7089 "failed to call EnumPrinterKey");
7092 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7093 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7094 _ndr_size, r.in.offered/2));
7096 torture_assert(tctx, (*r.out.needed <= r.in.offered),
7097 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
7099 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
7100 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
7102 if (key_buffer.string_array) {
7103 uint32_t calc_needed = 0;
7104 int s;
7105 for (s=0; key_buffer.string_array[s]; s++) {
7106 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7108 if (!key_buffer.string_array[0]) {
7109 calc_needed += 2;
7111 calc_needed += 2;
7113 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7114 "EnumPrinterKey unexpected size");
7118 if (array) {
7119 *array = key_buffer.string_array;
7122 return true;
7125 bool test_printer_all_keys(struct torture_context *tctx,
7126 struct dcerpc_binding_handle *b,
7127 struct policy_handle *handle)
7129 const char **key_array = NULL;
7130 int i;
7132 torture_comment(tctx, "Testing Printer Keys\n");
7134 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7135 "failed to call test_EnumPrinterKey");
7137 for (i=0; key_array && key_array[i]; i++) {
7138 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7139 "failed to call test_EnumPrinterKey");
7141 for (i=0; key_array && key_array[i]; i++) {
7142 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7143 "failed to call test_EnumPrinterDataEx");
7146 torture_comment(tctx, "Printer Keys test succeeded\n\n");
7148 return true;
7151 static bool test_openprinter_wrap(struct torture_context *tctx,
7152 void *private_data)
7154 struct torture_printer_context *t =
7155 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7156 struct dcerpc_pipe *p = t->spoolss_pipe;
7157 struct dcerpc_binding_handle *b = p->binding_handle;
7158 const char *printername = t->info2.printername;
7160 return test_openprinter(tctx, b, printername);
7163 static bool test_csetprinter(struct torture_context *tctx,
7164 void *private_data)
7166 struct torture_printer_context *t =
7167 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7168 struct dcerpc_pipe *p = t->spoolss_pipe;
7170 const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7171 const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7172 const char *portname = t->info2.portname;
7174 union spoolss_PrinterInfo info;
7175 struct policy_handle new_handle, new_handle2;
7176 struct dcerpc_binding_handle *b = p->binding_handle;
7178 torture_comment(tctx, "Testing c_setprinter\n");
7180 torture_assert(tctx,
7181 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7182 "failed to get level 0 printer info");
7183 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7184 info.info0.c_setprinter);
7186 /* check if c_setprinter on 1st handle increases after a printer has
7187 * been added */
7189 torture_assert(tctx,
7190 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7191 "failed to add new printer");
7192 torture_assert(tctx,
7193 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7194 "failed to get level 0 printer info");
7195 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7196 info.info0.c_setprinter);
7198 /* check if c_setprinter on new handle increases after a printer has
7199 * been added */
7201 torture_assert(tctx,
7202 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7203 "failed to get level 0 printer info");
7204 torture_comment(tctx, "csetprinter on created handle: %d\n",
7205 info.info0.c_setprinter);
7207 /* open the new printer and check if c_setprinter increases */
7209 torture_assert(tctx,
7210 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7211 "failed to open created printer");
7212 torture_assert(tctx,
7213 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
7214 "failed to get level 0 printer info");
7215 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
7216 info.info0.c_setprinter);
7218 /* cleanup */
7220 torture_assert(tctx,
7221 test_ClosePrinter(tctx, b, &new_handle2),
7222 "failed to close printer");
7223 torture_assert(tctx,
7224 test_DeletePrinter(tctx, b, &new_handle),
7225 "failed to delete new printer");
7227 return true;
7230 static bool compose_local_driver_directory(struct torture_context *tctx,
7231 const char *environment,
7232 const char *local_dir,
7233 const char **path)
7235 char *p;
7237 p = strrchr(local_dir, '/');
7238 if (!p) {
7239 return NULL;
7241 p++;
7243 if (strequal(environment, "Windows x64")) {
7244 if (!strequal(p, "x64")) {
7245 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
7247 } else if (strequal(environment, "Windows NT x86")) {
7248 if (!strequal(p, "i386")) {
7249 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
7251 } else {
7252 torture_assert(tctx, "unknown environment: '%s'\n", environment);
7255 return true;
7258 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
7259 const char *devicename)
7261 struct spoolss_DeviceMode *r;
7263 r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
7264 if (r == NULL) {
7265 return NULL;
7268 r->devicename = talloc_strdup(r, devicename);
7269 r->specversion = DMSPEC_NT4_AND_ABOVE;
7270 r->driverversion = 0x0600;
7271 r->size = 0x00dc;
7272 r->__driverextra_length = 0;
7273 r->fields = DEVMODE_FORMNAME |
7274 DEVMODE_TTOPTION |
7275 DEVMODE_PRINTQUALITY |
7276 DEVMODE_DEFAULTSOURCE |
7277 DEVMODE_COPIES |
7278 DEVMODE_SCALE |
7279 DEVMODE_PAPERSIZE |
7280 DEVMODE_ORIENTATION;
7281 r->orientation = DMORIENT_PORTRAIT;
7282 r->papersize = DMPAPER_LETTER;
7283 r->paperlength = 0;
7284 r->paperwidth = 0;
7285 r->scale = 100;
7286 r->copies = 55;
7287 r->defaultsource = DMBIN_FORMSOURCE;
7288 r->printquality = DMRES_HIGH;
7289 r->color = DMRES_MONOCHROME;
7290 r->duplex = DMDUP_SIMPLEX;
7291 r->yresolution = 0;
7292 r->ttoption = DMTT_SUBDEV;
7293 r->collate = DMCOLLATE_FALSE;
7294 r->formname = talloc_strdup(r, "Letter");
7296 return r;
7299 static bool test_architecture_buffer(struct torture_context *tctx,
7300 void *private_data)
7302 struct test_spoolss_context *ctx =
7303 talloc_get_type_abort(private_data, struct test_spoolss_context);
7305 struct spoolss_OpenPrinterEx r;
7306 struct spoolss_UserLevel1 u1;
7307 struct policy_handle handle;
7308 uint32_t architectures[] = {
7309 PROCESSOR_ARCHITECTURE_INTEL,
7310 PROCESSOR_ARCHITECTURE_IA64,
7311 PROCESSOR_ARCHITECTURE_AMD64
7313 uint32_t needed[3];
7314 int i;
7315 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7316 struct dcerpc_binding_handle *b = p->binding_handle;
7318 for (i=0; i < ARRAY_SIZE(architectures); i++) {
7320 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7322 u1.size = 0;
7323 u1.client = NULL;
7324 u1.user = NULL;
7325 u1.build = 0;
7326 u1.major = 3;
7327 u1.minor = 0;
7328 u1.processor = architectures[i];
7330 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7331 r.in.datatype = NULL;
7332 r.in.devmode_ctr.devmode= NULL;
7333 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7334 r.in.level = 1;
7335 r.in.userlevel.level1 = &u1;
7336 r.out.handle = &handle;
7338 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7339 torture_assert_werr_ok(tctx, r.out.result, "");
7342 struct spoolss_EnumPrinters e;
7343 uint32_t count;
7344 union spoolss_PrinterInfo *info;
7346 e.in.flags = PRINTER_ENUM_LOCAL;
7347 e.in.server = NULL;
7348 e.in.level = 2;
7349 e.in.buffer = NULL;
7350 e.in.offered = 0;
7351 e.out.count = &count;
7352 e.out.info = &info;
7353 e.out.needed = &needed[i];
7355 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7356 #if 0
7357 torture_comment(tctx, "needed was %d\n", needed[i]);
7358 #endif
7361 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7364 for (i=1; i < ARRAY_SIZE(architectures); i++) {
7365 if (needed[i-1] != needed[i]) {
7366 torture_fail(tctx,
7367 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7368 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7372 return true;
7375 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
7376 void *private_data)
7378 struct test_spoolss_context *ctx =
7379 talloc_get_type_abort(private_data, struct test_spoolss_context);
7380 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7381 struct dcerpc_binding_handle *b = p->binding_handle;
7383 return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
7386 static bool test_PrintServer_Forms(struct torture_context *tctx,
7387 void *private_data)
7389 struct test_spoolss_context *ctx =
7390 talloc_get_type_abort(private_data, struct test_spoolss_context);
7391 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7392 struct dcerpc_binding_handle *b = p->binding_handle;
7394 return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
7397 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
7398 void *private_data)
7400 struct test_spoolss_context *ctx =
7401 talloc_get_type_abort(private_data, struct test_spoolss_context);
7402 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7403 struct dcerpc_binding_handle *b = p->binding_handle;
7405 return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
7408 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
7410 NTSTATUS status;
7412 status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
7414 torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
7416 torture_assert(tctx,
7417 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
7418 "failed to open printserver");
7419 torture_assert(tctx,
7420 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
7421 "failed to get environment");
7423 return true;
7426 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
7428 struct test_spoolss_context *t;
7430 *data = t = talloc_zero(tctx, struct test_spoolss_context);
7432 return torture_rpc_spoolss_setup_common(tctx, t);
7435 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
7437 test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
7439 return true;
7442 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
7444 struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
7445 bool ret;
7447 ret = torture_rpc_spoolss_teardown_common(tctx, t);
7448 talloc_free(t);
7450 return ret;
7453 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
7455 struct dcerpc_pipe *p;
7456 struct dcerpc_binding_handle *b;
7457 const char *server_name_slash;
7458 const char *driver_name;
7459 const char *printer_name;
7460 const char *port_name;
7462 torture_assert_ntstatus_ok(tctx,
7463 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
7464 "Error connecting to server");
7466 p = t->spoolss_pipe;
7467 b = p->binding_handle;
7468 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7470 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
7471 t->driver.info8.driver_name = TORTURE_DRIVER;
7472 t->driver.info8.driver_path = "pscript5.dll";
7473 t->driver.info8.data_file = "cups6.ppd";
7474 t->driver.info8.config_file = "ps5ui.dll";
7475 t->driver.info8.help_file = "pscript.hlp";
7476 t->driver.info8.default_datatype = "RAW";
7477 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
7478 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
7479 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
7480 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
7481 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
7482 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
7483 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
7484 t->driver.info8.dependent_files->string[5] = "cups6.ini";
7485 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
7486 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
7488 t->driver.local.driver_directory= "/usr/share/cups/drivers";
7490 t->info2.drivername = "Microsoft XPS Document Writer";
7491 t->info2.portname = "LPT1:";
7493 printer_name = t->info2.printername;
7494 port_name = t->info2.portname;
7496 torture_assert(tctx,
7497 fillup_printserver_info(tctx, p, &t->driver),
7498 "failed to fillup printserver info");
7500 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
7502 torture_assert(tctx,
7503 compose_local_driver_directory(tctx, t->driver.remote.environment,
7504 t->driver.local.driver_directory,
7505 &t->driver.local.driver_directory),
7506 "failed to compose local driver directory");
7508 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7509 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7510 t->info2.drivername, t->driver.remote.environment);
7511 t->have_driver = true;
7512 goto try_add;
7515 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
7516 t->info2.drivername, t->driver.remote.environment);
7517 torture_comment(tctx, "trying to upload own driver\n");
7519 if (!directory_exist(t->driver.local.driver_directory)) {
7520 torture_warning(tctx, "no local driver is available!");
7521 t->have_driver = false;
7522 goto try_add;
7525 torture_assert(tctx,
7526 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
7527 "failed to upload printer driver");
7529 torture_assert(tctx,
7530 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
7531 "failed to add driver");
7533 t->added_driver = true;
7534 t->have_driver = true;
7536 try_add:
7537 driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7539 if (t->wellknown) {
7540 torture_assert(tctx,
7541 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
7542 "failed to add wellknown printer");
7543 } else {
7544 torture_assert(tctx,
7545 test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
7546 "failed to add printer");
7549 return true;
7552 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
7554 struct torture_printer_context *t;
7556 *data = t = talloc_zero(tctx, struct torture_printer_context);
7558 t->ex = false;
7559 t->wellknown = false;
7560 t->info2.printername = TORTURE_PRINTER;
7561 t->devmode = NULL;
7563 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7566 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
7568 struct torture_printer_context *t;
7570 *data = t = talloc_zero(tctx, struct torture_printer_context);
7572 t->ex = true;
7573 t->wellknown = false;
7574 t->info2.printername = TORTURE_PRINTER_EX;
7575 t->devmode = NULL;
7577 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7580 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
7582 struct torture_printer_context *t;
7584 *data = t = talloc_zero(tctx, struct torture_printer_context);
7586 t->ex = false;
7587 t->wellknown = true;
7588 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
7589 t->devmode = NULL;
7591 /* FIXME */
7592 if (t->wellknown) {
7593 torture_skip(tctx, "skipping AddPrinter level 1");
7596 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7599 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
7601 struct torture_printer_context *t;
7603 *data = t = talloc_zero(tctx, struct torture_printer_context);
7605 t->ex = true;
7606 t->wellknown = true;
7607 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
7608 t->devmode = NULL;
7610 /* FIXME */
7611 if (t->wellknown) {
7612 torture_skip(tctx, "skipping AddPrinterEx level 1");
7615 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7618 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
7620 struct torture_printer_context *t;
7622 *data = t = talloc_zero(tctx, struct torture_printer_context);
7624 t->ex = true;
7625 t->wellknown = false;
7626 t->info2.printername = TORTURE_PRINTER_EX;
7627 t->devmode = torture_devicemode(t, TORTURE_PRINTER_EX);
7629 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7632 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
7634 bool found = false;
7635 struct dcerpc_pipe *p = t->spoolss_pipe;
7636 struct dcerpc_binding_handle *b;
7637 const char *printer_name = t->info2.printername;
7639 if (t->added_driver) {
7640 torture_assert(tctx,
7641 remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
7642 "failed to remove printer driver");
7645 if (p) {
7646 b = p->binding_handle;
7649 if (!t->wellknown) {
7650 torture_assert(tctx,
7651 test_DeletePrinter(tctx, b, &t->handle),
7652 "failed to delete printer");
7654 torture_assert(tctx,
7655 test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
7656 printer_name, &found),
7657 "failed to enumerate printers");
7659 torture_assert(tctx, !found, "deleted printer still there");
7662 return true;
7665 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
7667 struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
7668 bool ret;
7670 ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
7671 talloc_free(t);
7673 return ret;
7676 static bool test_print_test(struct torture_context *tctx,
7677 void *private_data)
7679 struct torture_printer_context *t =
7680 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7681 struct dcerpc_pipe *p = t->spoolss_pipe;
7682 struct dcerpc_binding_handle *b = p->binding_handle;
7684 torture_assert(tctx,
7685 test_PausePrinter(tctx, b, &t->handle),
7686 "failed to pause printer");
7688 torture_assert(tctx,
7689 test_DoPrintTest(tctx, b, &t->handle),
7690 "failed to do print test");
7692 torture_assert(tctx,
7693 test_ResumePrinter(tctx, b, &t->handle),
7694 "failed to resume printer");
7696 return true;
7699 static bool test_print_test_extended(struct torture_context *tctx,
7700 void *private_data)
7702 struct torture_printer_context *t =
7703 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7704 struct dcerpc_pipe *p = t->spoolss_pipe;
7705 struct dcerpc_binding_handle *b = p->binding_handle;
7706 bool ret = true;
7708 torture_assert(tctx,
7709 test_PausePrinter(tctx, b, &t->handle),
7710 "failed to pause printer");
7712 ret = test_DoPrintTest_extended(tctx, b, &t->handle);
7713 if (ret == false) {
7714 torture_comment(tctx, "WARNING! failed to do extended print test\n");
7715 if (torture_setting_bool(tctx, "samba3", false)) {
7716 torture_comment(tctx, "non-critical for samba3\n");
7717 ret = true;
7718 tctx->last_result = TORTURE_SKIP;
7722 torture_assert(tctx,
7723 test_ResumePrinter(tctx, b, &t->handle),
7724 "failed to resume printer");
7726 return ret;
7729 static bool test_printer_sd(struct torture_context *tctx,
7730 void *private_data)
7732 struct torture_printer_context *t =
7733 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7734 struct dcerpc_pipe *p = t->spoolss_pipe;
7735 struct dcerpc_binding_handle *b = p->binding_handle;
7737 torture_assert(tctx,
7738 test_PrinterInfo_SD(tctx, b, &t->handle),
7739 "failed to test security descriptors");
7741 return true;
7744 static bool test_printer_dm(struct torture_context *tctx,
7745 void *private_data)
7747 struct torture_printer_context *t =
7748 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7749 struct dcerpc_pipe *p = t->spoolss_pipe;
7751 torture_assert(tctx,
7752 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
7753 "failed to test devicemodes");
7755 return true;
7758 static bool test_printer_info_winreg(struct torture_context *tctx,
7759 void *private_data)
7761 struct torture_printer_context *t =
7762 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7763 struct dcerpc_pipe *p = t->spoolss_pipe;
7765 torture_assert(tctx,
7766 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
7767 "failed to test printer info winreg");
7769 return true;
7772 static bool test_printer_change_id(struct torture_context *tctx,
7773 void *private_data)
7775 struct torture_printer_context *t =
7776 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7777 struct dcerpc_pipe *p = t->spoolss_pipe;
7779 torture_assert(tctx,
7780 test_ChangeID(tctx, p, &t->handle),
7781 "failed to test change id");
7783 return true;
7786 static bool test_printer_keys(struct torture_context *tctx,
7787 void *private_data)
7789 struct torture_printer_context *t =
7790 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7791 struct dcerpc_pipe *p = t->spoolss_pipe;
7792 struct dcerpc_binding_handle *b = p->binding_handle;
7794 torture_assert(tctx,
7795 test_printer_all_keys(tctx, b, &t->handle),
7796 "failed to test printer keys");
7798 return true;
7801 static bool test_printer_data_consistency(struct torture_context *tctx,
7802 void *private_data)
7804 struct torture_printer_context *t =
7805 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7806 struct dcerpc_pipe *p = t->spoolss_pipe;
7808 torture_assert(tctx,
7809 test_EnumPrinterData_consistency(tctx, p, &t->handle),
7810 "failed to test printer data consistency");
7812 return true;
7815 static bool test_printer_data_keys(struct torture_context *tctx,
7816 void *private_data)
7818 struct torture_printer_context *t =
7819 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7820 struct dcerpc_pipe *p = t->spoolss_pipe;
7822 torture_assert(tctx,
7823 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
7824 "failed to test printer data keys");
7826 return true;
7829 static bool test_printer_data_values(struct torture_context *tctx,
7830 void *private_data)
7832 struct torture_printer_context *t =
7833 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7834 struct dcerpc_pipe *p = t->spoolss_pipe;
7836 torture_assert(tctx,
7837 test_SetPrinterDataEx_values(tctx, p, &t->handle),
7838 "failed to test printer data values");
7840 return true;
7843 static bool test_printer_data_set(struct torture_context *tctx,
7844 void *private_data)
7846 struct torture_printer_context *t =
7847 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7848 struct dcerpc_pipe *p = t->spoolss_pipe;
7850 torture_assert(tctx,
7851 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
7852 "failed to test printer data set");
7854 return true;
7857 static bool test_printer_data_winreg(struct torture_context *tctx,
7858 void *private_data)
7860 struct torture_printer_context *t =
7861 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7862 struct dcerpc_pipe *p = t->spoolss_pipe;
7864 torture_assert(tctx,
7865 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
7866 "failed to test printer data winreg");
7868 return true;
7871 static bool test_printer_data_dsspooler(struct torture_context *tctx,
7872 void *private_data)
7874 struct torture_printer_context *t =
7875 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7876 struct dcerpc_pipe *p = t->spoolss_pipe;
7878 torture_assert(tctx,
7879 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
7880 "failed to test printer data winreg dsspooler");
7882 return true;
7885 static bool test_driver_info_winreg(struct torture_context *tctx,
7886 void *private_data)
7888 struct torture_printer_context *t =
7889 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7890 struct dcerpc_pipe *p = t->spoolss_pipe;
7891 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7893 if (!t->have_driver) {
7894 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
7897 torture_assert(tctx,
7898 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
7899 "failed to test driver info winreg");
7901 return true;
7904 void torture_tcase_printer(struct torture_tcase *tcase)
7906 torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
7907 torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
7908 torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
7909 torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
7910 torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
7911 torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
7912 torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
7913 torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
7914 torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
7915 torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
7916 torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
7917 torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
7918 torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
7919 torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
7920 torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
7921 torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
7922 torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
7923 torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
7926 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
7928 struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
7929 struct torture_tcase *tcase;
7931 tcase = torture_suite_add_tcase(suite, "addprinter");
7933 torture_tcase_set_fixture(tcase,
7934 torture_rpc_spoolss_printer_setup,
7935 torture_rpc_spoolss_printer_teardown);
7937 torture_tcase_printer(tcase);
7939 tcase = torture_suite_add_tcase(suite, "addprinterex");
7941 torture_tcase_set_fixture(tcase,
7942 torture_rpc_spoolss_printerex_setup,
7943 torture_rpc_spoolss_printer_teardown);
7945 torture_tcase_printer(tcase);
7947 tcase = torture_suite_add_tcase(suite, "addprinterwkn");
7949 torture_tcase_set_fixture(tcase,
7950 torture_rpc_spoolss_printerwkn_setup,
7951 torture_rpc_spoolss_printer_teardown);
7953 tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
7955 torture_tcase_set_fixture(tcase,
7956 torture_rpc_spoolss_printerexwkn_setup,
7957 torture_rpc_spoolss_printer_teardown);
7959 #if 0
7960 /* test is not correct */
7961 tcase = torture_suite_add_tcase(suite, "addprinterdm");
7963 torture_tcase_set_fixture(tcase,
7964 torture_rpc_spoolss_printerdm_setup,
7965 torture_rpc_spoolss_printer_teardown);
7967 torture_tcase_printer(tcase);
7968 #endif
7969 return suite;
7972 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
7974 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
7975 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
7977 torture_tcase_set_fixture(tcase,
7978 torture_rpc_spoolss_setup,
7979 torture_rpc_spoolss_teardown);
7981 torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
7982 torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
7983 torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
7984 torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
7985 torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
7986 torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
7987 torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
7988 torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
7989 torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
7990 torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
7991 torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
7992 torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
7993 torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
7994 torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
7995 torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
7996 torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
7997 torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
7998 torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
7999 torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
8000 torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
8002 torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
8004 return suite;
8007 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
8008 struct dcerpc_binding_handle *b,
8009 const char *server,
8010 const char *environment,
8011 const char **dir_p)
8013 struct spoolss_GetPrinterDriverDirectory r;
8014 uint32_t needed;
8016 r.in.server = server;
8017 r.in.environment = environment;
8018 r.in.level = 1;
8019 r.in.buffer = NULL;
8020 r.in.offered = 0;
8021 r.out.needed = &needed;
8023 torture_assert_ntstatus_ok(tctx,
8024 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8025 "failed to query driver directory");
8027 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
8028 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
8029 r.in.buffer = &blob;
8030 r.in.offered = needed;
8032 torture_assert_ntstatus_ok(tctx,
8033 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8034 "failed to query driver directory");
8037 torture_assert_werr_ok(tctx, r.out.result,
8038 "failed to query driver directory");
8040 if (dir_p) {
8041 *dir_p = r.out.info->info1.directory_name;
8044 return true;
8047 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8049 if (info_ctr == NULL) {
8050 return NULL;
8053 switch (info_ctr->level) {
8054 case 1:
8055 return info_ctr->info.info1->driver_name;
8056 case 2:
8057 return info_ctr->info.info2->driver_name;
8058 case 3:
8059 return info_ctr->info.info3->driver_name;
8060 case 4:
8061 return info_ctr->info.info4->driver_name;
8062 case 6:
8063 return info_ctr->info.info6->driver_name;
8064 case 8:
8065 return info_ctr->info.info8->driver_name;
8066 default:
8067 return NULL;
8071 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8073 if (info_ctr == NULL) {
8074 return NULL;
8077 switch (info_ctr->level) {
8078 case 2:
8079 return info_ctr->info.info2->architecture;
8080 case 3:
8081 return info_ctr->info.info3->architecture;
8082 case 4:
8083 return info_ctr->info.info4->architecture;
8084 case 6:
8085 return info_ctr->info.info6->architecture;
8086 case 8:
8087 return info_ctr->info.info8->architecture;
8088 default:
8089 return NULL;
8094 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
8095 struct dcerpc_binding_handle *b,
8096 const char *servername,
8097 struct spoolss_AddDriverInfoCtr *info_ctr,
8098 WERROR expected_result)
8100 struct spoolss_AddPrinterDriver r;
8101 const char *drivername = get_driver_from_info(info_ctr);
8102 const char *environment = get_environment_from_info(info_ctr);
8104 r.in.servername = servername;
8105 r.in.info_ctr = info_ctr;
8107 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
8108 drivername, info_ctr->level, environment);
8110 torture_assert_ntstatus_ok(tctx,
8111 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
8112 "spoolss_AddPrinterDriver failed");
8113 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8114 "spoolss_AddPrinterDriver failed with unexpected result");
8116 return true;
8120 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
8121 struct dcerpc_binding_handle *b,
8122 const char *servername,
8123 struct spoolss_AddDriverInfoCtr *info_ctr,
8124 uint32_t flags,
8125 WERROR expected_result)
8127 struct spoolss_AddPrinterDriverEx r;
8128 const char *drivername = get_driver_from_info(info_ctr);
8129 const char *environment = get_environment_from_info(info_ctr);
8131 r.in.servername = servername;
8132 r.in.info_ctr = info_ctr;
8133 r.in.flags = flags;
8135 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
8136 drivername, info_ctr->level, environment);
8138 torture_assert_ntstatus_ok(tctx,
8139 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
8140 "AddPrinterDriverEx failed");
8141 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8142 "AddPrinterDriverEx failed with unexpected result");
8144 return true;
8147 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
8148 if (path && strlen(path)) {\
8149 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
8152 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
8153 struct dcerpc_binding_handle *b,
8154 const char *server_name,
8155 struct spoolss_AddDriverInfo8 *r,
8156 uint32_t flags,
8157 bool ex,
8158 const char *remote_driver_dir)
8160 struct spoolss_AddDriverInfoCtr info_ctr;
8161 struct spoolss_AddDriverInfo1 info1;
8163 ZERO_STRUCT(info1);
8165 info_ctr.level = 1;
8166 info_ctr.info.info1 = &info1;
8168 if (ex) {
8169 torture_assert(tctx,
8170 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8171 "failed to test AddPrinterDriverEx level 1");
8172 } else {
8173 torture_assert(tctx,
8174 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8175 "failed to test AddPrinterDriver level 1");
8178 info1.driver_name = r->driver_name;
8180 if (ex) {
8181 torture_assert(tctx,
8182 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8183 "failed to test AddPrinterDriverEx level 1");
8184 } else {
8185 torture_assert(tctx,
8186 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8187 "failed to test AddPrinterDriver level 1");
8190 return true;
8193 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
8194 struct dcerpc_binding_handle *b,
8195 const char *server_name,
8196 struct spoolss_AddDriverInfo8 *r,
8197 uint32_t flags,
8198 bool ex,
8199 const char *remote_driver_dir)
8201 struct spoolss_AddDriverInfoCtr info_ctr;
8202 struct spoolss_AddDriverInfo2 info2;
8203 union spoolss_DriverInfo info;
8205 ZERO_STRUCT(info2);
8207 info_ctr.level = 2;
8208 info_ctr.info.info2 = &info2;
8210 if (ex) {
8211 torture_assert(tctx,
8212 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8213 "failed to test AddPrinterDriverEx level 2");
8214 } else {
8215 torture_assert(tctx,
8216 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8217 "failed to test AddPrinterDriver level 2");
8220 info2.driver_name = r->driver_name;
8222 if (ex) {
8223 torture_assert(tctx,
8224 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8225 "failed to test AddPrinterDriverEx level 2");
8226 } else {
8227 torture_assert(tctx,
8228 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8229 "failed to test AddPrinterDriver level 2");
8232 info2.version = r->version;
8234 if (ex) {
8235 torture_assert(tctx,
8236 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8237 "failed to test AddPrinterDriverEx level 2");
8238 } else {
8239 torture_assert(tctx,
8240 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8241 "failed to test AddPrinterDriver level 2");
8244 info2.architecture = r->architecture;
8246 if (ex) {
8247 torture_assert(tctx,
8248 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8249 "failed to test AddPrinterDriverEx level 2");
8250 } else {
8251 torture_assert(tctx,
8252 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8253 "failed to test AddPrinterDriver level 2");
8256 info2.driver_path = r->driver_path;
8258 if (ex) {
8259 torture_assert(tctx,
8260 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8261 "failed to test AddPrinterDriverEx level 2");
8262 } else {
8263 torture_assert(tctx,
8264 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8265 "failed to test AddPrinterDriver level 2");
8268 info2.data_file = r->data_file;
8270 if (ex) {
8271 torture_assert(tctx,
8272 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8273 "failed to test AddPrinterDriverEx level 2");
8274 } else {
8275 torture_assert(tctx,
8276 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8277 "failed to test AddPrinterDriver level 2");
8280 info2.config_file = r->config_file;
8282 if (ex) {
8283 torture_assert(tctx,
8284 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
8285 "failed to test AddPrinterDriverEx");
8288 if (ex) {
8289 torture_assert(tctx,
8290 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8291 "failed to test AddPrinterDriverEx level 2");
8292 } else {
8293 torture_assert(tctx,
8294 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8295 "failed to test AddPrinterDriver level 2");
8298 torture_assert(tctx,
8299 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
8300 "failed to find added printer driver");
8302 if (remote_driver_dir) {
8303 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
8304 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
8305 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
8308 return true;
8311 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
8312 struct dcerpc_binding_handle *b,
8313 const char *server_name,
8314 struct spoolss_AddDriverInfo8 *r,
8315 uint32_t flags,
8316 bool ex,
8317 const char *remote_driver_dir)
8319 struct spoolss_AddDriverInfoCtr info_ctr;
8320 struct spoolss_AddDriverInfo3 info3;
8321 union spoolss_DriverInfo info;
8323 info3.driver_name = r->driver_name;
8324 info3.version = r->version;
8325 info3.architecture = r->architecture;
8326 info3.driver_path = r->driver_path;
8327 info3.data_file = r->data_file;
8328 info3.config_file = r->config_file;
8329 info3.help_file = r->help_file;
8330 info3.monitor_name = r->monitor_name;
8331 info3.default_datatype = r->default_datatype;
8332 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8333 info3.dependent_files = r->dependent_files;
8335 info_ctr.level = 3;
8336 info_ctr.info.info3 = &info3;
8338 if (ex) {
8339 torture_assert(tctx,
8340 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8341 "failed to test AddPrinterDriverEx level 3");
8342 } else {
8343 torture_assert(tctx,
8344 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8345 "failed to test AddPrinterDriver level 3");
8348 torture_assert(tctx,
8349 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
8350 "failed to find added printer driver");
8352 if (remote_driver_dir) {
8353 int i;
8354 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
8355 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
8356 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
8357 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
8358 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
8359 ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
8363 return true;
8366 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
8367 struct dcerpc_binding_handle *b,
8368 const char *server_name,
8369 struct spoolss_AddDriverInfo8 *r,
8370 uint32_t flags,
8371 bool ex,
8372 const char *remote_driver_dir)
8374 struct spoolss_AddDriverInfoCtr info_ctr;
8375 struct spoolss_AddDriverInfo4 info4;
8376 union spoolss_DriverInfo info;
8378 info4.version = r->version;
8379 info4.driver_name = r->driver_name;
8380 info4.architecture = r->architecture;
8381 info4.driver_path = r->driver_path;
8382 info4.data_file = r->data_file;
8383 info4.config_file = r->config_file;
8384 info4.help_file = r->help_file;
8385 info4.monitor_name = r->monitor_name;
8386 info4.default_datatype = r->default_datatype;
8387 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8388 info4.dependent_files = r->dependent_files;
8389 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
8390 info4.previous_names = r->previous_names;
8392 info_ctr.level = 4;
8393 info_ctr.info.info4 = &info4;
8395 if (ex) {
8396 torture_assert(tctx,
8397 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8398 "failed to test AddPrinterDriverEx level 4");
8399 } else {
8400 torture_assert(tctx,
8401 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8402 "failed to test AddPrinterDriver level 4");
8405 torture_assert(tctx,
8406 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
8407 "failed to find added printer driver");
8409 if (remote_driver_dir) {
8410 int i;
8411 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
8412 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
8413 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
8414 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
8415 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
8416 ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
8420 return true;
8423 static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
8424 struct dcerpc_binding_handle *b,
8425 const char *server_name,
8426 struct spoolss_AddDriverInfo8 *r,
8427 uint32_t flags,
8428 bool ex,
8429 const char *remote_driver_dir)
8431 struct spoolss_AddDriverInfoCtr info_ctr;
8432 struct spoolss_AddDriverInfo6 info6;
8433 union spoolss_DriverInfo info;
8435 info6.version = r->version;
8436 info6.driver_name = r->driver_name;
8437 info6.architecture = r->architecture;
8438 info6.driver_path = r->driver_path;
8439 info6.data_file = r->data_file;
8440 info6.config_file = r->config_file;
8441 info6.help_file = r->help_file;
8442 info6.monitor_name = r->monitor_name;
8443 info6.default_datatype = r->default_datatype;
8444 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8445 info6.dependent_files = r->dependent_files;
8446 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
8447 info6.previous_names = r->previous_names;
8448 info6.driver_date = r->driver_date;
8449 info6.driver_version = r->driver_version;
8450 info6.manufacturer_name = r->manufacturer_name;
8451 info6.manufacturer_url = r->manufacturer_url;
8452 info6.hardware_id = r->hardware_id;
8453 info6.provider = r->provider;
8455 info_ctr.level = 6;
8456 info_ctr.info.info6 = &info6;
8458 if (ex) {
8459 torture_assert(tctx,
8460 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8461 "failed to test AddPrinterDriverEx level 6");
8462 } else {
8463 torture_assert(tctx,
8464 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8465 "failed to test AddPrinterDriver level 6");
8468 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8470 if (!ex) {
8471 return true;
8474 torture_assert(tctx,
8475 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
8476 "failed to find added printer driver");
8478 if (remote_driver_dir) {
8479 int i;
8480 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
8481 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
8482 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
8483 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
8484 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
8485 ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
8489 torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
8490 torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
8492 return true;
8495 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
8496 struct dcerpc_binding_handle *b,
8497 const char *server_name,
8498 struct spoolss_AddDriverInfo8 *r,
8499 uint32_t flags,
8500 bool ex,
8501 const char *remote_driver_dir)
8503 struct spoolss_AddDriverInfoCtr info_ctr;
8504 union spoolss_DriverInfo info;
8506 info_ctr.level = 8;
8507 info_ctr.info.info8 = r;
8509 if (ex) {
8510 torture_assert(tctx,
8511 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8512 "failed to test AddPrinterDriverEx level 8");
8513 } else {
8514 torture_assert(tctx,
8515 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8516 "failed to test AddPrinterDriver level 8");
8519 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8521 if (!ex) {
8522 return true;
8525 torture_assert(tctx,
8526 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
8527 "failed to find added printer driver");
8529 if (remote_driver_dir) {
8530 int i;
8531 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
8532 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
8533 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
8534 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
8535 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
8536 ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
8540 torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
8541 torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
8543 return true;
8546 #undef ASSERT_DRIVER_PATH
8548 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
8549 struct dcerpc_binding_handle *b,
8550 const char *server,
8551 const char *driver,
8552 const char *environment,
8553 WERROR expected_result)
8555 struct spoolss_DeletePrinterDriver r;
8557 r.in.server = server;
8558 r.in.architecture = environment;
8559 r.in.driver = driver;
8561 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
8563 torture_assert_ntstatus_ok(tctx,
8564 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
8565 "DeletePrinterDriver failed");
8566 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8567 "DeletePrinterDriver failed with unexpected result");
8569 return true;
8572 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
8573 struct dcerpc_binding_handle *b,
8574 const char *server,
8575 const char *driver,
8576 const char *environment,
8577 uint32_t delete_flags,
8578 uint32_t version,
8579 WERROR expected_result)
8581 struct spoolss_DeletePrinterDriverEx r;
8583 r.in.server = server;
8584 r.in.architecture = environment;
8585 r.in.driver = driver;
8586 r.in.delete_flags = delete_flags;
8587 r.in.version = version;
8589 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
8591 torture_assert_ntstatus_ok(tctx,
8592 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
8593 "DeletePrinterDriverEx failed");
8594 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8595 "DeletePrinterDriverEx failed with unexpected result");
8597 return true;
8600 static bool test_DeletePrinterDriver(struct torture_context *tctx,
8601 struct dcerpc_binding_handle *b,
8602 const char *server_name,
8603 const char *driver,
8604 const char *environment)
8606 torture_assert(tctx,
8607 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
8608 "failed to delete driver");
8610 torture_assert(tctx,
8611 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
8612 "failed to delete driver");
8614 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8615 torture_fail(tctx, "deleted driver still enumerated");
8618 torture_assert(tctx,
8619 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
8620 "2nd delete failed");
8622 return true;
8625 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
8626 struct dcerpc_binding_handle *b,
8627 const char *server_name,
8628 const char *driver,
8629 const char *environment,
8630 uint32_t delete_flags,
8631 uint32_t version)
8633 torture_assert(tctx,
8634 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
8635 "failed to delete driver");
8637 torture_assert(tctx,
8638 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
8639 "failed to delete driver");
8641 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8642 torture_fail(tctx, "deleted driver still enumerated");
8645 torture_assert(tctx,
8646 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
8647 "2nd delete failed");
8649 return true;
8652 static bool test_PrinterDriver_args(struct torture_context *tctx,
8653 struct dcerpc_binding_handle *b,
8654 const char *server_name,
8655 uint32_t level,
8656 struct spoolss_AddDriverInfo8 *r,
8657 uint32_t add_flags,
8658 uint32_t delete_flags,
8659 uint32_t delete_version,
8660 bool ex,
8661 const char *remote_driver_dir)
8663 bool ret = true;
8665 switch (level) {
8666 case 1:
8667 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8668 break;
8669 case 2:
8670 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8671 break;
8672 case 3:
8673 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8674 break;
8675 case 4:
8676 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8677 break;
8678 case 6:
8679 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8680 break;
8681 case 8:
8682 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8683 break;
8684 default:
8685 return false;
8688 if (ret == false) {
8689 return ret;
8692 if (level == 1) {
8693 return ret;
8696 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8698 if (!ex && (level == 6 || level == 8)) {
8699 return ret;
8703 struct dcerpc_pipe *p2;
8704 struct policy_handle hive_handle;
8705 struct dcerpc_binding_handle *b2;
8707 torture_assert_ntstatus_ok(tctx,
8708 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
8709 "could not open winreg pipe");
8710 b2 = p2->binding_handle;
8712 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
8714 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
8716 test_winreg_CloseKey(tctx, b2, &hive_handle);
8718 talloc_free(p2);
8721 if (ex) {
8722 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
8723 } else {
8724 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
8728 static bool fillup_printserver_info(struct torture_context *tctx,
8729 struct dcerpc_pipe *p,
8730 struct torture_driver_context *d)
8732 struct policy_handle server_handle;
8733 struct dcerpc_binding_handle *b = p->binding_handle;
8734 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8736 torture_assert(tctx,
8737 test_OpenPrinter_server(tctx, p, &server_handle),
8738 "failed to open printserver");
8739 torture_assert(tctx,
8740 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
8741 "failed to get environment");
8742 torture_assert(tctx,
8743 test_ClosePrinter(tctx, b, &server_handle),
8744 "failed to close printserver");
8746 torture_assert(tctx,
8747 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
8748 d->local.environment ? d->local.environment : d->remote.environment,
8749 &d->remote.driver_directory),
8750 "failed to get driver directory");
8752 return true;
8755 static const char *driver_directory_dir(const char *driver_directory)
8757 char *p;
8759 p = strrchr(driver_directory, '\\');
8760 if (p) {
8761 return p+1;
8764 return NULL;
8767 static const char *driver_directory_share(struct torture_context *tctx,
8768 const char *driver_directory)
8770 const char *p;
8771 char *tok;
8773 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
8774 driver_directory += 2;
8777 p = talloc_strdup(tctx, driver_directory);
8779 torture_assert(tctx,
8780 next_token_talloc(tctx, &p, &tok, "\\"),
8781 "cannot explode uri");
8782 torture_assert(tctx,
8783 next_token_talloc(tctx, &p, &tok, "\\"),
8784 "cannot explode uri");
8786 return tok;
8789 static bool upload_printer_driver_file(struct torture_context *tctx,
8790 struct smbcli_state *cli,
8791 struct torture_driver_context *d,
8792 const char *file_name)
8794 XFILE *f;
8795 int fnum;
8796 uint8_t *buf;
8797 int maxwrite = 64512;
8798 off_t nread = 0;
8799 size_t start = 0;
8800 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
8801 const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
8802 const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8804 if (!file_name || strlen(file_name) == 0) {
8805 return true;
8808 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
8810 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
8811 if (fnum == -1) {
8812 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
8815 f = x_fopen(local_name, O_RDONLY, 0);
8816 if (f == NULL) {
8817 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
8820 buf = talloc_array(tctx, uint8_t, maxwrite);
8821 if (!buf) {
8822 return false;
8825 while (!x_feof(f)) {
8826 int n = maxwrite;
8827 int ret;
8829 if ((n = x_fread(buf, 1, n, f)) < 1) {
8830 if((n == 0) && x_feof(f))
8831 break; /* Empty local file. */
8833 torture_warning(tctx,
8834 "failed to read file: %s\n", strerror(errno));
8835 break;
8838 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
8840 if (n != ret) {
8841 torture_warning(tctx,
8842 "failed to write file: %s\n", smbcli_errstr(cli->tree));
8843 break;
8846 nread += n;
8849 x_fclose(f);
8851 torture_assert_ntstatus_ok(tctx,
8852 smbcli_close(cli->tree, fnum),
8853 "failed to close file");
8855 return true;
8858 static bool connect_printer_driver_share(struct torture_context *tctx,
8859 const char *server_name,
8860 const char *share_name,
8861 struct smbcli_state **cli)
8863 struct smbcli_options smb_options;
8864 struct smbcli_session_options smb_session_options;
8866 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
8867 share_name, server_name);
8869 lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
8870 lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
8872 torture_assert_ntstatus_ok(tctx,
8873 smbcli_full_connection(tctx, cli, server_name,
8874 lpcfg_smb_ports(tctx->lp_ctx),
8875 share_name, NULL,
8876 lpcfg_socket_options(tctx->lp_ctx),
8877 cmdline_credentials,
8878 lpcfg_resolve_context(tctx->lp_ctx),
8879 tctx->ev,
8880 &smb_options,
8881 &smb_session_options,
8882 lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
8883 "failed to open driver share");
8885 return true;
8888 static bool upload_printer_driver(struct torture_context *tctx,
8889 const char *server_name,
8890 struct torture_driver_context *d)
8892 struct smbcli_state *cli;
8893 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8894 int i;
8896 torture_assert(tctx,
8897 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8898 "failed to connect to driver share");
8900 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
8901 server_name, share_name);
8903 torture_assert(tctx,
8904 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8905 "failed to upload driver_path");
8906 torture_assert(tctx,
8907 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
8908 "failed to upload data_file");
8909 torture_assert(tctx,
8910 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
8911 "failed to upload config_file");
8912 torture_assert(tctx,
8913 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
8914 "failed to upload help_file");
8915 if (d->info8.dependent_files) {
8916 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8917 torture_assert(tctx,
8918 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8919 "failed to upload dependent_files");
8923 talloc_free(cli);
8925 return true;
8928 static bool check_printer_driver_file(struct torture_context *tctx,
8929 struct smbcli_state *cli,
8930 struct torture_driver_context *d,
8931 const char *file_name)
8933 const char *remote_arch_dir = driver_directory_dir(d->remote.driver_directory);
8934 const char *remote_name = talloc_asprintf(tctx, "%s\\%d\\%s",
8935 remote_arch_dir,
8936 d->info8.version,
8937 file_name);
8938 int fnum;
8940 torture_assert(tctx, (file_name && strlen(file_name) != 0), "invalid filename");
8942 torture_comment(tctx, "checking for driver file at %s\n", remote_name);
8944 fnum = smbcli_open(cli->tree, remote_name, O_RDONLY, DENY_NONE);
8945 if (fnum == -1) {
8946 return false;
8949 torture_assert_ntstatus_ok(tctx,
8950 smbcli_close(cli->tree, fnum),
8951 "failed to close driver file");
8953 return true;
8956 static bool check_printer_driver_files(struct torture_context *tctx,
8957 const char *server_name,
8958 struct torture_driver_context *d,
8959 bool expect_exist)
8961 struct smbcli_state *cli;
8962 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8963 int i;
8965 torture_assert(tctx,
8966 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8967 "failed to connect to driver share");
8969 torture_comment(tctx, "checking %sexistent driver files at \\\\%s\\%s\n",
8970 (expect_exist ? "": "non-"),
8971 server_name, share_name);
8973 if (d->info8.driver_path && d->info8.driver_path[0]) {
8974 torture_assert(tctx,
8975 check_printer_driver_file(tctx, cli, d, d->info8.driver_path) == expect_exist,
8976 "failed driver_path check");
8978 if (d->info8.data_file && d->info8.data_file[0]) {
8979 torture_assert(tctx,
8980 check_printer_driver_file(tctx, cli, d, d->info8.data_file) == expect_exist,
8981 "failed data_file check");
8983 if (d->info8.config_file && d->info8.config_file[0]) {
8984 torture_assert(tctx,
8985 check_printer_driver_file(tctx, cli, d, d->info8.config_file) == expect_exist,
8986 "failed config_file check");
8988 if (d->info8.help_file && d->info8.help_file[0]) {
8989 torture_assert(tctx,
8990 check_printer_driver_file(tctx, cli, d, d->info8.help_file) == expect_exist,
8991 "failed help_file check");
8993 if (d->info8.dependent_files) {
8994 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8995 torture_assert(tctx,
8996 check_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]) == expect_exist,
8997 "failed dependent_files check");
9001 talloc_free(cli);
9003 return true;
9006 static bool remove_printer_driver_file(struct torture_context *tctx,
9007 struct smbcli_state *cli,
9008 struct torture_driver_context *d,
9009 const char *file_name)
9011 const char *remote_name;
9012 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
9014 if (!file_name || strlen(file_name) == 0) {
9015 return true;
9018 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
9020 torture_comment(tctx, "Removing %s\n", remote_name);
9022 torture_assert_ntstatus_ok(tctx,
9023 smbcli_unlink(cli->tree, remote_name),
9024 "failed to unlink");
9026 return true;
9029 static bool remove_printer_driver(struct torture_context *tctx,
9030 const char *server_name,
9031 struct torture_driver_context *d)
9033 struct smbcli_state *cli;
9034 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9035 int i;
9037 torture_assert(tctx,
9038 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9039 "failed to connect to driver share");
9041 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
9042 server_name, share_name);
9044 torture_assert(tctx,
9045 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
9046 "failed to remove driver_path");
9047 torture_assert(tctx,
9048 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
9049 "failed to remove data_file");
9050 if (!strequal(d->info8.config_file, d->info8.driver_path)) {
9051 torture_assert(tctx,
9052 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
9053 "failed to remove config_file");
9055 torture_assert(tctx,
9056 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
9057 "failed to remove help_file");
9058 if (d->info8.dependent_files) {
9059 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9060 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
9061 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
9062 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
9063 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
9064 continue;
9066 torture_assert(tctx,
9067 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9068 "failed to remove dependent_files");
9072 talloc_free(cli);
9074 return true;
9078 static bool test_add_driver_arg(struct torture_context *tctx,
9079 struct dcerpc_pipe *p,
9080 struct torture_driver_context *d)
9082 bool ret = true;
9083 struct dcerpc_binding_handle *b = p->binding_handle;
9084 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9085 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
9086 int i;
9087 struct spoolss_AddDriverInfo8 info8;
9088 uint32_t add_flags = APD_COPY_NEW_FILES;
9089 uint32_t delete_flags = 0;
9091 ZERO_STRUCT(info8);
9093 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
9094 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
9096 torture_assert(tctx,
9097 fillup_printserver_info(tctx, p, d),
9098 "failed to fillup printserver info");
9100 if (!directory_exist(d->local.driver_directory)) {
9101 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9104 torture_assert(tctx,
9105 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9106 "failed to upload printer driver");
9108 info8 = d->info8;
9109 if (d->info8.dependent_files) {
9110 info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
9111 if (d->info8.dependent_files->string) {
9112 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9114 info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
9115 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9116 info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
9120 info8.architecture = d->local.environment;
9122 for (i=0; i < ARRAY_SIZE(levels); i++) {
9124 if (torture_setting_bool(tctx, "samba3", false)) {
9125 switch (levels[i]) {
9126 case 2:
9127 case 4:
9128 case 8:
9129 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9130 continue;
9131 default:
9132 break;
9135 if (torture_setting_bool(tctx, "w2k3", false)) {
9136 switch (levels[i]) {
9137 case 8:
9138 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9139 continue;
9140 default:
9141 break;
9145 torture_comment(tctx,
9146 "Testing PrinterDriver%s '%s' add & delete level %d\n",
9147 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9149 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);
9152 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
9153 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
9154 if (d->info8.config_file) {
9155 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
9157 if (d->info8.help_file) {
9158 info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
9160 if (d->info8.dependent_files && d->info8.dependent_files->string) {
9161 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9162 info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
9166 for (i=0; i < ARRAY_SIZE(levels); i++) {
9168 if (torture_setting_bool(tctx, "samba3", false)) {
9169 switch (levels[i]) {
9170 case 2:
9171 case 4:
9172 case 8:
9173 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9174 continue;
9175 default:
9176 break;
9179 if (torture_setting_bool(tctx, "w2k3", false)) {
9180 switch (levels[i]) {
9181 case 8:
9182 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9183 continue;
9184 default:
9185 break;
9189 torture_comment(tctx,
9190 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
9191 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9193 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);
9196 torture_assert(tctx,
9197 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9198 "failed to remove printer driver");
9200 torture_comment(tctx, "\n");
9202 return ret;
9205 static bool test_add_driver_ex_64(struct torture_context *tctx,
9206 struct dcerpc_pipe *p)
9208 struct torture_driver_context *d;
9210 d = talloc_zero(tctx, struct torture_driver_context);
9212 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9213 d->info8.driver_name = TORTURE_DRIVER_EX;
9214 d->info8.architecture = NULL;
9215 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9216 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9217 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9218 d->local.environment = talloc_strdup(d, "Windows x64");
9219 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9220 d->ex = true;
9222 return test_add_driver_arg(tctx, p, d);
9225 static bool test_add_driver_ex_32(struct torture_context *tctx,
9226 struct dcerpc_pipe *p)
9228 struct torture_driver_context *d;
9230 d = talloc_zero(tctx, struct torture_driver_context);
9232 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9233 d->info8.driver_name = TORTURE_DRIVER_EX;
9234 d->info8.architecture = NULL;
9235 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9236 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9237 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9238 d->local.environment = talloc_strdup(d, "Windows NT x86");
9239 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9240 d->ex = true;
9242 return test_add_driver_arg(tctx, p, d);
9245 static bool test_add_driver_64(struct torture_context *tctx,
9246 struct dcerpc_pipe *p)
9248 struct torture_driver_context *d;
9250 d = talloc_zero(tctx, struct torture_driver_context);
9252 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9253 d->info8.driver_name = TORTURE_DRIVER;
9254 d->info8.architecture = NULL;
9255 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9256 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9257 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9258 d->local.environment = talloc_strdup(d, "Windows x64");
9259 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9260 d->ex = false;
9262 return test_add_driver_arg(tctx, p, d);
9265 static bool test_add_driver_32(struct torture_context *tctx,
9266 struct dcerpc_pipe *p)
9268 struct torture_driver_context *d;
9270 d = talloc_zero(tctx, struct torture_driver_context);
9272 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9273 d->info8.driver_name = TORTURE_DRIVER;
9274 d->info8.architecture = NULL;
9275 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9276 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9277 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9278 d->local.environment = talloc_strdup(d, "Windows NT x86");
9279 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9280 d->ex = false;
9282 return test_add_driver_arg(tctx, p, d);
9285 static bool test_add_driver_adobe(struct torture_context *tctx,
9286 struct dcerpc_pipe *p)
9288 struct torture_driver_context *d;
9290 if (!torture_setting_bool(tctx, "samba3", false)) {
9291 torture_skip(tctx, "skipping adobe test which only works against samba3");
9294 d = talloc_zero(tctx, struct torture_driver_context);
9296 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9297 d->info8.driver_name = TORTURE_DRIVER_ADOBE;
9298 d->info8.architecture = NULL;
9299 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9300 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9301 d->info8.config_file = talloc_strdup(d, "ADOBEPS4.DRV");
9302 #if 0
9303 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9304 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9305 #endif
9306 d->local.environment = talloc_strdup(d, "Windows 4.0");
9307 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9308 d->ex = false;
9310 return test_add_driver_arg(tctx, p, d);
9313 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
9314 struct dcerpc_pipe *p)
9316 struct torture_driver_context *d;
9317 struct spoolss_StringArray *a;
9319 if (!torture_setting_bool(tctx, "samba3", false)) {
9320 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
9323 d = talloc_zero(tctx, struct torture_driver_context);
9325 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9326 d->info8.driver_name = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
9327 d->info8.architecture = NULL;
9328 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9329 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9330 d->info8.config_file = NULL;
9331 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9332 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9333 d->info8.default_datatype = talloc_strdup(d, "RAW");
9335 a = talloc_zero(d, struct spoolss_StringArray);
9336 a->string = talloc_zero_array(a, const char *, 7);
9337 a->string[0] = talloc_strdup(a->string, "ADOBEPS4.DRV");
9338 a->string[1] = talloc_strdup(a->string, "DEFPRTR2.PPD");
9339 a->string[2] = talloc_strdup(a->string, "ADOBEPS4.HLP");
9340 a->string[3] = talloc_strdup(a->string, "PSMON.DLL");
9341 a->string[4] = talloc_strdup(a->string, "ADFONTS.MFM");
9342 a->string[5] = talloc_strdup(a->string, "ICONLIB.DLL");
9344 d->info8.dependent_files = a;
9345 d->local.environment = talloc_strdup(d, "Windows 4.0");
9346 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9347 d->ex = false;
9349 return test_add_driver_arg(tctx, p, d);
9352 static bool test_add_driver_timestamps(struct torture_context *tctx,
9353 struct dcerpc_pipe *p)
9355 struct torture_driver_context *d;
9356 struct timeval t = timeval_current();
9358 d = talloc_zero(tctx, struct torture_driver_context);
9360 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9361 d->info8.driver_name = TORTURE_DRIVER_TIMESTAMPS;
9362 d->info8.architecture = NULL;
9363 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9364 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9365 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9366 d->info8.driver_date = timeval_to_nttime(&t);
9367 d->local.environment = talloc_strdup(d, "Windows NT x86");
9368 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9369 d->ex = true;
9371 torture_assert(tctx,
9372 test_add_driver_arg(tctx, p, d),
9373 "");
9375 unix_to_nt_time(&d->info8.driver_date, 1);
9377 torture_assert(tctx,
9378 test_add_driver_arg(tctx, p, d),
9379 "");
9381 return true;
9384 static bool test_multiple_drivers(struct torture_context *tctx,
9385 struct dcerpc_pipe *p)
9387 struct torture_driver_context *d;
9388 struct dcerpc_binding_handle *b = p->binding_handle;
9389 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9390 int i;
9391 struct spoolss_AddDriverInfo8 info8;
9392 uint32_t add_flags = APD_COPY_NEW_FILES;
9393 uint32_t delete_flags = 0;
9395 d = talloc_zero(tctx, struct torture_driver_context);
9397 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9398 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9399 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9400 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9401 d->local.environment = talloc_strdup(d, "Windows NT x86");
9402 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9403 d->ex = true;
9405 torture_assert(tctx,
9406 fillup_printserver_info(tctx, p, d),
9407 "failed to fillup printserver info");
9409 if (!directory_exist(d->local.driver_directory)) {
9410 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9413 torture_assert(tctx,
9414 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9415 "failed to upload printer driver");
9417 info8 = d->info8;
9418 info8.architecture = d->local.environment;
9420 for (i=0; i < 3; i++) {
9421 info8.driver_name = talloc_asprintf(d, "torture_test_driver_%d", i);
9423 torture_assert(tctx,
9424 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &info8, add_flags, true, NULL),
9425 "failed to add driver");
9428 torture_assert(tctx,
9429 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_0", info8.architecture, delete_flags, info8.version),
9430 "failed to delete driver");
9432 torture_assert(tctx,
9433 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_1", NULL),
9434 "torture_test_driver_1 no longer on the server");
9436 torture_assert(tctx,
9437 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
9438 "torture_test_driver_2 no longer on the server");
9440 torture_assert(tctx,
9441 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_1", info8.architecture, delete_flags, info8.version),
9442 "failed to delete driver");
9444 torture_assert(tctx,
9445 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
9446 "torture_test_driver_2 no longer on the server");
9448 torture_assert(tctx,
9449 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_2", info8.architecture, delete_flags, info8.version),
9450 "failed to delete driver");
9452 torture_assert(tctx,
9453 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9454 "failed to remove printer driver");
9456 return true;
9459 static bool test_del_driver_all_files(struct torture_context *tctx,
9460 struct dcerpc_pipe *p)
9462 struct torture_driver_context *d;
9463 struct spoolss_StringArray *a;
9464 uint32_t add_flags = APD_COPY_NEW_FILES;
9465 uint32_t delete_flags = DPD_DELETE_ALL_FILES;
9466 struct dcerpc_binding_handle *b = p->binding_handle;
9467 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9469 d = talloc_zero(tctx, struct torture_driver_context);
9471 d->ex = true;
9472 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9473 d->info8.driver_name = TORTURE_DRIVER_DELETER;
9474 d->info8.architecture = NULL;
9475 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9476 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9477 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9478 d->info8.help_file = talloc_strdup(d, "pscript.hlp");
9479 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
9480 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9482 a = talloc_zero(d, struct spoolss_StringArray);
9483 a->string = talloc_zero_array(a, const char *, 3);
9484 a->string[0] = talloc_strdup(a->string, "cups6.inf");
9485 a->string[1] = talloc_strdup(a->string, "cups6.ini");
9487 d->info8.dependent_files = a;
9488 d->info8.architecture = d->local.environment;
9490 torture_assert(tctx,
9491 fillup_printserver_info(tctx, p, d),
9492 "failed to fillup printserver info");
9494 if (!directory_exist(d->local.driver_directory)) {
9495 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9498 torture_assert(tctx,
9499 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9500 "failed to upload printer driver");
9502 torture_assert(tctx,
9503 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d->info8, add_flags, true, NULL),
9504 "failed to add driver");
9506 torture_assert(tctx,
9507 test_DeletePrinterDriverEx(tctx, b, server_name_slash,
9508 d->info8.driver_name,
9509 d->local.environment,
9510 delete_flags,
9511 d->info8.version),
9512 "failed to delete driver");
9514 torture_assert(tctx,
9515 check_printer_driver_files(tctx, dcerpc_server_name(p), d, false),
9516 "printer driver file check failed");
9518 talloc_free(d);
9519 return true;
9522 static bool test_del_driver_unused_files(struct torture_context *tctx,
9523 struct dcerpc_pipe *p)
9525 struct torture_driver_context *d1;
9526 struct torture_driver_context *d2;
9527 uint32_t add_flags = APD_COPY_NEW_FILES;
9528 struct dcerpc_binding_handle *b = p->binding_handle;
9529 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9531 d1 = talloc_zero(tctx, struct torture_driver_context);
9532 d1->ex = true;
9533 d1->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9534 d1->info8.driver_name = TORTURE_DRIVER_DELETER;
9535 d1->info8.architecture = NULL;
9536 d1->info8.driver_path = talloc_strdup(d1, "pscript5.dll");
9537 d1->info8.data_file = talloc_strdup(d1, "cups6.ppd");
9538 d1->info8.config_file = talloc_strdup(d1, "cupsui6.dll");
9539 d1->info8.help_file = talloc_strdup(d1, "pscript.hlp");
9540 d1->local.environment = talloc_strdup(d1, SPOOLSS_ARCHITECTURE_x64);
9541 d1->local.driver_directory = talloc_strdup(d1, "/usr/share/cups/drivers/x64");
9542 d1->info8.architecture = d1->local.environment;
9544 d2 = talloc_zero(tctx, struct torture_driver_context);
9545 d2->ex = true;
9546 d2->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9547 d2->info8.driver_name = TORTURE_DRIVER_DELETERIN;
9548 d2->info8.architecture = NULL;
9549 d2->info8.driver_path = talloc_strdup(d2, "pscript5.dll"); /* overlapping */
9550 d2->info8.data_file = talloc_strdup(d2, "cupsps6.dll");
9551 d2->info8.config_file = talloc_strdup(d2, "cups6.ini");
9552 d2->info8.help_file = talloc_strdup(d2, "pscript.hlp"); /* overlapping */
9553 d2->local.environment = talloc_strdup(d2, SPOOLSS_ARCHITECTURE_x64);
9554 d2->local.driver_directory = talloc_strdup(d2, "/usr/share/cups/drivers/x64");
9555 d2->info8.architecture = d2->local.environment;
9557 torture_assert(tctx,
9558 fillup_printserver_info(tctx, p, d1),
9559 "failed to fillup printserver info");
9560 torture_assert(tctx,
9561 fillup_printserver_info(tctx, p, d2),
9562 "failed to fillup printserver info");
9564 if (!directory_exist(d1->local.driver_directory)) {
9565 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9568 torture_assert(tctx,
9569 upload_printer_driver(tctx, dcerpc_server_name(p), d1),
9570 "failed to upload printer driver");
9571 torture_assert(tctx,
9572 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d1->info8, add_flags, true, NULL),
9573 "failed to add driver");
9575 torture_assert(tctx,
9576 upload_printer_driver(tctx, dcerpc_server_name(p), d2),
9577 "failed to upload printer driver");
9578 torture_assert(tctx,
9579 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d2->info8, add_flags, true, NULL),
9580 "failed to add driver");
9582 /* some files are in use by a separate driver, should fail */
9583 torture_assert(tctx,
9584 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9585 d1->info8.driver_name,
9586 d1->local.environment,
9587 DPD_DELETE_ALL_FILES,
9588 d1->info8.version,
9589 WERR_PRINTER_DRIVER_IN_USE),
9590 "invalid delete driver response");
9592 /* should only delete files not in use by other driver */
9593 torture_assert(tctx,
9594 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9595 d1->info8.driver_name,
9596 d1->local.environment,
9597 DPD_DELETE_UNUSED_FILES,
9598 d1->info8.version,
9599 WERR_OK),
9600 "failed to delete driver (unused files)");
9602 /* check non-overlapping were deleted */
9603 d1->info8.driver_path = NULL;
9604 d1->info8.help_file = NULL;
9605 torture_assert(tctx,
9606 check_printer_driver_files(tctx, dcerpc_server_name(p), d1, false),
9607 "printer driver file check failed");
9608 /* d2 files should be uneffected */
9609 torture_assert(tctx,
9610 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, true),
9611 "printer driver file check failed");
9613 torture_assert(tctx,
9614 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9615 d2->info8.driver_name,
9616 d2->local.environment,
9617 DPD_DELETE_ALL_FILES,
9618 d2->info8.version,
9619 WERR_OK),
9620 "failed to delete driver");
9622 torture_assert(tctx,
9623 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, false),
9624 "printer driver file check failed");
9626 talloc_free(d1);
9627 talloc_free(d2);
9628 return true;
9631 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
9633 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
9635 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
9636 "driver", &ndr_table_spoolss);
9637 torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
9638 torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
9640 torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
9641 torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
9643 torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
9645 torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
9647 torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
9649 torture_rpc_tcase_add_test(tcase, "multiple_drivers", test_multiple_drivers);
9651 torture_rpc_tcase_add_test(tcase, "del_driver_all_files", test_del_driver_all_files);
9653 torture_rpc_tcase_add_test(tcase, "del_driver_unused_files", test_del_driver_unused_files);
9655 return suite;