s3-printing: return talloced print jobs
[Samba.git] / source4 / torture / rpc / spoolss.c
bloba724aeeae16791e35eeb30bc304b5db0c41f884a
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 "libcli/smb2/smb2.h"
39 #include "libcli/smb2/smb2_calls.h"
40 #include "lib/cmdline/popt_common.h"
41 #include "system/filesys.h"
42 #include "torture/ndr/ndr.h"
43 #include "torture/smb2/proto.h"
45 #define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
46 #define TORTURE_PRINTER "torture_printer"
47 #define TORTURE_WELLKNOWN_PRINTER_EX "torture_wkn_printer_ex"
48 #define TORTURE_PRINTER_EX "torture_printer_ex"
49 #define TORTURE_DRIVER "torture_driver"
50 #define TORTURE_DRIVER_EX "torture_driver_ex"
51 #define TORTURE_DRIVER_ADOBE "torture_driver_adobe"
52 #define TORTURE_DRIVER_EX_ADOBE "torture_driver_ex_adobe"
53 #define TORTURE_DRIVER_ADOBE_CUPSADDSMB "torture_driver_adobe_cupsaddsmb"
54 #define TORTURE_DRIVER_TIMESTAMPS "torture_driver_timestamps"
55 #define TORTURE_DRIVER_DELETER "torture_driver_deleter"
56 #define TORTURE_DRIVER_DELETERIN "torture_driver_deleterin"
58 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
59 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
60 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
61 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
62 #define TOP_LEVEL_CONTROL_PRINTERS_KEY TOP_LEVEL_CONTROL_KEY "\\Printers"
63 #define TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY TOP_LEVEL_CONTROL_KEY "\\Environments"
65 struct test_spoolss_context {
66 struct dcerpc_pipe *spoolss_pipe;
68 /* server environment */
69 const char *environment;
71 /* print server handle */
72 struct policy_handle server_handle;
74 /* for EnumPorts */
75 uint32_t port_count[3];
76 union spoolss_PortInfo *ports[3];
78 /* for EnumPrinterDrivers */
79 uint32_t driver_count[8];
80 union spoolss_DriverInfo *drivers[8];
82 /* for EnumMonitors */
83 uint32_t monitor_count[3];
84 union spoolss_MonitorInfo *monitors[3];
86 /* for EnumPrintProcessors */
87 uint32_t print_processor_count[2];
88 union spoolss_PrintProcessorInfo *print_processors[2];
90 /* for EnumPrinters */
91 uint32_t printer_count[6];
92 union spoolss_PrinterInfo *printers[6];
95 struct torture_driver_context {
96 struct {
97 const char *driver_directory;
98 const char *environment;
99 } local;
100 struct {
101 const char *driver_directory;
102 const char *environment;
103 } remote;
104 struct spoolss_AddDriverInfo8 info8;
105 bool ex;
108 struct torture_printer_context {
109 struct dcerpc_pipe *spoolss_pipe;
110 struct spoolss_SetPrinterInfo2 info2;
111 struct torture_driver_context driver;
112 bool ex;
113 bool wellknown;
114 bool added_driver;
115 bool have_driver;
116 struct spoolss_DeviceMode *devmode;
117 struct policy_handle handle;
120 static bool upload_printer_driver(struct torture_context *tctx,
121 const char *server_name,
122 struct torture_driver_context *d);
123 static bool remove_printer_driver(struct torture_context *tctx,
124 const char *server_name,
125 struct torture_driver_context *d);
126 static bool fillup_printserver_info(struct torture_context *tctx,
127 struct dcerpc_pipe *p,
128 struct torture_driver_context *d);
129 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
130 struct dcerpc_binding_handle *b,
131 const char *server_name,
132 struct spoolss_AddDriverInfo8 *r,
133 uint32_t flags,
134 bool ex,
135 const char *remote_driver_dir);
137 #define COMPARE_STRING(tctx, c,r,e) \
138 torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
140 /* not every compiler supports __typeof__() */
141 #if (__GNUC__ >= 3)
142 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
143 if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
144 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
146 if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
147 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
149 } while(0)
150 #else
151 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
152 #endif
154 #define COMPARE_UINT32(tctx, c, r, e) do {\
155 _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
156 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
157 } while(0)
159 #define COMPARE_UINT64(tctx, c, r, e) do {\
160 _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
161 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
162 } while(0)
165 #define COMPARE_NTTIME(tctx, c, r, e) do {\
166 _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
167 torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
168 } while(0)
170 #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
171 int __i; \
172 if (!c.e && !r.e) { \
173 break; \
175 if (c.e && !r.e) { \
176 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
178 if (!c.e && r.e) { \
179 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
181 for (__i=0;c.e[__i] != NULL; __i++) { \
182 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
184 } while(0)
186 #define CHECK_ALIGN(size, n) do {\
187 if (size % n) {\
188 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
189 size, n, size + n - (size % n));\
191 } while(0)
193 #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
195 #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, needed, align) do { \
196 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
197 uint32_t size = ndr_size_##fn##_info(tctx, level, count, info);\
198 uint32_t round_size = DO_ROUND(size, align);\
199 if (round_size != needed) {\
200 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
201 CHECK_ALIGN(size, align);\
204 } while(0)
206 #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, needed, align) do { \
207 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
208 uint32_t size = ndr_size_##fn##_info(tctx, count, info);\
209 uint32_t round_size = DO_ROUND(size, align);\
210 if (round_size != needed) {\
211 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
212 CHECK_ALIGN(size, align);\
215 } while(0)
217 #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, needed, align) do { \
218 if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
219 uint32_t size = ndr_size_##fn(info, level, 0);\
220 uint32_t round_size = DO_ROUND(size, align);\
221 if (round_size != needed) {\
222 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
223 CHECK_ALIGN(size, align);\
226 } while(0)
228 static bool PrinterInfo_to_SetPrinterInfo(struct torture_context *tctx,
229 const union spoolss_PrinterInfo *i,
230 uint32_t level,
231 union spoolss_SetPrinterInfo *s)
233 switch (level) {
234 case 0:
235 s->info0 = talloc(tctx, struct spoolss_SetPrinterInfo0);
236 break;
237 case 2:
238 s->info2 = talloc(tctx, struct spoolss_SetPrinterInfo2);
239 s->info2->servername = i->info2.servername;
240 s->info2->printername = i->info2.printername;
241 s->info2->sharename = i->info2.sharename;
242 s->info2->portname = i->info2.portname;
243 s->info2->drivername = i->info2.drivername;
244 s->info2->comment = i->info2.comment;
245 s->info2->location = i->info2.location;
246 s->info2->devmode_ptr = 0;
247 s->info2->sepfile = i->info2.sepfile;
248 s->info2->printprocessor = i->info2.printprocessor;
249 s->info2->datatype = i->info2.datatype;
250 s->info2->parameters = i->info2.parameters;
251 s->info2->secdesc_ptr = 0;
252 s->info2->attributes = i->info2.attributes;
253 s->info2->priority = i->info2.priority;
254 s->info2->defaultpriority = i->info2.defaultpriority;
255 s->info2->starttime = i->info2.starttime;
256 s->info2->untiltime = i->info2.untiltime;
257 s->info2->status = i->info2.status;
258 s->info2->cjobs = i->info2.cjobs;
259 s->info2->averageppm = i->info2.averageppm;
260 break;
261 case 3:
262 case 4:
263 case 5:
264 case 6:
265 case 7:
266 case 8:
267 case 9:
268 default:
269 return false;
272 return true;
275 static bool test_OpenPrinter_server(struct torture_context *tctx,
276 struct dcerpc_pipe *p,
277 struct policy_handle *server_handle)
279 NTSTATUS status;
280 struct spoolss_OpenPrinter op;
281 struct dcerpc_binding_handle *b = p->binding_handle;
283 op.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
284 op.in.datatype = NULL;
285 op.in.devmode_ctr.devmode= NULL;
286 op.in.access_mask = 0;
287 op.out.handle = server_handle;
289 torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
291 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
292 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
293 torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
295 return true;
298 static bool test_EnumPorts(struct torture_context *tctx,
299 void *private_data)
301 struct test_spoolss_context *ctx =
302 talloc_get_type_abort(private_data, struct test_spoolss_context);
303 struct dcerpc_pipe *p = ctx->spoolss_pipe;
304 struct dcerpc_binding_handle *b = p->binding_handle;
305 NTSTATUS status;
306 struct spoolss_EnumPorts r;
307 uint16_t levels[] = { 1, 2 };
308 int i, j;
310 for (i=0;i<ARRAY_SIZE(levels);i++) {
311 int level = levels[i];
312 DATA_BLOB blob;
313 uint32_t needed;
314 uint32_t count;
315 union spoolss_PortInfo *info;
317 r.in.servername = "";
318 r.in.level = level;
319 r.in.buffer = NULL;
320 r.in.offered = 0;
321 r.out.needed = &needed;
322 r.out.count = &count;
323 r.out.info = &info;
325 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
327 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
328 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
329 if (W_ERROR_IS_OK(r.out.result)) {
330 /* TODO: do some more checks here */
331 continue;
333 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
334 "EnumPorts unexpected return code");
336 blob = data_blob_talloc_zero(ctx, needed);
337 r.in.buffer = &blob;
338 r.in.offered = needed;
340 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
341 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
343 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
345 torture_assert(tctx, info, "EnumPorts returned no info");
347 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, needed, 4);
349 ctx->port_count[level] = count;
350 ctx->ports[level] = info;
353 for (i=1;i<ARRAY_SIZE(levels);i++) {
354 int level = levels[i];
355 int old_level = levels[i-1];
356 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
357 "EnumPorts invalid value");
359 /* if the array sizes are not the same we would maybe segfault in the following code */
361 for (i=0;i<ARRAY_SIZE(levels);i++) {
362 int level = levels[i];
363 for (j=0;j<ctx->port_count[level];j++) {
364 union spoolss_PortInfo *cur = &ctx->ports[level][j];
365 union spoolss_PortInfo *ref = &ctx->ports[2][j];
366 switch (level) {
367 case 1:
368 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
369 break;
370 case 2:
371 /* level 2 is our reference, and it makes no sense to compare it to itself */
372 break;
377 return true;
380 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
381 void *private_data)
383 struct test_spoolss_context *ctx =
384 talloc_get_type_abort(private_data, struct test_spoolss_context);
386 NTSTATUS status;
387 struct dcerpc_pipe *p = ctx->spoolss_pipe;
388 struct dcerpc_binding_handle *b = p->binding_handle;
389 struct spoolss_GetPrintProcessorDirectory r;
390 struct {
391 uint16_t level;
392 const char *server;
393 } levels[] = {{
394 .level = 1,
395 .server = NULL
397 .level = 1,
398 .server = ""
400 .level = 78,
401 .server = ""
403 .level = 1,
404 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
406 .level = 1024,
407 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
410 int i;
411 uint32_t needed;
413 for (i=0;i<ARRAY_SIZE(levels);i++) {
414 int level = levels[i].level;
415 DATA_BLOB blob;
417 r.in.server = levels[i].server;
418 r.in.environment = ctx->environment;
419 r.in.level = level;
420 r.in.buffer = NULL;
421 r.in.offered = 0;
422 r.out.needed = &needed;
424 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
426 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
427 torture_assert_ntstatus_ok(tctx, status,
428 "dcerpc_spoolss_GetPrintProcessorDirectory failed");
429 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
430 "GetPrintProcessorDirectory unexpected return code");
432 blob = data_blob_talloc_zero(tctx, needed);
433 r.in.buffer = &blob;
434 r.in.offered = needed;
436 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
437 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
439 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
441 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, needed, 2);
444 return true;
448 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
449 void *private_data)
451 struct test_spoolss_context *ctx =
452 talloc_get_type_abort(private_data, struct test_spoolss_context);
454 NTSTATUS status;
455 struct dcerpc_pipe *p = ctx->spoolss_pipe;
456 struct dcerpc_binding_handle *b = p->binding_handle;
457 struct spoolss_GetPrinterDriverDirectory r;
458 struct {
459 uint16_t level;
460 const char *server;
461 } levels[] = {{
462 .level = 1,
463 .server = NULL
465 .level = 1,
466 .server = ""
468 .level = 78,
469 .server = ""
471 .level = 1,
472 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
474 .level = 1024,
475 .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
478 int i;
479 uint32_t needed;
481 for (i=0;i<ARRAY_SIZE(levels);i++) {
482 int level = levels[i].level;
483 DATA_BLOB blob;
485 r.in.server = levels[i].server;
486 r.in.environment = ctx->environment;
487 r.in.level = level;
488 r.in.buffer = NULL;
489 r.in.offered = 0;
490 r.out.needed = &needed;
492 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
494 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
495 torture_assert_ntstatus_ok(tctx, status,
496 "dcerpc_spoolss_GetPrinterDriverDirectory failed");
497 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
498 "GetPrinterDriverDirectory unexpected return code");
500 blob = data_blob_talloc_zero(tctx, needed);
501 r.in.buffer = &blob;
502 r.in.offered = needed;
504 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
505 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
507 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
509 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, needed, 2);
512 return true;
515 static bool test_EnumPrinterDrivers_args(struct torture_context *tctx,
516 struct dcerpc_binding_handle *b,
517 const char *server_name,
518 const char *environment,
519 uint32_t level,
520 uint32_t *count_p,
521 union spoolss_DriverInfo **info_p)
523 struct spoolss_EnumPrinterDrivers r;
524 uint32_t needed;
525 uint32_t count;
526 union spoolss_DriverInfo *info;
528 r.in.server = server_name;
529 r.in.environment = environment;
530 r.in.level = level;
531 r.in.buffer = NULL;
532 r.in.offered = 0;
533 r.out.needed = &needed;
534 r.out.count = &count;
535 r.out.info = &info;
537 torture_comment(tctx, "Testing EnumPrinterDrivers(%s) level %u\n",
538 r.in.environment, r.in.level);
540 torture_assert_ntstatus_ok(tctx,
541 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
542 "EnumPrinterDrivers failed");
543 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
544 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
545 r.in.buffer = &blob;
546 r.in.offered = needed;
548 torture_assert_ntstatus_ok(tctx,
549 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
550 "EnumPrinterDrivers failed");
553 torture_assert_werr_ok(tctx, r.out.result,
554 "EnumPrinterDrivers failed");
556 if (count_p) {
557 *count_p = count;
559 if (info_p) {
560 *info_p = info;
563 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, needed, 4);
565 return true;
569 static bool test_EnumPrinterDrivers_findone(struct torture_context *tctx,
570 struct dcerpc_binding_handle *b,
571 const char *server_name,
572 const char *environment,
573 uint32_t level,
574 const char *driver_name,
575 union spoolss_DriverInfo *info_p)
577 uint32_t count;
578 union spoolss_DriverInfo *info;
579 int i;
580 const char *environment_ret = NULL;
582 torture_assert(tctx,
583 test_EnumPrinterDrivers_args(tctx, b, server_name, environment, level, &count, &info),
584 "failed to enumerate printer drivers");
586 for (i=0; i < count; i++) {
587 const char *driver_name_ret;
588 switch (level) {
589 case 1:
590 driver_name_ret = info[i].info1.driver_name;
591 break;
592 case 2:
593 driver_name_ret = info[i].info2.driver_name;
594 environment_ret = info[i].info2.architecture;
595 break;
596 case 3:
597 driver_name_ret = info[i].info3.driver_name;
598 environment_ret = info[i].info3.architecture;
599 break;
600 case 4:
601 driver_name_ret = info[i].info4.driver_name;
602 environment_ret = info[i].info4.architecture;
603 break;
604 case 5:
605 driver_name_ret = info[i].info5.driver_name;
606 environment_ret = info[i].info5.architecture;
607 break;
608 case 6:
609 driver_name_ret = info[i].info6.driver_name;
610 environment_ret = info[i].info6.architecture;
611 break;
612 case 7:
613 driver_name_ret = info[i].info7.driver_name;
614 break;
615 case 8:
616 driver_name_ret = info[i].info8.driver_name;
617 environment_ret = info[i].info8.architecture;
618 break;
619 default:
620 break;
622 if (environment_ret) {
623 torture_assert_str_equal(tctx, environment, environment_ret, "architecture mismatch");
625 if (strequal(driver_name, driver_name_ret)) {
626 if (info_p) {
627 *info_p = info[i];
629 return true;
633 return false;
636 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
637 void *private_data)
639 struct test_spoolss_context *ctx =
640 talloc_get_type_abort(private_data, struct test_spoolss_context);
641 struct dcerpc_pipe *p = ctx->spoolss_pipe;
642 struct dcerpc_binding_handle *b = p->binding_handle;
643 uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
644 int i, j, a;
646 /* FIXME: gd, come back and fix "" as server, and handle
647 * priority of returned error codes in torture test and samba 3
648 * server */
649 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
650 const char *environments[2];
652 environments[0] = SPOOLSS_ARCHITECTURE_ALL;
653 environments[1] = ctx->environment;
655 for (a=0;a<ARRAY_SIZE(environments);a++) {
657 for (i=0;i<ARRAY_SIZE(levels);i++) {
658 int level = levels[i];
659 uint32_t count;
660 union spoolss_DriverInfo *info;
662 torture_assert(tctx,
663 test_EnumPrinterDrivers_args(tctx, b, server_name, environments[a], level, &count, &info),
664 "failed to enumerate drivers");
666 ctx->driver_count[level] = count;
667 ctx->drivers[level] = info;
670 for (i=1;i<ARRAY_SIZE(levels);i++) {
671 int level = levels[i];
672 int old_level = levels[i-1];
674 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
675 "EnumPrinterDrivers invalid value");
678 for (i=0;i<ARRAY_SIZE(levels);i++) {
679 int level = levels[i];
681 for (j=0;j<ctx->driver_count[level];j++) {
682 union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
683 union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
685 switch (level) {
686 case 1:
687 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
688 break;
689 case 2:
690 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
691 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
692 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
693 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
694 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
695 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
696 break;
697 case 3:
698 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
699 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
700 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
701 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
702 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
703 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
704 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
705 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
706 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
707 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
708 break;
709 case 4:
710 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
711 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
712 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
713 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
714 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
715 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
716 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
717 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
718 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
719 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
720 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
721 break;
722 case 5:
723 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
724 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
725 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
726 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
727 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
728 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
729 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
730 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
731 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
732 break;
733 case 6:
734 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
735 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
736 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
737 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
738 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
739 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
740 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
741 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
742 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
743 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
744 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
745 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
746 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
747 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
748 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
749 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
750 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
751 break;
752 case 8:
753 /* level 8 is our reference, and it makes no sense to compare it to itself */
754 break;
760 return true;
763 static bool test_EnumMonitors(struct torture_context *tctx,
764 void *private_data)
766 struct test_spoolss_context *ctx =
767 talloc_get_type_abort(private_data, struct test_spoolss_context);
768 struct dcerpc_pipe *p = ctx->spoolss_pipe;
769 struct dcerpc_binding_handle *b = p->binding_handle;
770 NTSTATUS status;
771 struct spoolss_EnumMonitors r;
772 uint16_t levels[] = { 1, 2 };
773 int i, j;
775 for (i=0;i<ARRAY_SIZE(levels);i++) {
776 int level = levels[i];
777 DATA_BLOB blob;
778 uint32_t needed;
779 uint32_t count;
780 union spoolss_MonitorInfo *info;
782 r.in.servername = "";
783 r.in.level = level;
784 r.in.buffer = NULL;
785 r.in.offered = 0;
786 r.out.needed = &needed;
787 r.out.count = &count;
788 r.out.info = &info;
790 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
792 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
793 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
794 if (W_ERROR_IS_OK(r.out.result)) {
795 /* TODO: do some more checks here */
796 continue;
798 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
799 "EnumMonitors failed");
801 blob = data_blob_talloc_zero(ctx, needed);
802 r.in.buffer = &blob;
803 r.in.offered = needed;
805 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
806 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
808 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
810 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, needed, 4);
812 ctx->monitor_count[level] = count;
813 ctx->monitors[level] = info;
816 for (i=1;i<ARRAY_SIZE(levels);i++) {
817 int level = levels[i];
818 int old_level = levels[i-1];
819 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
820 "EnumMonitors invalid value");
823 for (i=0;i<ARRAY_SIZE(levels);i++) {
824 int level = levels[i];
825 for (j=0;j<ctx->monitor_count[level];j++) {
826 union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
827 union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
828 switch (level) {
829 case 1:
830 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
831 break;
832 case 2:
833 /* level 2 is our reference, and it makes no sense to compare it to itself */
834 break;
839 return true;
842 static bool test_EnumPrintProcessors_level(struct torture_context *tctx,
843 struct dcerpc_binding_handle *b,
844 const char *environment,
845 uint32_t level,
846 uint32_t *count_p,
847 union spoolss_PrintProcessorInfo **info_p,
848 WERROR expected_result)
850 struct spoolss_EnumPrintProcessors r;
851 DATA_BLOB blob;
852 uint32_t needed;
853 uint32_t count;
854 union spoolss_PrintProcessorInfo *info;
856 r.in.servername = "";
857 r.in.environment = environment;
858 r.in.level = level;
859 r.in.buffer = NULL;
860 r.in.offered = 0;
861 r.out.needed = &needed;
862 r.out.count = &count;
863 r.out.info = &info;
865 torture_comment(tctx, "Testing EnumPrintProcessors(%s) level %u\n",
866 r.in.environment, r.in.level);
868 torture_assert_ntstatus_ok(tctx,
869 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
870 "EnumPrintProcessors failed");
871 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
872 blob = data_blob_talloc_zero(tctx, needed);
873 r.in.buffer = &blob;
874 r.in.offered = needed;
875 torture_assert_ntstatus_ok(tctx,
876 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
877 "EnumPrintProcessors failed");
879 torture_assert_werr_equal(tctx, r.out.result, expected_result,
880 "EnumPrintProcessors failed");
882 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, level, count, needed, 4);
884 if (count_p) {
885 *count_p = count;
887 if (info_p) {
888 *info_p = info;
891 return true;
894 static bool test_EnumPrintProcessors(struct torture_context *tctx,
895 void *private_data)
897 struct test_spoolss_context *ctx =
898 talloc_get_type_abort(private_data, struct test_spoolss_context);
900 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
901 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
902 int i;
903 struct dcerpc_pipe *p = ctx->spoolss_pipe;
904 struct dcerpc_binding_handle *b = p->binding_handle;
906 torture_assert(tctx,
907 test_EnumPrintProcessors_level(tctx, b, "phantasy", 1, NULL, NULL, WERR_INVALID_ENVIRONMENT),
908 "test_EnumPrintProcessors_level failed");
910 for (i=0;i<ARRAY_SIZE(levels);i++) {
911 union spoolss_PrintProcessorInfo *info;
912 uint32_t count;
913 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
915 torture_assert(tctx,
916 test_EnumPrintProcessors_level(tctx, b, ctx->environment, levels[i], &count, &info, expected_result),
917 "test_EnumPrintProcessors_level failed");
920 return true;
923 static bool test_EnumPrintProcDataTypes_level(struct torture_context *tctx,
924 struct dcerpc_binding_handle *b,
925 const char *print_processor_name,
926 uint32_t level,
927 uint32_t *count_p,
928 union spoolss_PrintProcDataTypesInfo **info_p,
929 WERROR expected_result)
931 struct spoolss_EnumPrintProcDataTypes r;
932 DATA_BLOB blob;
933 uint32_t needed;
934 uint32_t count;
935 union spoolss_PrintProcDataTypesInfo *info;
937 r.in.servername = "";
938 r.in.print_processor_name = print_processor_name;
939 r.in.level = level;
940 r.in.buffer = NULL;
941 r.in.offered = 0;
942 r.out.needed = &needed;
943 r.out.count = &count;
944 r.out.info = &info;
946 torture_comment(tctx, "Testing EnumPrintProcDataTypes(%s) level %u\n",
947 r.in.print_processor_name, r.in.level);
949 torture_assert_ntstatus_ok(tctx,
950 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
951 "EnumPrintProcDataTypes failed");
952 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
953 blob = data_blob_talloc_zero(tctx, needed);
954 r.in.buffer = &blob;
955 r.in.offered = needed;
956 torture_assert_ntstatus_ok(tctx,
957 dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
958 "EnumPrintProcDataTypes failed");
960 torture_assert_werr_equal(tctx, r.out.result, expected_result,
961 "EnumPrintProcDataTypes failed");
963 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, level, count, needed, 4);
965 if (count_p) {
966 *count_p = count;
968 if (info_p) {
969 *info_p = info;
972 return true;
975 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
976 void *private_data)
978 struct test_spoolss_context *ctx =
979 talloc_get_type_abort(private_data, struct test_spoolss_context);
981 uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
982 uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
983 int i;
984 struct dcerpc_pipe *p = ctx->spoolss_pipe;
985 struct dcerpc_binding_handle *b = p->binding_handle;
987 torture_assert(tctx,
988 test_EnumPrintProcDataTypes_level(tctx, b, NULL, 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
989 "test_EnumPrintProcDataTypes_level failed");
991 torture_assert(tctx,
992 test_EnumPrintProcDataTypes_level(tctx, b, "nonexisting", 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
993 "test_EnumPrintProcDataTypes_level failed");
995 for (i=0;i<ARRAY_SIZE(levels);i++) {
996 int level = levels[i];
997 uint32_t count;
998 union spoolss_PrintProcDataTypesInfo *info;
999 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
1001 torture_assert(tctx,
1002 test_EnumPrintProcDataTypes_level(tctx, b, "winprint", level, &count, &info, expected_result),
1003 "test_EnumPrintProcDataTypes_level failed");
1007 union spoolss_PrintProcessorInfo *info;
1008 uint32_t count;
1010 torture_assert(tctx,
1011 test_EnumPrintProcessors_level(tctx, b, ctx->environment, 1, &count, &info, WERR_OK),
1012 "test_EnumPrintProcessors_level failed");
1014 for (i=0; i < count; i++) {
1015 torture_assert(tctx,
1016 test_EnumPrintProcDataTypes_level(tctx, b, info[i].info1.print_processor_name, 1, NULL, NULL, WERR_OK),
1017 "test_EnumPrintProcDataTypes_level failed");
1022 return true;
1025 static bool test_EnumPrinters(struct torture_context *tctx,
1026 void *private_data)
1028 struct test_spoolss_context *ctx =
1029 talloc_get_type_abort(private_data, struct test_spoolss_context);
1030 struct dcerpc_pipe *p = ctx->spoolss_pipe;
1031 struct dcerpc_binding_handle *b = p->binding_handle;
1032 struct spoolss_EnumPrinters r;
1033 NTSTATUS status;
1034 uint16_t levels[] = { 0, 1, 2, 4, 5 };
1035 int i, j;
1037 for (i=0;i<ARRAY_SIZE(levels);i++) {
1038 int level = levels[i];
1039 DATA_BLOB blob;
1040 uint32_t needed;
1041 uint32_t count;
1042 union spoolss_PrinterInfo *info;
1044 r.in.flags = PRINTER_ENUM_LOCAL;
1045 r.in.server = "";
1046 r.in.level = level;
1047 r.in.buffer = NULL;
1048 r.in.offered = 0;
1049 r.out.needed = &needed;
1050 r.out.count = &count;
1051 r.out.info = &info;
1053 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1055 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1056 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1057 if (W_ERROR_IS_OK(r.out.result)) {
1058 /* TODO: do some more checks here */
1059 continue;
1061 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
1062 "EnumPrinters unexpected return code");
1064 blob = data_blob_talloc_zero(ctx, needed);
1065 r.in.buffer = &blob;
1066 r.in.offered = needed;
1068 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
1069 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
1071 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1073 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
1075 ctx->printer_count[level] = count;
1076 ctx->printers[level] = info;
1079 for (i=1;i<ARRAY_SIZE(levels);i++) {
1080 int level = levels[i];
1081 int old_level = levels[i-1];
1082 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
1083 "EnumPrinters invalid value");
1086 for (i=0;i<ARRAY_SIZE(levels);i++) {
1087 int level = levels[i];
1088 for (j=0;j<ctx->printer_count[level];j++) {
1089 union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
1090 union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
1091 switch (level) {
1092 case 0:
1093 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
1094 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
1095 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
1096 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
1097 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
1098 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
1099 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
1100 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
1101 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
1102 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
1103 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
1104 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
1105 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
1106 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
1107 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
1108 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
1109 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
1110 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
1111 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
1112 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
1113 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
1114 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
1115 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
1116 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
1117 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
1118 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
1119 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
1120 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
1121 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
1122 break;
1123 case 1:
1124 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
1125 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
1126 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
1127 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
1128 break;
1129 case 2:
1130 /* level 2 is our reference, and it makes no sense to compare it to itself */
1131 break;
1132 case 4:
1133 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
1134 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
1135 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
1136 break;
1137 case 5:
1138 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
1139 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
1140 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
1141 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
1142 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
1143 break;
1148 /* TODO:
1149 * - verify that the port of a printer was in the list returned by EnumPorts
1152 return true;
1155 static bool test_GetPrinterDriver2(struct torture_context *tctx,
1156 struct dcerpc_binding_handle *b,
1157 struct policy_handle *handle,
1158 const char *driver_name,
1159 const char *environment);
1161 bool test_GetPrinter_level(struct torture_context *tctx,
1162 struct dcerpc_binding_handle *b,
1163 struct policy_handle *handle,
1164 uint32_t level,
1165 union spoolss_PrinterInfo *info)
1167 struct spoolss_GetPrinter r;
1168 uint32_t needed;
1170 r.in.handle = handle;
1171 r.in.level = level;
1172 r.in.buffer = NULL;
1173 r.in.offered = 0;
1174 r.out.needed = &needed;
1176 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
1178 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1179 "GetPrinter failed");
1181 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1182 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
1183 r.in.buffer = &blob;
1184 r.in.offered = needed;
1186 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
1187 "GetPrinter failed");
1190 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
1192 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, needed, 4);
1194 if (info && r.out.info) {
1195 *info = *r.out.info;
1198 return true;
1202 static bool test_GetPrinter(struct torture_context *tctx,
1203 struct dcerpc_binding_handle *b,
1204 struct policy_handle *handle,
1205 const char *environment)
1207 uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1208 int i;
1210 for (i=0;i<ARRAY_SIZE(levels);i++) {
1212 union spoolss_PrinterInfo info;
1214 ZERO_STRUCT(info);
1216 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
1217 "failed to call GetPrinter");
1219 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
1220 torture_assert(tctx,
1221 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
1222 "failed to call test_GetPrinterDriver2");
1226 return true;
1229 static bool test_SetPrinter(struct torture_context *tctx,
1230 struct dcerpc_binding_handle *b,
1231 struct policy_handle *handle,
1232 struct spoolss_SetPrinterInfoCtr *info_ctr,
1233 struct spoolss_DevmodeContainer *devmode_ctr,
1234 struct sec_desc_buf *secdesc_ctr,
1235 enum spoolss_PrinterControl command)
1237 struct spoolss_SetPrinter r;
1239 r.in.handle = handle;
1240 r.in.info_ctr = info_ctr;
1241 r.in.devmode_ctr = devmode_ctr;
1242 r.in.secdesc_ctr = secdesc_ctr;
1243 r.in.command = command;
1245 torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
1247 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1248 "failed to call SetPrinter");
1249 torture_assert_werr_ok(tctx, r.out.result,
1250 "failed to call SetPrinter");
1252 return true;
1255 static bool test_SetPrinter_errors(struct torture_context *tctx,
1256 struct dcerpc_binding_handle *b,
1257 struct policy_handle *handle)
1259 struct spoolss_SetPrinter r;
1260 uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1261 int i;
1263 struct spoolss_SetPrinterInfoCtr info_ctr;
1264 struct spoolss_DevmodeContainer devmode_ctr;
1265 struct sec_desc_buf secdesc_ctr;
1267 info_ctr.level = 0;
1268 info_ctr.info.info0 = NULL;
1270 ZERO_STRUCT(devmode_ctr);
1271 ZERO_STRUCT(secdesc_ctr);
1273 r.in.handle = handle;
1274 r.in.info_ctr = &info_ctr;
1275 r.in.devmode_ctr = &devmode_ctr;
1276 r.in.secdesc_ctr = &secdesc_ctr;
1277 r.in.command = 0;
1279 torture_comment(tctx, "Testing SetPrinter all zero\n");
1281 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1282 "failed to call SetPrinter");
1283 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1284 "failed to call SetPrinter");
1286 again:
1287 for (i=0; i < ARRAY_SIZE(levels); i++) {
1289 struct spoolss_SetPrinterInfo0 info0;
1290 struct spoolss_SetPrinterInfo1 info1;
1291 struct spoolss_SetPrinterInfo2 info2;
1292 struct spoolss_SetPrinterInfo3 info3;
1293 struct spoolss_SetPrinterInfo4 info4;
1294 struct spoolss_SetPrinterInfo5 info5;
1295 struct spoolss_SetPrinterInfo6 info6;
1296 struct spoolss_SetPrinterInfo7 info7;
1297 struct spoolss_SetPrinterInfo8 info8;
1298 struct spoolss_SetPrinterInfo9 info9;
1301 info_ctr.level = levels[i];
1302 switch (levels[i]) {
1303 case 0:
1304 ZERO_STRUCT(info0);
1305 info_ctr.info.info0 = &info0;
1306 break;
1307 case 1:
1308 ZERO_STRUCT(info1);
1309 info_ctr.info.info1 = &info1;
1310 break;
1311 case 2:
1312 ZERO_STRUCT(info2);
1313 info_ctr.info.info2 = &info2;
1314 break;
1315 case 3:
1316 ZERO_STRUCT(info3);
1317 info_ctr.info.info3 = &info3;
1318 break;
1319 case 4:
1320 ZERO_STRUCT(info4);
1321 info_ctr.info.info4 = &info4;
1322 break;
1323 case 5:
1324 ZERO_STRUCT(info5);
1325 info_ctr.info.info5 = &info5;
1326 break;
1327 case 6:
1328 ZERO_STRUCT(info6);
1329 info_ctr.info.info6 = &info6;
1330 break;
1331 case 7:
1332 ZERO_STRUCT(info7);
1333 info_ctr.info.info7 = &info7;
1334 break;
1335 case 8:
1336 ZERO_STRUCT(info8);
1337 info_ctr.info.info8 = &info8;
1338 break;
1339 case 9:
1340 ZERO_STRUCT(info9);
1341 info_ctr.info.info9 = &info9;
1342 break;
1345 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
1346 info_ctr.level, r.in.command);
1348 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
1349 "failed to call SetPrinter");
1351 switch (r.in.command) {
1352 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
1353 /* is ignored for all levels other then 0 */
1354 if (info_ctr.level > 0) {
1355 /* ignored then */
1356 break;
1358 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
1359 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
1360 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
1361 if (info_ctr.level > 0) {
1362 /* is invalid for all levels other then 0 */
1363 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1364 "unexpected error code returned");
1365 continue;
1366 } else {
1367 torture_assert_werr_ok(tctx, r.out.result,
1368 "failed to call SetPrinter with non 0 command");
1369 continue;
1371 break;
1373 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
1374 /* FIXME: gd needs further investigation */
1375 default:
1376 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
1377 "unexpected error code returned");
1378 continue;
1381 switch (info_ctr.level) {
1382 case 1:
1383 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
1384 "unexpected error code returned");
1385 break;
1386 case 2:
1387 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
1388 "unexpected error code returned");
1389 break;
1390 case 3:
1391 case 4:
1392 case 5:
1393 case 7:
1394 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
1395 "unexpected error code returned");
1396 break;
1397 case 9:
1398 torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
1399 "unexpected error code returned");
1400 break;
1401 default:
1402 torture_assert_werr_ok(tctx, r.out.result,
1403 "failed to call SetPrinter");
1404 break;
1408 if (r.in.command < 5) {
1409 r.in.command++;
1410 goto again;
1413 return true;
1416 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
1418 if ((r->level == 2) && (r->info.info2)) {
1419 r->info.info2->secdesc_ptr = 0;
1420 r->info.info2->devmode_ptr = 0;
1424 static bool test_PrinterInfo(struct torture_context *tctx,
1425 struct dcerpc_binding_handle *b,
1426 struct policy_handle *handle)
1428 NTSTATUS status;
1429 struct spoolss_SetPrinter s;
1430 struct spoolss_GetPrinter q;
1431 struct spoolss_GetPrinter q0;
1432 struct spoolss_SetPrinterInfoCtr info_ctr;
1433 union spoolss_PrinterInfo info;
1434 struct spoolss_DevmodeContainer devmode_ctr;
1435 struct sec_desc_buf secdesc_ctr;
1436 uint32_t needed;
1437 bool ret = true;
1438 int i;
1440 torture_skip(tctx, "Printer Info test is currently broken, skipping");
1442 uint32_t status_list[] = {
1443 /* these do not stick
1444 PRINTER_STATUS_PAUSED,
1445 PRINTER_STATUS_ERROR,
1446 PRINTER_STATUS_PENDING_DELETION, */
1447 PRINTER_STATUS_PAPER_JAM,
1448 PRINTER_STATUS_PAPER_OUT,
1449 PRINTER_STATUS_MANUAL_FEED,
1450 PRINTER_STATUS_PAPER_PROBLEM,
1451 PRINTER_STATUS_OFFLINE,
1452 PRINTER_STATUS_IO_ACTIVE,
1453 PRINTER_STATUS_BUSY,
1454 PRINTER_STATUS_PRINTING,
1455 PRINTER_STATUS_OUTPUT_BIN_FULL,
1456 PRINTER_STATUS_NOT_AVAILABLE,
1457 PRINTER_STATUS_WAITING,
1458 PRINTER_STATUS_PROCESSING,
1459 PRINTER_STATUS_INITIALIZING,
1460 PRINTER_STATUS_WARMING_UP,
1461 PRINTER_STATUS_TONER_LOW,
1462 PRINTER_STATUS_NO_TONER,
1463 PRINTER_STATUS_PAGE_PUNT,
1464 PRINTER_STATUS_USER_INTERVENTION,
1465 PRINTER_STATUS_OUT_OF_MEMORY,
1466 PRINTER_STATUS_DOOR_OPEN,
1467 PRINTER_STATUS_SERVER_UNKNOWN,
1468 PRINTER_STATUS_POWER_SAVE,
1469 /* these do not stick
1470 0x02000000,
1471 0x04000000,
1472 0x08000000,
1473 0x10000000,
1474 0x20000000,
1475 0x40000000,
1476 0x80000000 */
1478 uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1479 uint32_t attribute_list[] = {
1480 PRINTER_ATTRIBUTE_QUEUED,
1481 /* fails with WERR_INVALID_DATATYPE:
1482 PRINTER_ATTRIBUTE_DIRECT, */
1483 /* does not stick
1484 PRINTER_ATTRIBUTE_DEFAULT, */
1485 PRINTER_ATTRIBUTE_SHARED,
1486 /* does not stick
1487 PRINTER_ATTRIBUTE_NETWORK, */
1488 PRINTER_ATTRIBUTE_HIDDEN,
1489 PRINTER_ATTRIBUTE_LOCAL,
1490 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1491 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1492 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1493 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1494 /* does not stick
1495 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1496 /* fails with WERR_INVALID_DATATYPE:
1497 PRINTER_ATTRIBUTE_RAW_ONLY, */
1498 /* these do not stick
1499 PRINTER_ATTRIBUTE_PUBLISHED,
1500 PRINTER_ATTRIBUTE_FAX,
1501 PRINTER_ATTRIBUTE_TS,
1502 0x00010000,
1503 0x00020000,
1504 0x00040000,
1505 0x00080000,
1506 0x00100000,
1507 0x00200000,
1508 0x00400000,
1509 0x00800000,
1510 0x01000000,
1511 0x02000000,
1512 0x04000000,
1513 0x08000000,
1514 0x10000000,
1515 0x20000000,
1516 0x40000000,
1517 0x80000000 */
1520 ZERO_STRUCT(devmode_ctr);
1521 ZERO_STRUCT(secdesc_ctr);
1523 s.in.handle = handle;
1524 s.in.command = 0;
1525 s.in.info_ctr = &info_ctr;
1526 s.in.devmode_ctr = &devmode_ctr;
1527 s.in.secdesc_ctr = &secdesc_ctr;
1529 q.in.handle = handle;
1530 q.out.info = &info;
1531 q0 = q;
1533 #define TESTGETCALL(call, r) \
1534 r.in.buffer = NULL; \
1535 r.in.offered = 0;\
1536 r.out.needed = &needed; \
1537 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1538 if (!NT_STATUS_IS_OK(status)) { \
1539 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1540 r.in.level, nt_errstr(status), __location__); \
1541 ret = false; \
1542 break; \
1544 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1545 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
1546 r.in.buffer = &blob; \
1547 r.in.offered = needed; \
1549 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1550 if (!NT_STATUS_IS_OK(status)) { \
1551 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1552 r.in.level, nt_errstr(status), __location__); \
1553 ret = false; \
1554 break; \
1556 if (!W_ERROR_IS_OK(r.out.result)) { \
1557 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1558 r.in.level, win_errstr(r.out.result), __location__); \
1559 ret = false; \
1560 break; \
1564 #define TESTSETCALL_EXP(call, r, err) \
1565 clear_info2(&info_ctr);\
1566 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
1567 if (!NT_STATUS_IS_OK(status)) { \
1568 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1569 r.in.info_ctr->level, nt_errstr(status), __location__); \
1570 ret = false; \
1571 break; \
1573 if (!W_ERROR_IS_OK(err)) { \
1574 if (!W_ERROR_EQUAL(err, r.out.result)) { \
1575 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1576 r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1577 ret = false; \
1579 break; \
1581 if (!W_ERROR_IS_OK(r.out.result)) { \
1582 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1583 r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1584 ret = false; \
1585 break; \
1588 #define TESTSETCALL(call, r) \
1589 TESTSETCALL_EXP(call, r, WERR_OK)
1591 #define STRING_EQUAL(s1, s2, field) \
1592 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1593 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1594 #field, s2, __location__); \
1595 ret = false; \
1596 break; \
1599 #define MEM_EQUAL(s1, s2, length, field) \
1600 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1601 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1602 #field, (const char *)s2, __location__); \
1603 ret = false; \
1604 break; \
1607 #define INT_EQUAL(i1, i2, field) \
1608 if (i1 != i2) { \
1609 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1610 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1611 ret = false; \
1612 break; \
1615 #define SD_EQUAL(sd1, sd2, field) \
1616 if (!security_descriptor_equal(sd1, sd2)) { \
1617 torture_comment(tctx, "Failed to set %s (%s)\n", \
1618 #field, __location__); \
1619 ret = false; \
1620 break; \
1623 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1624 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1625 q.in.level = lvl1; \
1626 TESTGETCALL(GetPrinter, q) \
1627 info_ctr.level = lvl1; \
1628 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1629 info_ctr.info.info ## lvl1->field1 = value;\
1630 TESTSETCALL_EXP(SetPrinter, s, err) \
1631 info_ctr.info.info ## lvl1->field1 = ""; \
1632 TESTGETCALL(GetPrinter, q) \
1633 info_ctr.info.info ## lvl1->field1 = value; \
1634 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1635 q.in.level = lvl2; \
1636 TESTGETCALL(GetPrinter, q) \
1637 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1638 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1639 } while (0)
1641 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1642 TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1643 } while (0);
1645 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1646 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1647 q.in.level = lvl1; \
1648 TESTGETCALL(GetPrinter, q) \
1649 info_ctr.level = lvl1; \
1650 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1651 info_ctr.info.info ## lvl1->field1 = value; \
1652 TESTSETCALL(SetPrinter, s) \
1653 info_ctr.info.info ## lvl1->field1 = 0; \
1654 TESTGETCALL(GetPrinter, q) \
1655 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
1656 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1657 q.in.level = lvl2; \
1658 TESTGETCALL(GetPrinter, q) \
1659 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
1660 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1661 } while (0)
1663 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1664 TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1665 } while (0)
1667 q0.in.level = 0;
1668 do { TESTGETCALL(GetPrinter, q0) } while (0);
1670 TEST_PRINTERINFO_STRING(2, comment, 1, comment, "xx2-1 comment");
1671 TEST_PRINTERINFO_STRING(2, comment, 2, comment, "xx2-2 comment");
1673 /* level 0 printername does not stick */
1674 /* TEST_PRINTERINFO_STRING(2, printername, 0, printername, "xx2-0 printer"); */
1675 TEST_PRINTERINFO_STRING(2, printername, 1, name, "xx2-1 printer");
1676 TEST_PRINTERINFO_STRING(2, printername, 2, printername, "xx2-2 printer");
1677 TEST_PRINTERINFO_STRING(2, printername, 4, printername, "xx2-4 printer");
1678 TEST_PRINTERINFO_STRING(2, printername, 5, printername, "xx2-5 printer");
1679 /* TEST_PRINTERINFO_STRING(4, printername, 0, printername, "xx4-0 printer"); */
1680 TEST_PRINTERINFO_STRING(4, printername, 1, name, "xx4-1 printer");
1681 TEST_PRINTERINFO_STRING(4, printername, 2, printername, "xx4-2 printer");
1682 TEST_PRINTERINFO_STRING(4, printername, 4, printername, "xx4-4 printer");
1683 TEST_PRINTERINFO_STRING(4, printername, 5, printername, "xx4-5 printer");
1684 /* TEST_PRINTERINFO_STRING(5, printername, 0, printername, "xx5-0 printer"); */
1685 TEST_PRINTERINFO_STRING(5, printername, 1, name, "xx5-1 printer");
1686 TEST_PRINTERINFO_STRING(5, printername, 2, printername, "xx5-2 printer");
1687 TEST_PRINTERINFO_STRING(5, printername, 4, printername, "xx5-4 printer");
1688 TEST_PRINTERINFO_STRING(5, printername, 5, printername, "xx5-5 printer");
1690 /* servername can be set but does not stick
1691 TEST_PRINTERINFO_STRING(2, servername, 0, servername, "xx2-0 servername");
1692 TEST_PRINTERINFO_STRING(2, servername, 2, servername, "xx2-2 servername");
1693 TEST_PRINTERINFO_STRING(2, servername, 4, servername, "xx2-4 servername");
1696 /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1697 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1698 TEST_PRINTERINFO_STRING_EXP_ERR(2, portname, 5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1699 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1700 TEST_PRINTERINFO_STRING_EXP_ERR(5, portname, 5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1702 TEST_PRINTERINFO_STRING(2, sharename, 2, sharename, "xx2-2 sharename");
1703 /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1704 TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername, 2, drivername, "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1705 TEST_PRINTERINFO_STRING(2, location, 2, location, "xx2-2 location");
1706 /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1707 TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile, 2, sepfile, "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1708 /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1709 TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1710 TEST_PRINTERINFO_STRING(2, datatype, 2, datatype, "xx2-2 datatype");
1711 TEST_PRINTERINFO_STRING(2, parameters, 2, parameters, "xx2-2 parameters");
1713 for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1714 /* TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1715 attribute_list[i],
1716 (attribute_list[i] | default_attribute)
1717 ); */
1718 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1719 attribute_list[i],
1720 (attribute_list[i] | default_attribute)
1722 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1723 attribute_list[i],
1724 (attribute_list[i] | default_attribute)
1726 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1727 attribute_list[i],
1728 (attribute_list[i] | default_attribute)
1730 /* TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1731 attribute_list[i],
1732 (attribute_list[i] | default_attribute)
1733 ); */
1734 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1735 attribute_list[i],
1736 (attribute_list[i] | default_attribute)
1738 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1739 attribute_list[i],
1740 (attribute_list[i] | default_attribute)
1742 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1743 attribute_list[i],
1744 (attribute_list[i] | default_attribute)
1746 /* TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1747 attribute_list[i],
1748 (attribute_list[i] | default_attribute)
1749 ); */
1750 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1751 attribute_list[i],
1752 (attribute_list[i] | default_attribute)
1754 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1755 attribute_list[i],
1756 (attribute_list[i] | default_attribute)
1758 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1759 attribute_list[i],
1760 (attribute_list[i] | default_attribute)
1764 for (i=0; i < ARRAY_SIZE(status_list); i++) {
1765 /* level 2 sets do not stick
1766 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1767 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1768 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1769 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1770 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1771 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1774 /* priorities need to be between 0 and 99
1775 passing an invalid priority will result in WERR_INVALID_PRIORITY */
1776 TEST_PRINTERINFO_INT(2, priority, 2, priority, 0);
1777 TEST_PRINTERINFO_INT(2, priority, 2, priority, 1);
1778 TEST_PRINTERINFO_INT(2, priority, 2, priority, 99);
1779 /* TEST_PRINTERINFO_INT(2, priority, 2, priority, 100); */
1780 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1781 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1782 TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1783 /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1785 TEST_PRINTERINFO_INT(2, starttime, 2, starttime, __LINE__);
1786 TEST_PRINTERINFO_INT(2, untiltime, 2, untiltime, __LINE__);
1788 /* does not stick
1789 TEST_PRINTERINFO_INT(2, cjobs, 2, cjobs, __LINE__);
1790 TEST_PRINTERINFO_INT(2, averageppm, 2, averageppm, __LINE__); */
1792 /* does not stick
1793 TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1794 TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1796 /* FIXME: gd also test devmode and secdesc behavior */
1799 /* verify composition of level 1 description field */
1800 const char *description;
1801 const char *tmp;
1803 q0.in.level = 1;
1804 do { TESTGETCALL(GetPrinter, q0) } while (0);
1806 description = talloc_strdup(tctx, q0.out.info->info1.description);
1808 q0.in.level = 2;
1809 do { TESTGETCALL(GetPrinter, q0) } while (0);
1811 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1812 q0.out.info->info2.printername,
1813 q0.out.info->info2.drivername,
1814 q0.out.info->info2.location);
1816 do { STRING_EQUAL(description, tmp, "description")} while (0);
1819 return ret;
1822 static bool test_security_descriptor_equal(struct torture_context *tctx,
1823 const struct security_descriptor *sd1,
1824 const struct security_descriptor *sd2)
1826 if (sd1 == sd2) {
1827 return true;
1830 if (!sd1 || !sd2) {
1831 torture_comment(tctx, "%s\n", __location__);
1832 return false;
1835 torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
1836 torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
1838 torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
1839 torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
1841 if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
1842 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
1843 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
1844 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
1845 return false;
1847 if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
1848 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
1849 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
1850 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
1851 return false;
1854 return true;
1857 static bool test_sd_set_level(struct torture_context *tctx,
1858 struct dcerpc_binding_handle *b,
1859 struct policy_handle *handle,
1860 uint32_t level,
1861 struct security_descriptor *sd)
1863 struct spoolss_SetPrinterInfoCtr info_ctr;
1864 struct spoolss_DevmodeContainer devmode_ctr;
1865 struct sec_desc_buf secdesc_ctr;
1866 union spoolss_SetPrinterInfo sinfo;
1868 ZERO_STRUCT(devmode_ctr);
1869 ZERO_STRUCT(secdesc_ctr);
1871 switch (level) {
1872 case 2: {
1873 union spoolss_PrinterInfo info;
1874 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1875 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
1877 info_ctr.level = 2;
1878 info_ctr.info = sinfo;
1880 break;
1882 case 3: {
1883 struct spoolss_SetPrinterInfo3 info3;
1885 info3.sec_desc_ptr = 0;
1887 info_ctr.level = 3;
1888 info_ctr.info.info3 = &info3;
1890 break;
1892 default:
1893 return false;
1896 secdesc_ctr.sd = sd;
1898 torture_assert(tctx,
1899 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
1901 return true;
1904 static bool test_PrinterInfo_SDs(struct torture_context *tctx,
1905 struct dcerpc_binding_handle *b,
1906 struct policy_handle *handle)
1908 union spoolss_PrinterInfo info;
1909 struct security_descriptor *sd1, *sd2;
1910 int i;
1912 /* just compare level 2 and level 3 */
1914 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1916 sd1 = info.info2.secdesc;
1918 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
1920 sd2 = info.info3.secdesc;
1922 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1923 "SD level 2 != SD level 3");
1926 /* query level 2, set level 2, query level 2 */
1928 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1930 sd1 = info.info2.secdesc;
1932 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
1934 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1936 sd2 = info.info2.secdesc;
1937 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1938 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1939 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1942 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1943 "SD level 2 != SD level 2 after SD has been set via level 2");
1946 /* query level 2, set level 3, query level 2 */
1948 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1950 sd1 = info.info2.secdesc;
1952 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1954 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1956 sd2 = info.info2.secdesc;
1958 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1959 "SD level 2 != SD level 2 after SD has been set via level 3");
1961 /* set modified sd level 3, query level 2 */
1963 for (i=0; i < 93; i++) {
1964 struct security_ace a;
1965 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
1966 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1967 a.flags = 0;
1968 a.size = 0; /* autogenerated */
1969 a.access_mask = 0;
1970 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
1971 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
1974 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
1976 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
1977 sd2 = info.info2.secdesc;
1979 if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
1980 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
1981 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
1984 torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
1985 "modified SD level 2 != SD level 2 after SD has been set via level 3");
1988 return true;
1992 * wrapper call that saves original sd, runs tests, and restores sd
1995 static bool test_PrinterInfo_SD(struct torture_context *tctx,
1996 struct dcerpc_binding_handle *b,
1997 struct policy_handle *handle)
1999 union spoolss_PrinterInfo info;
2000 struct security_descriptor *sd;
2001 bool ret = true;
2003 torture_comment(tctx, "Testing Printer Security Descriptors\n");
2005 /* save original sd */
2007 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
2008 "failed to get initial security descriptor");
2010 sd = security_descriptor_copy(tctx, info.info2.secdesc);
2012 /* run tests */
2014 ret = test_PrinterInfo_SDs(tctx, b, handle);
2016 /* restore original sd */
2018 torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
2019 "failed to restore initial security descriptor");
2021 torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
2022 ret ? "succeeded" : "failed");
2025 return ret;
2028 static bool test_devmode_set_level(struct torture_context *tctx,
2029 struct dcerpc_binding_handle *b,
2030 struct policy_handle *handle,
2031 uint32_t level,
2032 struct spoolss_DeviceMode *devmode)
2034 struct spoolss_SetPrinterInfoCtr info_ctr;
2035 struct spoolss_DevmodeContainer devmode_ctr;
2036 struct sec_desc_buf secdesc_ctr;
2037 union spoolss_SetPrinterInfo sinfo;
2039 ZERO_STRUCT(devmode_ctr);
2040 ZERO_STRUCT(secdesc_ctr);
2042 switch (level) {
2043 case 2: {
2044 union spoolss_PrinterInfo info;
2045 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2046 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
2048 info_ctr.level = 2;
2049 info_ctr.info = sinfo;
2051 break;
2053 case 8: {
2054 struct spoolss_SetPrinterInfo8 info8;
2056 info8.devmode_ptr = 0;
2058 info_ctr.level = 8;
2059 info_ctr.info.info8 = &info8;
2061 break;
2063 default:
2064 return false;
2067 devmode_ctr.devmode = devmode;
2069 torture_assert(tctx,
2070 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
2072 return true;
2076 static bool test_devicemode_equal(struct torture_context *tctx,
2077 const struct spoolss_DeviceMode *d1,
2078 const struct spoolss_DeviceMode *d2)
2080 if (d1 == d2) {
2081 return true;
2084 if (!d1 || !d2) {
2085 torture_comment(tctx, "%s\n", __location__);
2086 return false;
2088 torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
2089 torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
2090 torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
2091 torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
2092 torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
2093 torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
2094 torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
2095 torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
2096 torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
2097 torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
2098 torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
2099 torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
2100 torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
2101 torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
2102 torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
2103 torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
2104 torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
2105 torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
2106 torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
2107 torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
2108 torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
2109 torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
2110 torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
2111 torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
2112 torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
2113 torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
2114 torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
2115 torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
2116 torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
2117 torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
2118 torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
2119 torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
2120 torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
2121 torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
2122 torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
2124 return true;
2127 static bool test_devicemode_full(struct torture_context *tctx,
2128 struct dcerpc_binding_handle *b,
2129 struct policy_handle *handle)
2131 struct spoolss_SetPrinter s;
2132 struct spoolss_GetPrinter q;
2133 struct spoolss_GetPrinter q0;
2134 struct spoolss_SetPrinterInfoCtr info_ctr;
2135 struct spoolss_SetPrinterInfo8 info8;
2136 union spoolss_PrinterInfo info;
2137 struct spoolss_DevmodeContainer devmode_ctr;
2138 struct sec_desc_buf secdesc_ctr;
2139 uint32_t needed;
2140 bool ret = true;
2141 NTSTATUS status;
2143 #define TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, exp_value, expected_result) do { \
2144 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
2145 q.in.level = lvl1; \
2146 TESTGETCALL(GetPrinter, q) \
2147 info_ctr.level = lvl1; \
2148 if (lvl1 == 2) {\
2149 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
2150 } else if (lvl1 == 8) {\
2151 info_ctr.info.info ## lvl1 = &info8; \
2153 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
2154 devmode_ctr.devmode->field1 = value; \
2155 TESTSETCALL_EXP(SetPrinter, s, expected_result) \
2156 if (W_ERROR_IS_OK(expected_result)) { \
2157 TESTGETCALL(GetPrinter, q) \
2158 INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
2159 q.in.level = lvl2; \
2160 TESTGETCALL(GetPrinter, q) \
2161 INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
2163 } while (0)
2165 #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, expected_result) do { \
2166 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, expected_result); \
2167 } while (0)
2169 #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
2170 TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, WERR_OK); \
2171 } while (0)
2173 ZERO_STRUCT(devmode_ctr);
2174 ZERO_STRUCT(secdesc_ctr);
2175 ZERO_STRUCT(info8);
2177 s.in.handle = handle;
2178 s.in.command = 0;
2179 s.in.info_ctr = &info_ctr;
2180 s.in.devmode_ctr = &devmode_ctr;
2181 s.in.secdesc_ctr = &secdesc_ctr;
2183 q.in.handle = handle;
2184 q.out.info = &info;
2185 q0 = q;
2187 #if 0
2188 const char *devicename;/* [charset(UTF16)] */
2189 enum spoolss_DeviceModeSpecVersion specversion;
2190 uint16_t driverversion;
2191 uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
2192 uint32_t fields;
2193 #endif
2194 TEST_DEVMODE_INT_EXP(8, size, 8, size, __LINE__, WERR_INVALID_PARAM);
2195 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0, WERR_INVALID_PARAM);
2196 TEST_DEVMODE_INT_EXP(8, size, 8, size, 0xffff, WERR_INVALID_PARAM);
2197 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);
2198 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2200 devmode_ctr.devmode->driverextra_data = data_blob_string_const("foobar");
2201 torture_assert(tctx,
2202 test_devmode_set_level(tctx, b, handle, 8, devmode_ctr.devmode),
2203 "failed to set devmode");
2205 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);
2206 TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
2208 TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
2209 TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
2210 TEST_DEVMODE_INT(8, paperlength, 8, paperlength, __LINE__);
2211 TEST_DEVMODE_INT(8, paperwidth, 8, paperwidth, __LINE__);
2212 TEST_DEVMODE_INT(8, scale, 8, scale, __LINE__);
2213 TEST_DEVMODE_INT(8, copies, 8, copies, __LINE__);
2214 TEST_DEVMODE_INT(8, defaultsource, 8, defaultsource, __LINE__);
2215 TEST_DEVMODE_INT(8, printquality, 8, printquality, __LINE__);
2216 TEST_DEVMODE_INT(8, color, 8, color, __LINE__);
2217 TEST_DEVMODE_INT(8, duplex, 8, duplex, __LINE__);
2218 TEST_DEVMODE_INT(8, yresolution, 8, yresolution, __LINE__);
2219 TEST_DEVMODE_INT(8, ttoption, 8, ttoption, __LINE__);
2220 TEST_DEVMODE_INT(8, collate, 8, collate, __LINE__);
2221 #if 0
2222 const char *formname;/* [charset(UTF16)] */
2223 #endif
2224 TEST_DEVMODE_INT(8, logpixels, 8, logpixels, __LINE__);
2225 TEST_DEVMODE_INT(8, bitsperpel, 8, bitsperpel, __LINE__);
2226 TEST_DEVMODE_INT(8, pelswidth, 8, pelswidth, __LINE__);
2227 TEST_DEVMODE_INT(8, pelsheight, 8, pelsheight, __LINE__);
2228 TEST_DEVMODE_INT(8, displayflags, 8, displayflags, __LINE__);
2229 TEST_DEVMODE_INT(8, displayfrequency, 8, displayfrequency, __LINE__);
2230 TEST_DEVMODE_INT(8, icmmethod, 8, icmmethod, __LINE__);
2231 TEST_DEVMODE_INT(8, icmintent, 8, icmintent, __LINE__);
2232 TEST_DEVMODE_INT(8, mediatype, 8, mediatype, __LINE__);
2233 TEST_DEVMODE_INT(8, dithertype, 8, dithertype, __LINE__);
2234 TEST_DEVMODE_INT(8, reserved1, 8, reserved1, __LINE__);
2235 TEST_DEVMODE_INT(8, reserved2, 8, reserved2, __LINE__);
2236 TEST_DEVMODE_INT(8, panningwidth, 8, panningwidth, __LINE__);
2237 TEST_DEVMODE_INT(8, panningheight, 8, panningheight, __LINE__);
2239 return ret;
2242 static bool call_OpenPrinterEx(struct torture_context *tctx,
2243 struct dcerpc_pipe *p,
2244 const char *name,
2245 struct spoolss_DeviceMode *devmode,
2246 struct policy_handle *handle);
2248 static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
2249 struct dcerpc_pipe *p,
2250 struct policy_handle *handle,
2251 const char *name)
2253 union spoolss_PrinterInfo info;
2254 struct spoolss_DeviceMode *devmode;
2255 struct spoolss_DeviceMode *devmode2;
2256 struct policy_handle handle_devmode;
2257 struct dcerpc_binding_handle *b = p->binding_handle;
2259 /* simply compare level8 and level2 devmode */
2261 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2263 devmode = info.info8.devmode;
2265 if (devmode && devmode->size == 0) {
2266 torture_fail(tctx,
2267 "devmode of zero size!");
2270 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2272 devmode2 = info.info2.devmode;
2274 if (devmode2 && devmode2->size == 0) {
2275 torture_fail(tctx,
2276 "devmode of zero size!");
2279 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2280 "DM level 8 != DM level 2");
2283 /* set devicemode level 8 and see if it persists */
2285 devmode->copies = 93;
2286 devmode->formname = talloc_strdup(tctx, "Legal");
2288 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
2290 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2292 devmode2 = info.info8.devmode;
2294 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2295 "modified DM level 8 != DM level 8 after DM has been set via level 8");
2297 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2299 devmode2 = info.info2.devmode;
2301 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2302 "modified DM level 8 != DM level 2");
2305 /* set devicemode level 2 and see if it persists */
2307 devmode->copies = 39;
2308 devmode->formname = talloc_strdup(tctx, "Executive");
2310 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
2312 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
2314 devmode2 = info.info8.devmode;
2316 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2317 "modified DM level 8 != DM level 8 after DM has been set via level 2");
2319 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
2321 devmode2 = info.info2.devmode;
2323 torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
2324 "modified DM level 8 != DM level 2");
2327 /* check every single bit in public part of devicemode */
2329 torture_assert(tctx, test_devicemode_full(tctx, b, handle),
2330 "failed to set every single devicemode component");
2333 /* change formname upon open and see if it persists in getprinter calls */
2335 devmode->formname = talloc_strdup(tctx, "A4");
2336 devmode->copies = 42;
2338 torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
2339 "failed to open printer handle");
2341 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
2343 devmode2 = info.info8.devmode;
2345 if (strequal(devmode->devicename, devmode2->devicename)) {
2346 torture_warning(tctx, "devicenames are the same\n");
2347 } else {
2348 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2349 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
2352 if (strequal(devmode->formname, devmode2->formname)) {
2353 torture_warning(tctx, "formname are the same\n");
2354 } else {
2355 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2356 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
2359 if (devmode->copies == devmode2->copies) {
2360 torture_warning(tctx, "copies are the same\n");
2361 } else {
2362 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2363 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
2366 torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
2368 devmode2 = info.info2.devmode;
2370 if (strequal(devmode->devicename, devmode2->devicename)) {
2371 torture_warning(tctx, "devicenames are the same\n");
2372 } else {
2373 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
2374 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
2377 if (strequal(devmode->formname, devmode2->formname)) {
2378 torture_warning(tctx, "formname is the same\n");
2379 } else {
2380 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
2381 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
2384 if (devmode->copies == devmode2->copies) {
2385 torture_warning(tctx, "copies are the same\n");
2386 } else {
2387 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
2388 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
2391 test_ClosePrinter(tctx, b, &handle_devmode);
2393 return true;
2397 * wrapper call that saves original devmode, runs tests, and restores devmode
2400 static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
2401 struct dcerpc_pipe *p,
2402 struct policy_handle *handle,
2403 const char *name,
2404 struct spoolss_DeviceMode *addprinter_devmode)
2406 union spoolss_PrinterInfo info;
2407 struct spoolss_DeviceMode *devmode;
2408 bool ret = true;
2409 struct dcerpc_binding_handle *b = p->binding_handle;
2411 torture_comment(tctx, "Testing Printer Devicemodes\n");
2413 /* save original devmode */
2415 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
2416 "failed to get initial global devicemode");
2418 devmode = info.info8.devmode;
2420 if (devmode && devmode->size == 0) {
2421 torture_fail(tctx,
2422 "devmode of zero size!");
2425 if (addprinter_devmode) {
2426 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
2427 torture_warning(tctx, "current global DM is != DM provided in addprinter");
2431 /* run tests */
2433 ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
2435 /* restore original devmode */
2437 torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
2438 "failed to restore initial global device mode");
2440 torture_comment(tctx, "Printer Devicemodes test %s\n\n",
2441 ret ? "succeeded" : "failed");
2444 return ret;
2447 bool test_ClosePrinter(struct torture_context *tctx,
2448 struct dcerpc_binding_handle *b,
2449 struct policy_handle *handle)
2451 NTSTATUS status;
2452 struct spoolss_ClosePrinter r;
2454 r.in.handle = handle;
2455 r.out.handle = handle;
2457 torture_comment(tctx, "Testing ClosePrinter\n");
2459 status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
2460 torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
2461 torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
2463 return true;
2466 static bool test_GetForm_args(struct torture_context *tctx,
2467 struct dcerpc_binding_handle *b,
2468 struct policy_handle *handle,
2469 const char *form_name,
2470 uint32_t level,
2471 union spoolss_FormInfo *info_p)
2473 NTSTATUS status;
2474 struct spoolss_GetForm r;
2475 uint32_t needed;
2477 r.in.handle = handle;
2478 r.in.form_name = form_name;
2479 r.in.level = level;
2480 r.in.buffer = NULL;
2481 r.in.offered = 0;
2482 r.out.needed = &needed;
2484 torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
2486 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2487 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2489 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2490 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2491 r.in.buffer = &blob;
2492 r.in.offered = needed;
2493 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
2494 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
2496 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2498 torture_assert(tctx, r.out.info, "No form info returned");
2501 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
2503 CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
2505 if (info_p) {
2506 *info_p = *r.out.info;
2509 return true;
2512 static bool test_GetForm(struct torture_context *tctx,
2513 struct dcerpc_binding_handle *b,
2514 struct policy_handle *handle,
2515 const char *form_name,
2516 uint32_t level)
2518 return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
2521 static bool test_EnumForms(struct torture_context *tctx,
2522 struct dcerpc_binding_handle *b,
2523 struct policy_handle *handle,
2524 bool print_server,
2525 uint32_t level,
2526 uint32_t *count_p,
2527 union spoolss_FormInfo **info_p)
2529 struct spoolss_EnumForms r;
2530 uint32_t needed;
2531 uint32_t count;
2532 union spoolss_FormInfo *info;
2534 r.in.handle = handle;
2535 r.in.level = level;
2536 r.in.buffer = NULL;
2537 r.in.offered = 0;
2538 r.out.needed = &needed;
2539 r.out.count = &count;
2540 r.out.info = &info;
2542 torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
2544 torture_assert_ntstatus_ok(tctx,
2545 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2546 "EnumForms failed");
2548 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
2549 torture_skip(tctx, "EnumForms level 2 not supported");
2552 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID)) {
2553 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
2556 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2557 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
2558 r.in.buffer = &blob;
2559 r.in.offered = needed;
2561 torture_assert_ntstatus_ok(tctx,
2562 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
2563 "EnumForms failed");
2565 torture_assert(tctx, info, "No forms returned");
2568 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
2570 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
2572 if (info_p) {
2573 *info_p = info;
2575 if (count_p) {
2576 *count_p = count;
2579 return true;
2582 static bool test_EnumForms_all(struct torture_context *tctx,
2583 struct dcerpc_binding_handle *b,
2584 struct policy_handle *handle,
2585 bool print_server)
2587 uint32_t levels[] = { 1, 2 };
2588 int i, j;
2590 for (i=0; i<ARRAY_SIZE(levels); i++) {
2592 uint32_t count = 0;
2593 union spoolss_FormInfo *info = NULL;
2595 torture_assert(tctx,
2596 test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
2597 "failed to enum forms");
2599 for (j = 0; j < count; j++) {
2600 if (!print_server) {
2601 torture_assert(tctx,
2602 test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
2603 "failed to get form");
2608 return true;
2611 static bool test_EnumForms_find_one(struct torture_context *tctx,
2612 struct dcerpc_binding_handle *b,
2613 struct policy_handle *handle,
2614 bool print_server,
2615 const char *form_name)
2617 union spoolss_FormInfo *info;
2618 uint32_t count;
2619 bool found = false;
2620 int i;
2622 torture_assert(tctx,
2623 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
2624 "failed to enumerate forms");
2626 for (i=0; i<count; i++) {
2627 if (strequal(form_name, info[i].info1.form_name)) {
2628 found = true;
2629 break;
2633 return found;
2636 static bool test_DeleteForm(struct torture_context *tctx,
2637 struct dcerpc_binding_handle *b,
2638 struct policy_handle *handle,
2639 const char *form_name,
2640 WERROR expected_result)
2642 struct spoolss_DeleteForm r;
2644 r.in.handle = handle;
2645 r.in.form_name = form_name;
2647 torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
2649 torture_assert_ntstatus_ok(tctx,
2650 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2651 "DeleteForm failed");
2652 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2653 "DeleteForm gave unexpected result");
2654 if (W_ERROR_IS_OK(r.out.result)) {
2655 torture_assert_ntstatus_ok(tctx,
2656 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
2657 "2nd DeleteForm failed");
2658 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
2659 "2nd DeleteForm failed");
2662 return true;
2665 static bool test_AddForm(struct torture_context *tctx,
2666 struct dcerpc_binding_handle *b,
2667 struct policy_handle *handle,
2668 uint32_t level,
2669 union spoolss_AddFormInfo *info,
2670 WERROR expected_result)
2672 struct spoolss_AddForm r;
2674 if (level != 1) {
2675 torture_skip(tctx, "only level 1 supported");
2678 r.in.handle = handle;
2679 r.in.level = level;
2680 r.in.info = *info;
2682 torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
2683 r.in.info.info1->form_name, r.in.level,
2684 r.in.info.info1->flags);
2686 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2687 "AddForm failed");
2688 torture_assert_werr_equal(tctx, r.out.result, expected_result,
2689 "AddForm gave unexpected result");
2691 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
2692 "2nd AddForm failed");
2693 if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAM)) {
2694 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
2695 "2nd AddForm gave unexpected result");
2696 } else {
2697 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
2698 "2nd AddForm gave unexpected result");
2701 return true;
2704 static bool test_SetForm(struct torture_context *tctx,
2705 struct dcerpc_binding_handle *b,
2706 struct policy_handle *handle,
2707 const char *form_name,
2708 uint32_t level,
2709 union spoolss_AddFormInfo *info)
2711 struct spoolss_SetForm r;
2713 r.in.handle = handle;
2714 r.in.form_name = form_name;
2715 r.in.level = level;
2716 r.in.info = *info;
2718 torture_comment(tctx, "Testing SetForm(%s) level %d\n",
2719 form_name, r.in.level);
2721 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
2722 "SetForm failed");
2724 torture_assert_werr_ok(tctx, r.out.result,
2725 "SetForm failed");
2727 return true;
2730 static bool test_GetForm_winreg(struct torture_context *tctx,
2731 struct dcerpc_binding_handle *b,
2732 struct policy_handle *handle,
2733 const char *key_name,
2734 const char *form_name,
2735 enum winreg_Type *w_type,
2736 uint32_t *w_size,
2737 uint32_t *w_length,
2738 uint8_t **w_data);
2740 static bool test_Forms_args(struct torture_context *tctx,
2741 struct dcerpc_binding_handle *b,
2742 struct policy_handle *handle,
2743 bool print_server,
2744 const char *printer_name,
2745 struct dcerpc_binding_handle *winreg_handle,
2746 struct policy_handle *hive_handle,
2747 const char *form_name,
2748 struct spoolss_AddFormInfo1 *info1,
2749 WERROR expected_add_result,
2750 WERROR expected_delete_result)
2752 union spoolss_FormInfo info;
2753 union spoolss_AddFormInfo add_info;
2755 enum winreg_Type w_type;
2756 uint32_t w_size;
2757 uint32_t w_length;
2758 uint8_t *w_data;
2760 add_info.info1 = info1;
2762 torture_assert(tctx,
2763 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
2764 "failed to add form");
2766 if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
2768 struct spoolss_FormInfo1 i1;
2770 torture_assert(tctx,
2771 test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
2772 "failed to get form via winreg");
2774 i1.size.width = IVAL(w_data, 0);
2775 i1.size.height = IVAL(w_data, 4);
2776 i1.area.left = IVAL(w_data, 8);
2777 i1.area.top = IVAL(w_data, 12);
2778 i1.area.right = IVAL(w_data, 16);
2779 i1.area.bottom = IVAL(w_data, 20);
2780 /* skip index here */
2781 i1.flags = IVAL(w_data, 28);
2783 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
2784 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
2785 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
2786 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
2787 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
2788 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
2789 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
2790 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
2791 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2792 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
2795 if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
2796 torture_assert(tctx,
2797 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2798 "failed to get added form");
2800 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2801 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
2802 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
2803 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
2804 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
2805 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
2806 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
2808 if (winreg_handle && hive_handle) {
2810 struct spoolss_FormInfo1 i1;
2812 i1.size.width = IVAL(w_data, 0);
2813 i1.size.height = IVAL(w_data, 4);
2814 i1.area.left = IVAL(w_data, 8);
2815 i1.area.top = IVAL(w_data, 12);
2816 i1.area.right = IVAL(w_data, 16);
2817 i1.area.bottom = IVAL(w_data, 20);
2818 /* skip index here */
2819 i1.flags = IVAL(w_data, 28);
2821 torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
2822 torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
2823 torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
2824 torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
2825 torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
2826 torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
2827 torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
2830 add_info.info1->size.width = 1234;
2832 torture_assert(tctx,
2833 test_SetForm(tctx, b, handle, form_name, 1, &add_info),
2834 "failed to set form");
2835 torture_assert(tctx,
2836 test_GetForm_args(tctx, b, handle, form_name, 1, &info),
2837 "failed to get setted form");
2839 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
2842 if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAM)) {
2843 torture_assert(tctx,
2844 test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
2845 "Newly added form not found in enum call");
2848 torture_assert(tctx,
2849 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
2850 "failed to delete form");
2852 return true;
2855 static bool test_Forms(struct torture_context *tctx,
2856 struct dcerpc_binding_handle *b,
2857 struct policy_handle *handle,
2858 bool print_server,
2859 const char *printer_name,
2860 struct dcerpc_binding_handle *winreg_handle,
2861 struct policy_handle *hive_handle)
2863 const struct spoolss_FormSize size = {
2864 .width = 50,
2865 .height = 25
2867 const struct spoolss_FormArea area = {
2868 .left = 5,
2869 .top = 10,
2870 .right = 45,
2871 .bottom = 15
2873 int i;
2875 struct {
2876 struct spoolss_AddFormInfo1 info1;
2877 WERROR expected_add_result;
2878 WERROR expected_delete_result;
2879 } forms[] = {
2881 .info1 = {
2882 .flags = SPOOLSS_FORM_USER,
2883 .form_name = "testform_user",
2884 .size = size,
2885 .area = area,
2887 .expected_add_result = WERR_OK,
2888 .expected_delete_result = WERR_OK
2891 weird, we can add a builtin form but we can never remove it
2892 again - gd
2895 .info1 = {
2896 .flags = SPOOLSS_FORM_BUILTIN,
2897 .form_name = "testform_builtin",
2898 .size = size,
2899 .area = area,
2901 .expected_add_result = WERR_OK,
2902 .expected_delete_result = WERR_INVALID_PARAM,
2906 .info1 = {
2907 .flags = SPOOLSS_FORM_PRINTER,
2908 .form_name = "testform_printer",
2909 .size = size,
2910 .area = area,
2912 .expected_add_result = WERR_OK,
2913 .expected_delete_result = WERR_OK
2916 .info1 = {
2917 .flags = SPOOLSS_FORM_USER,
2918 .form_name = "Letter",
2919 .size = size,
2920 .area = area,
2922 .expected_add_result = WERR_FILE_EXISTS,
2923 .expected_delete_result = WERR_INVALID_PARAM
2926 .info1 = {
2927 .flags = SPOOLSS_FORM_BUILTIN,
2928 .form_name = "Letter",
2929 .size = size,
2930 .area = area,
2932 .expected_add_result = WERR_FILE_EXISTS,
2933 .expected_delete_result = WERR_INVALID_PARAM
2936 .info1 = {
2937 .flags = SPOOLSS_FORM_PRINTER,
2938 .form_name = "Letter",
2939 .size = size,
2940 .area = area,
2942 .expected_add_result = WERR_FILE_EXISTS,
2943 .expected_delete_result = WERR_INVALID_PARAM
2946 .info1 = {
2947 .flags = 12345,
2948 .form_name = "invalid_flags",
2949 .size = size,
2950 .area = area,
2952 .expected_add_result = WERR_INVALID_PARAM,
2953 .expected_delete_result = WERR_INVALID_FORM_NAME
2958 for (i=0; i < ARRAY_SIZE(forms); i++) {
2959 torture_assert(tctx,
2960 test_Forms_args(tctx, b, handle, print_server, printer_name,
2961 winreg_handle, hive_handle,
2962 forms[i].info1.form_name,
2963 &forms[i].info1,
2964 forms[i].expected_add_result,
2965 forms[i].expected_delete_result),
2966 talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
2969 return true;
2972 static bool test_EnumPorts_old(struct torture_context *tctx,
2973 void *private_data)
2975 struct test_spoolss_context *ctx =
2976 talloc_get_type_abort(private_data, struct test_spoolss_context);
2978 NTSTATUS status;
2979 struct spoolss_EnumPorts r;
2980 uint32_t needed;
2981 uint32_t count;
2982 union spoolss_PortInfo *info;
2983 struct dcerpc_pipe *p = ctx->spoolss_pipe;
2984 struct dcerpc_binding_handle *b = p->binding_handle;
2986 r.in.servername = talloc_asprintf(tctx, "\\\\%s",
2987 dcerpc_server_name(p));
2988 r.in.level = 2;
2989 r.in.buffer = NULL;
2990 r.in.offered = 0;
2991 r.out.needed = &needed;
2992 r.out.count = &count;
2993 r.out.info = &info;
2995 torture_comment(tctx, "Testing EnumPorts\n");
2997 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
2999 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3001 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3002 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3003 r.in.buffer = &blob;
3004 r.in.offered = needed;
3006 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
3007 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
3008 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3010 torture_assert(tctx, info, "No ports returned");
3013 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
3015 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
3017 return true;
3020 static bool test_AddPort(struct torture_context *tctx,
3021 void *private_data)
3023 struct test_spoolss_context *ctx =
3024 talloc_get_type_abort(private_data, struct test_spoolss_context);
3026 NTSTATUS status;
3027 struct spoolss_AddPort r;
3028 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3029 struct dcerpc_binding_handle *b = p->binding_handle;
3031 r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
3032 dcerpc_server_name(p));
3033 r.in.unknown = 0;
3034 r.in.monitor_name = "foo";
3036 torture_comment(tctx, "Testing AddPort\n");
3038 status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
3040 torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
3042 /* win2k3 returns WERR_NOT_SUPPORTED */
3044 #if 0
3046 if (!W_ERROR_IS_OK(r.out.result)) {
3047 printf("AddPort failed - %s\n", win_errstr(r.out.result));
3048 return false;
3051 #endif
3053 return true;
3056 static bool test_GetJob_args(struct torture_context *tctx,
3057 struct dcerpc_binding_handle *b,
3058 struct policy_handle *handle,
3059 uint32_t job_id,
3060 uint32_t level,
3061 union spoolss_JobInfo *info_p)
3063 NTSTATUS status;
3064 struct spoolss_GetJob r;
3065 union spoolss_JobInfo info;
3066 uint32_t needed;
3068 r.in.handle = handle;
3069 r.in.job_id = job_id;
3070 r.in.level = level;
3071 r.in.buffer = NULL;
3072 r.in.offered = 0;
3073 r.out.needed = &needed;
3074 r.out.info = &info;
3076 torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
3078 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3079 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3080 if (level == 0) {
3081 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
3084 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3085 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3086 r.in.buffer = &blob;
3087 r.in.offered = needed;
3089 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
3090 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
3093 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
3094 torture_assert(tctx, r.out.info, "No job info returned");
3096 CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
3098 if (info_p) {
3099 *info_p = *r.out.info;
3102 return true;
3105 static bool test_GetJob(struct torture_context *tctx,
3106 struct dcerpc_binding_handle *b,
3107 struct policy_handle *handle,
3108 uint32_t job_id)
3110 uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
3111 uint32_t i;
3113 for (i=0; i < ARRAY_SIZE(levels); i++) {
3114 torture_assert(tctx,
3115 test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
3116 "GetJob failed");
3119 return true;
3122 static bool test_SetJob(struct torture_context *tctx,
3123 struct dcerpc_binding_handle *b,
3124 struct policy_handle *handle,
3125 uint32_t job_id,
3126 struct spoolss_JobInfoContainer *ctr,
3127 enum spoolss_JobControl command)
3129 NTSTATUS status;
3130 struct spoolss_SetJob r;
3132 r.in.handle = handle;
3133 r.in.job_id = job_id;
3134 r.in.ctr = ctr;
3135 r.in.command = command;
3137 switch (command) {
3138 case SPOOLSS_JOB_CONTROL_PAUSE:
3139 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
3140 break;
3141 case SPOOLSS_JOB_CONTROL_RESUME:
3142 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
3143 break;
3144 case SPOOLSS_JOB_CONTROL_CANCEL:
3145 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
3146 break;
3147 case SPOOLSS_JOB_CONTROL_RESTART:
3148 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
3149 break;
3150 case SPOOLSS_JOB_CONTROL_DELETE:
3151 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
3152 break;
3153 case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
3154 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
3155 break;
3156 case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
3157 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
3158 break;
3159 case SPOOLSS_JOB_CONTROL_RETAIN:
3160 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
3161 break;
3162 case SPOOLSS_JOB_CONTROL_RELEASE:
3163 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
3164 break;
3165 default:
3166 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
3167 break;
3170 status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
3171 torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
3172 torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
3174 return true;
3177 static bool test_AddJob(struct torture_context *tctx,
3178 struct dcerpc_binding_handle *b,
3179 struct policy_handle *handle)
3181 NTSTATUS status;
3182 struct spoolss_AddJob r;
3183 uint32_t needed;
3185 r.in.level = 0;
3186 r.in.handle = handle;
3187 r.in.offered = 0;
3188 r.out.needed = &needed;
3189 r.in.buffer = r.out.buffer = NULL;
3191 torture_comment(tctx, "Testing AddJob\n");
3193 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3194 torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
3196 r.in.level = 1;
3198 status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
3199 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
3201 return true;
3205 static bool test_EnumJobs_args(struct torture_context *tctx,
3206 struct dcerpc_binding_handle *b,
3207 struct policy_handle *handle,
3208 uint32_t level,
3209 uint32_t *count_p,
3210 union spoolss_JobInfo **info_p)
3212 NTSTATUS status;
3213 struct spoolss_EnumJobs r;
3214 uint32_t needed;
3215 uint32_t count;
3216 union spoolss_JobInfo *info;
3218 r.in.handle = handle;
3219 r.in.firstjob = 0;
3220 r.in.numjobs = 0xffffffff;
3221 r.in.level = level;
3222 r.in.buffer = NULL;
3223 r.in.offered = 0;
3224 r.out.needed = &needed;
3225 r.out.count = &count;
3226 r.out.info = &info;
3228 torture_comment(tctx, "Testing EnumJobs level %d\n", level);
3230 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3232 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3234 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
3235 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
3236 r.in.buffer = &blob;
3237 r.in.offered = needed;
3239 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
3241 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
3242 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3243 torture_assert(tctx, info, "No jobs returned");
3245 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
3247 } else {
3248 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
3251 if (count_p) {
3252 *count_p = count;
3254 if (info_p) {
3255 *info_p = info;
3258 return true;
3261 static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
3262 struct dcerpc_binding_handle *b,
3263 struct policy_handle *handle,
3264 const char *document_name,
3265 uint32_t *job_id)
3267 NTSTATUS status;
3268 struct spoolss_StartDocPrinter s;
3269 struct spoolss_DocumentInfo1 info1;
3270 struct spoolss_StartPagePrinter sp;
3271 struct spoolss_WritePrinter w;
3272 struct spoolss_EndPagePrinter ep;
3273 struct spoolss_EndDocPrinter e;
3274 int i;
3275 uint32_t num_written;
3277 torture_comment(tctx, "Testing StartDocPrinter\n");
3279 s.in.handle = handle;
3280 s.in.level = 1;
3281 s.in.info.info1 = &info1;
3282 s.out.job_id = job_id;
3283 info1.document_name = document_name;
3284 info1.output_file = NULL;
3285 info1.datatype = "RAW";
3287 status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
3288 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
3289 torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
3291 for (i=1; i < 4; i++) {
3292 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3294 sp.in.handle = handle;
3296 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
3297 torture_assert_ntstatus_ok(tctx, status,
3298 "dcerpc_spoolss_StartPagePrinter failed");
3299 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
3301 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3303 w.in.handle = handle;
3304 w.in.data = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
3305 w.out.num_written = &num_written;
3307 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
3308 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
3309 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
3311 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
3313 ep.in.handle = handle;
3315 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
3316 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
3317 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
3320 torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
3322 e.in.handle = handle;
3324 status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
3325 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
3326 torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
3328 return true;
3331 static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
3332 struct dcerpc_binding_handle *b,
3333 struct policy_handle *handle,
3334 uint32_t num_jobs,
3335 uint32_t *job_ids)
3337 uint32_t count;
3338 union spoolss_JobInfo *info = NULL;
3339 int i;
3341 torture_assert(tctx,
3342 test_AddJob(tctx, b, handle),
3343 "AddJob failed");
3345 torture_assert(tctx,
3346 test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
3347 "EnumJobs level 1 failed");
3349 torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
3351 for (i=0; i < num_jobs; i++) {
3352 union spoolss_JobInfo ginfo;
3353 const char *document_name;
3354 const char *new_document_name = "any_other_docname";
3355 struct spoolss_JobInfoContainer ctr;
3356 struct spoolss_SetJobInfo1 info1;
3358 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
3360 torture_assert(tctx,
3361 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3362 "failed to call test_GetJob");
3364 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
3366 document_name = ginfo.info1.document_name;
3368 info1.job_id = ginfo.info1.job_id;
3369 info1.printer_name = ginfo.info1.printer_name;
3370 info1.server_name = ginfo.info1.server_name;
3371 info1.user_name = ginfo.info1.user_name;
3372 info1.document_name = new_document_name;
3373 info1.data_type = ginfo.info1.data_type;
3374 info1.text_status = ginfo.info1.text_status;
3375 info1.status = ginfo.info1.status;
3376 info1.priority = ginfo.info1.priority;
3377 info1.position = ginfo.info1.position;
3378 info1.total_pages = ginfo.info1.total_pages;
3379 info1.pages_printed = ginfo.info1.pages_printed;
3380 info1.submitted = ginfo.info1.submitted;
3382 ctr.level = 1;
3383 ctr.info.info1 = &info1;
3385 torture_assert(tctx,
3386 test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
3387 "failed to call test_SetJob level 1");
3389 torture_assert(tctx,
3390 test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
3391 "failed to call test_GetJob");
3393 if (strequal(ginfo.info1.document_name, document_name)) {
3394 torture_warning(tctx,
3395 "document_name did *NOT* change from '%s' to '%s'\n",
3396 document_name, new_document_name);
3400 for (i=0; i < num_jobs; i++) {
3401 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
3402 torture_warning(tctx, "failed to pause printjob\n");
3404 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
3405 torture_warning(tctx, "failed to resume printjob\n");
3409 return true;
3412 static bool test_DoPrintTest(struct torture_context *tctx,
3413 struct dcerpc_binding_handle *b,
3414 struct policy_handle *handle)
3416 bool ret = true;
3417 uint32_t num_jobs = 8;
3418 uint32_t *job_ids;
3419 int i;
3421 torture_comment(tctx, "Testing real print operations\n");
3423 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3425 for (i=0; i < num_jobs; i++) {
3426 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3429 for (i=0; i < num_jobs; i++) {
3430 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3433 if (ret == true) {
3434 torture_comment(tctx, "real print operations test succeeded\n\n");
3437 return ret;
3440 static bool test_DoPrintTest_extended(struct torture_context *tctx,
3441 struct dcerpc_binding_handle *b,
3442 struct policy_handle *handle)
3444 bool ret = true;
3445 uint32_t num_jobs = 8;
3446 uint32_t *job_ids;
3447 int i;
3448 torture_comment(tctx, "Testing real print operations (extended)\n");
3450 job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
3452 for (i=0; i < num_jobs; i++) {
3453 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
3456 ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
3458 for (i=0; i < num_jobs; i++) {
3459 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
3462 if (ret == true) {
3463 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
3466 return ret;
3469 static bool test_PausePrinter(struct torture_context *tctx,
3470 struct dcerpc_binding_handle *b,
3471 struct policy_handle *handle)
3473 NTSTATUS status;
3474 struct spoolss_SetPrinter r;
3475 struct spoolss_SetPrinterInfoCtr info_ctr;
3476 struct spoolss_DevmodeContainer devmode_ctr;
3477 struct sec_desc_buf secdesc_ctr;
3479 info_ctr.level = 0;
3480 info_ctr.info.info0 = NULL;
3482 ZERO_STRUCT(devmode_ctr);
3483 ZERO_STRUCT(secdesc_ctr);
3485 r.in.handle = handle;
3486 r.in.info_ctr = &info_ctr;
3487 r.in.devmode_ctr = &devmode_ctr;
3488 r.in.secdesc_ctr = &secdesc_ctr;
3489 r.in.command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3491 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
3493 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3495 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3497 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3499 return true;
3502 static bool test_ResumePrinter(struct torture_context *tctx,
3503 struct dcerpc_binding_handle *b,
3504 struct policy_handle *handle)
3506 NTSTATUS status;
3507 struct spoolss_SetPrinter r;
3508 struct spoolss_SetPrinterInfoCtr info_ctr;
3509 struct spoolss_DevmodeContainer devmode_ctr;
3510 struct sec_desc_buf secdesc_ctr;
3512 info_ctr.level = 0;
3513 info_ctr.info.info0 = NULL;
3515 ZERO_STRUCT(devmode_ctr);
3516 ZERO_STRUCT(secdesc_ctr);
3518 r.in.handle = handle;
3519 r.in.info_ctr = &info_ctr;
3520 r.in.devmode_ctr = &devmode_ctr;
3521 r.in.secdesc_ctr = &secdesc_ctr;
3522 r.in.command = SPOOLSS_PRINTER_CONTROL_RESUME;
3524 torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
3526 status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
3528 torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
3530 torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
3532 return true;
3535 static bool test_GetPrinterData_checktype(struct torture_context *tctx,
3536 struct dcerpc_binding_handle *b,
3537 struct policy_handle *handle,
3538 const char *value_name,
3539 enum winreg_Type *expected_type,
3540 enum winreg_Type *type_p,
3541 uint8_t **data_p,
3542 uint32_t *needed_p)
3544 NTSTATUS status;
3545 struct spoolss_GetPrinterData r;
3546 uint32_t needed;
3547 enum winreg_Type type;
3548 union spoolss_PrinterData data;
3550 r.in.handle = handle;
3551 r.in.value_name = value_name;
3552 r.in.offered = 0;
3553 r.out.needed = &needed;
3554 r.out.type = &type;
3555 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3557 torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
3559 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3560 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3562 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3563 if (expected_type) {
3564 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3566 r.in.offered = needed;
3567 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3568 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
3569 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
3572 torture_assert_werr_ok(tctx, r.out.result,
3573 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
3575 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3577 if (type_p) {
3578 *type_p = type;
3581 if (data_p) {
3582 *data_p = r.out.data;
3585 if (needed_p) {
3586 *needed_p = needed;
3589 return true;
3592 static bool test_GetPrinterData(struct torture_context *tctx,
3593 struct dcerpc_binding_handle *b,
3594 struct policy_handle *handle,
3595 const char *value_name,
3596 enum winreg_Type *type_p,
3597 uint8_t **data_p,
3598 uint32_t *needed_p)
3600 return test_GetPrinterData_checktype(tctx, b, handle, value_name,
3601 NULL, type_p, data_p, needed_p);
3604 static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
3605 struct dcerpc_pipe *p,
3606 struct policy_handle *handle,
3607 const char *key_name,
3608 const char *value_name,
3609 enum winreg_Type *expected_type,
3610 enum winreg_Type *type_p,
3611 uint8_t **data_p,
3612 uint32_t *needed_p)
3614 NTSTATUS status;
3615 struct spoolss_GetPrinterDataEx r;
3616 enum winreg_Type type;
3617 uint32_t needed;
3618 union spoolss_PrinterData data;
3619 struct dcerpc_binding_handle *b = p->binding_handle;
3621 r.in.handle = handle;
3622 r.in.key_name = key_name;
3623 r.in.value_name = value_name;
3624 r.in.offered = 0;
3625 r.out.type = &type;
3626 r.out.needed = &needed;
3627 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3629 torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
3630 r.in.key_name, r.in.value_name);
3632 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3633 if (!NT_STATUS_IS_OK(status)) {
3634 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
3635 torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
3637 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3640 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3641 if (expected_type) {
3642 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
3644 r.in.offered = needed;
3645 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
3646 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
3647 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
3650 torture_assert_werr_ok(tctx, r.out.result,
3651 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
3653 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
3655 if (type_p) {
3656 *type_p = type;
3659 if (data_p) {
3660 *data_p = r.out.data;
3663 if (needed_p) {
3664 *needed_p = needed;
3667 return true;
3670 static bool test_GetPrinterDataEx(struct torture_context *tctx,
3671 struct dcerpc_pipe *p,
3672 struct policy_handle *handle,
3673 const char *key_name,
3674 const char *value_name,
3675 enum winreg_Type *type_p,
3676 uint8_t **data_p,
3677 uint32_t *needed_p)
3679 return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
3680 NULL, type_p, data_p, needed_p);
3683 static bool test_get_environment(struct torture_context *tctx,
3684 struct dcerpc_binding_handle *b,
3685 struct policy_handle *handle,
3686 const char **architecture)
3688 DATA_BLOB blob;
3689 enum winreg_Type type;
3690 uint8_t *data;
3691 uint32_t needed;
3693 torture_assert(tctx,
3694 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
3695 "failed to get Architecture");
3697 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
3699 blob = data_blob_const(data, needed);
3700 *architecture = reg_val_data_string(tctx, REG_SZ, blob);
3702 return true;
3705 static bool test_GetPrinterData_list(struct torture_context *tctx,
3706 void *private_data)
3708 struct test_spoolss_context *ctx =
3709 talloc_get_type_abort(private_data, struct test_spoolss_context);
3710 struct dcerpc_pipe *p = ctx->spoolss_pipe;
3711 struct dcerpc_binding_handle *b = p->binding_handle;
3712 const char *list[] = {
3713 "W3SvcInstalled",
3714 "BeepEnabled",
3715 "EventLog",
3716 /* "NetPopup", not on w2k8 */
3717 /* "NetPopupToComputer", not on w2k8 */
3718 "MajorVersion",
3719 "MinorVersion",
3720 "DefaultSpoolDirectory",
3721 "Architecture",
3722 "DsPresent",
3723 "OSVersion",
3724 /* "OSVersionEx", not on s3 */
3725 "DNSMachineName"
3727 int i;
3729 for (i=0; i < ARRAY_SIZE(list); i++) {
3730 enum winreg_Type type, type_ex;
3731 uint8_t *data, *data_ex;
3732 uint32_t needed, needed_ex;
3734 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
3735 talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
3736 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex, &data_ex, &needed_ex),
3737 talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
3738 torture_assert_int_equal(tctx, type, type_ex, "type mismatch");
3739 torture_assert_int_equal(tctx, needed, needed_ex, "needed mismatch");
3740 torture_assert_mem_equal(tctx, data, data_ex, needed, "data mismatch");
3743 return true;
3746 static bool test_EnumPrinterData(struct torture_context *tctx,
3747 struct dcerpc_pipe *p,
3748 struct policy_handle *handle,
3749 uint32_t enum_index,
3750 uint32_t value_offered,
3751 uint32_t data_offered,
3752 enum winreg_Type *type_p,
3753 uint32_t *value_needed_p,
3754 uint32_t *data_needed_p,
3755 const char **value_name_p,
3756 uint8_t **data_p,
3757 WERROR *result_p)
3759 struct spoolss_EnumPrinterData r;
3760 uint32_t data_needed;
3761 uint32_t value_needed;
3762 enum winreg_Type type;
3763 struct dcerpc_binding_handle *b = p->binding_handle;
3765 r.in.handle = handle;
3766 r.in.enum_index = enum_index;
3767 r.in.value_offered = value_offered;
3768 r.in.data_offered = data_offered;
3769 r.out.data_needed = &data_needed;
3770 r.out.value_needed = &value_needed;
3771 r.out.type = &type;
3772 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
3773 r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
3775 torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
3777 torture_assert_ntstatus_ok(tctx,
3778 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
3779 "EnumPrinterData failed");
3781 if (type_p) {
3782 *type_p = type;
3784 if (value_needed_p) {
3785 *value_needed_p = value_needed;
3787 if (data_needed_p) {
3788 *data_needed_p = data_needed;
3790 if (value_name_p) {
3791 *value_name_p = r.out.value_name;
3793 if (data_p) {
3794 *data_p = r.out.data;
3796 if (result_p) {
3797 *result_p = r.out.result;
3800 return true;
3804 static bool test_EnumPrinterData_all(struct torture_context *tctx,
3805 struct dcerpc_pipe *p,
3806 struct policy_handle *handle)
3808 uint32_t enum_index = 0;
3809 enum winreg_Type type;
3810 uint32_t value_needed;
3811 uint32_t data_needed;
3812 uint8_t *data;
3813 const char *value_name;
3814 WERROR result;
3816 torture_comment(tctx, "Testing EnumPrinterData\n");
3818 do {
3819 torture_assert(tctx,
3820 test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
3821 &type, &value_needed, &data_needed,
3822 &value_name, &data, &result),
3823 "EnumPrinterData failed");
3825 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3826 break;
3829 torture_assert(tctx,
3830 test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
3831 &type, &value_needed, &data_needed,
3832 &value_name, &data, &result),
3833 "EnumPrinterData failed");
3835 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
3836 break;
3839 enum_index++;
3841 } while (W_ERROR_IS_OK(result));
3843 torture_comment(tctx, "EnumPrinterData test succeeded\n");
3845 return true;
3848 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
3849 struct dcerpc_binding_handle *b,
3850 struct policy_handle *handle,
3851 const char *key_name,
3852 uint32_t *count_p,
3853 struct spoolss_PrinterEnumValues **info_p)
3855 struct spoolss_EnumPrinterDataEx r;
3856 struct spoolss_PrinterEnumValues *info;
3857 uint32_t needed;
3858 uint32_t count;
3860 r.in.handle = handle;
3861 r.in.key_name = key_name;
3862 r.in.offered = 0;
3863 r.out.needed = &needed;
3864 r.out.count = &count;
3865 r.out.info = &info;
3867 torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
3869 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3870 "EnumPrinterDataEx failed");
3871 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3872 r.in.offered = needed;
3873 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
3874 "EnumPrinterDataEx failed");
3877 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
3879 CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
3881 if (count_p) {
3882 *count_p = count;
3884 if (info_p) {
3885 *info_p = info;
3888 return true;
3891 static bool test_SetPrinterData(struct torture_context *tctx,
3892 struct dcerpc_binding_handle *b,
3893 struct policy_handle *handle,
3894 const char *value_name,
3895 enum winreg_Type type,
3896 uint8_t *data,
3897 uint32_t offered);
3898 static bool test_DeletePrinterData(struct torture_context *tctx,
3899 struct dcerpc_binding_handle *b,
3900 struct policy_handle *handle,
3901 const char *value_name);
3903 static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
3904 struct dcerpc_pipe *p,
3905 struct policy_handle *handle)
3907 uint32_t count;
3908 struct spoolss_PrinterEnumValues *info;
3909 int i;
3910 uint32_t value_needed, data_needed;
3911 uint32_t value_offered, data_offered;
3912 WERROR result;
3913 struct dcerpc_binding_handle *b = p->binding_handle;
3915 enum winreg_Type type;
3916 DATA_BLOB blob;
3918 torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
3920 torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
3921 type = REG_SZ;
3923 torture_assert(tctx,
3924 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
3925 "SetPrinterData failed");
3927 blob = data_blob_string_const("torture_data2");
3929 torture_assert(tctx,
3930 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
3931 "SetPrinterData failed");
3933 blob = data_blob_talloc(tctx, NULL, 4);
3934 SIVAL(blob.data, 0, 0x11223344);
3936 torture_assert(tctx,
3937 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
3938 "SetPrinterData failed");
3940 torture_assert(tctx,
3941 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
3942 "failed to call EnumPrinterDataEx");
3944 /* get the max sizes for value and data */
3946 torture_assert(tctx,
3947 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
3948 NULL, &value_needed, &data_needed,
3949 NULL, NULL, &result),
3950 "EnumPrinterData failed");
3951 torture_assert_werr_ok(tctx, result, "unexpected result");
3953 /* check if the reply from the EnumPrinterData really matches max values */
3955 for (i=0; i < count; i++) {
3956 if (info[i].value_name_len > value_needed) {
3957 torture_fail(tctx,
3958 talloc_asprintf(tctx,
3959 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
3960 info[i].value_name_len, value_needed));
3962 if (info[i].data_length > data_needed) {
3963 torture_fail(tctx,
3964 talloc_asprintf(tctx,
3965 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
3966 info[i].data_length, data_needed));
3970 /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
3971 * sort or not sort the replies by value name, we should be able to do
3972 * the following entry comparison */
3974 data_offered = data_needed;
3975 value_offered = value_needed;
3977 for (i=0; i < count; i++) {
3979 const char *value_name;
3980 uint8_t *data;
3982 torture_assert(tctx,
3983 test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
3984 &type, &value_needed, &data_needed,
3985 &value_name, &data, &result),
3986 "EnumPrinterData failed");
3988 if (i -1 == count) {
3989 torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
3990 "unexpected result");
3991 break;
3992 } else {
3993 torture_assert_werr_ok(tctx, result, "unexpected result");
3996 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
3997 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
3998 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
3999 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
4000 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
4003 torture_assert(tctx,
4004 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
4005 "DeletePrinterData failed");
4006 torture_assert(tctx,
4007 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
4008 "DeletePrinterData failed");
4009 torture_assert(tctx,
4010 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
4011 "DeletePrinterData failed");
4013 torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
4015 return true;
4018 static bool test_DeletePrinterData(struct torture_context *tctx,
4019 struct dcerpc_binding_handle *b,
4020 struct policy_handle *handle,
4021 const char *value_name)
4023 NTSTATUS status;
4024 struct spoolss_DeletePrinterData r;
4026 r.in.handle = handle;
4027 r.in.value_name = value_name;
4029 torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
4030 r.in.value_name);
4032 status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
4034 torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
4035 torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
4037 return true;
4040 static bool test_DeletePrinterDataEx(struct torture_context *tctx,
4041 struct dcerpc_binding_handle *b,
4042 struct policy_handle *handle,
4043 const char *key_name,
4044 const char *value_name)
4046 struct spoolss_DeletePrinterDataEx r;
4048 r.in.handle = handle;
4049 r.in.key_name = key_name;
4050 r.in.value_name = value_name;
4052 torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
4053 r.in.key_name, r.in.value_name);
4055 torture_assert_ntstatus_ok(tctx,
4056 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
4057 "DeletePrinterDataEx failed");
4058 torture_assert_werr_ok(tctx, r.out.result,
4059 "DeletePrinterDataEx failed");
4061 return true;
4064 static bool test_DeletePrinterKey(struct torture_context *tctx,
4065 struct dcerpc_binding_handle *b,
4066 struct policy_handle *handle,
4067 const char *key_name)
4069 struct spoolss_DeletePrinterKey r;
4071 r.in.handle = handle;
4072 r.in.key_name = key_name;
4074 torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
4076 if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
4077 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
4078 return true;
4081 torture_assert_ntstatus_ok(tctx,
4082 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
4083 "DeletePrinterKey failed");
4084 torture_assert_werr_ok(tctx, r.out.result,
4085 "DeletePrinterKey failed");
4087 return true;
4090 static bool test_winreg_OpenHKLM(struct torture_context *tctx,
4091 struct dcerpc_binding_handle *b,
4092 struct policy_handle *handle)
4094 struct winreg_OpenHKLM r;
4096 r.in.system_name = NULL;
4097 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4098 r.out.handle = handle;
4100 torture_comment(tctx, "Testing winreg_OpenHKLM\n");
4102 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
4103 torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
4105 return true;
4108 static void init_winreg_String(struct winreg_String *name, const char *s)
4110 name->name = s;
4111 if (s) {
4112 name->name_len = 2 * (strlen_m(s) + 1);
4113 name->name_size = name->name_len;
4114 } else {
4115 name->name_len = 0;
4116 name->name_size = 0;
4120 static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
4121 struct dcerpc_binding_handle *b,
4122 struct policy_handle *hive_handle,
4123 const char *keyname,
4124 uint32_t options,
4125 struct policy_handle *key_handle)
4127 struct winreg_OpenKey r;
4129 r.in.parent_handle = hive_handle;
4130 init_winreg_String(&r.in.keyname, keyname);
4131 r.in.options = options;
4132 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4133 r.out.handle = key_handle;
4135 torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
4137 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
4138 torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
4140 return true;
4143 static bool test_winreg_OpenKey(struct torture_context *tctx,
4144 struct dcerpc_binding_handle *b,
4145 struct policy_handle *hive_handle,
4146 const char *keyname,
4147 struct policy_handle *key_handle)
4149 return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
4150 REG_OPTION_NON_VOLATILE, key_handle);
4153 static bool test_winreg_CloseKey(struct torture_context *tctx,
4154 struct dcerpc_binding_handle *b,
4155 struct policy_handle *handle)
4157 struct winreg_CloseKey r;
4159 r.in.handle = handle;
4160 r.out.handle = handle;
4162 torture_comment(tctx, "Testing winreg_CloseKey\n");
4164 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
4165 torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
4167 return true;
4170 bool test_winreg_QueryValue(struct torture_context *tctx,
4171 struct dcerpc_binding_handle *b,
4172 struct policy_handle *handle,
4173 const char *value_name,
4174 enum winreg_Type *type_p,
4175 uint32_t *data_size_p,
4176 uint32_t *data_length_p,
4177 uint8_t **data_p)
4179 struct winreg_QueryValue r;
4180 enum winreg_Type type = REG_NONE;
4181 uint32_t data_size = 0;
4182 uint32_t data_length = 0;
4183 struct winreg_String valuename;
4184 uint8_t *data = NULL;
4186 init_winreg_String(&valuename, value_name);
4188 data = talloc_zero_array(tctx, uint8_t, 0);
4190 r.in.handle = handle;
4191 r.in.value_name = &valuename;
4192 r.in.type = &type;
4193 r.in.data_size = &data_size;
4194 r.in.data_length = &data_length;
4195 r.in.data = data;
4196 r.out.type = &type;
4197 r.out.data = data;
4198 r.out.data_size = &data_size;
4199 r.out.data_length = &data_length;
4201 torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
4203 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4204 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
4205 *r.in.data_size = *r.out.data_size;
4206 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
4207 r.in.data = data;
4208 r.out.data = data;
4209 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
4211 torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
4213 if (type_p) {
4214 *type_p = *r.out.type;
4216 if (data_size_p) {
4217 *data_size_p = *r.out.data_size;
4219 if (data_length_p) {
4220 *data_length_p = *r.out.data_length;
4222 if (data_p) {
4223 *data_p = r.out.data;
4226 return true;
4229 static bool test_winreg_query_printerdata(struct torture_context *tctx,
4230 struct dcerpc_binding_handle *b,
4231 struct policy_handle *handle,
4232 const char *printer_name,
4233 const char *key_name,
4234 const char *value_name,
4235 enum winreg_Type *w_type,
4236 uint32_t *w_size,
4237 uint32_t *w_length,
4238 uint8_t **w_data)
4240 const char *printer_key;
4241 struct policy_handle key_handle;
4243 printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
4244 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
4246 torture_assert(tctx,
4247 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
4249 torture_assert(tctx,
4250 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
4252 torture_assert(tctx,
4253 test_winreg_CloseKey(tctx, b, &key_handle), "");
4255 return true;
4258 static bool test_GetForm_winreg(struct torture_context *tctx,
4259 struct dcerpc_binding_handle *b,
4260 struct policy_handle *handle,
4261 const char *key_name,
4262 const char *form_name,
4263 enum winreg_Type *w_type,
4264 uint32_t *w_size,
4265 uint32_t *w_length,
4266 uint8_t **w_data)
4268 struct policy_handle key_handle;
4270 torture_assert(tctx,
4271 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
4273 torture_assert(tctx,
4274 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
4276 torture_assert(tctx,
4277 test_winreg_CloseKey(tctx, b, &key_handle), "");
4279 return true;
4282 static bool test_winreg_symbolic_link(struct torture_context *tctx,
4283 struct dcerpc_binding_handle *b,
4284 struct policy_handle *handle,
4285 const char *symlink_keyname,
4286 const char *symlink_destination)
4288 /* check if the first key is a symlink to the second key */
4290 enum winreg_Type w_type;
4291 uint32_t w_size;
4292 uint32_t w_length;
4293 uint8_t *w_data;
4294 struct policy_handle key_handle;
4295 DATA_BLOB blob;
4296 const char *str;
4298 if (torture_setting_bool(tctx, "samba3", false)) {
4299 torture_skip(tctx, "skip winreg symlink test against samba");
4302 torture_assert(tctx,
4303 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
4304 "failed to open key link");
4306 torture_assert(tctx,
4307 test_winreg_QueryValue(tctx, b, &key_handle,
4308 "SymbolicLinkValue",
4309 &w_type, &w_size, &w_length, &w_data),
4310 "failed to query for 'SymbolicLinkValue' attribute");
4312 torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
4314 blob = data_blob(w_data, w_size);
4315 str = reg_val_data_string(tctx, REG_SZ, blob);
4317 torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
4319 torture_assert(tctx,
4320 test_winreg_CloseKey(tctx, b, &key_handle),
4321 "failed to close key link");
4323 return true;
4326 static const char *strip_unc(const char *unc)
4328 char *name;
4330 if (!unc) {
4331 return NULL;
4334 if (unc[0] == '\\' && unc[1] == '\\') {
4335 unc +=2;
4338 name = strchr(unc, '\\');
4339 if (name) {
4340 return name+1;
4343 return unc;
4346 static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
4347 struct dcerpc_binding_handle *b,
4348 struct policy_handle *handle,
4349 const char *printer_name,
4350 struct dcerpc_binding_handle *winreg_handle,
4351 struct policy_handle *hive_handle)
4353 union spoolss_PrinterInfo info;
4354 const char *keys[] = {
4355 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4356 TOP_LEVEL_PRINT_PRINTERS_KEY
4358 int i;
4359 const char *printername, *sharename;
4361 torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
4363 torture_assert(tctx,
4364 test_GetPrinter_level(tctx, b, handle, 2, &info),
4365 "failed to get printer info level 2");
4367 printername = strip_unc(info.info2.printername);
4368 sharename = strip_unc(info.info2.sharename);
4370 #define test_sz(wname, iname) \
4371 do {\
4372 DATA_BLOB blob;\
4373 const char *str;\
4374 enum winreg_Type w_type;\
4375 uint32_t w_size;\
4376 uint32_t w_length;\
4377 uint8_t *w_data;\
4378 torture_assert(tctx,\
4379 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4380 &w_type, &w_size, &w_length, &w_data),\
4381 "failed to query winreg");\
4382 torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
4383 blob = data_blob(w_data, w_size);\
4384 str = reg_val_data_string(tctx, REG_SZ, blob);\
4385 if (w_size == 2 && iname == NULL) {\
4386 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
4387 } else {\
4388 torture_assert_str_equal(tctx, str, iname,\
4389 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4391 } while(0);
4393 #define test_dword(wname, iname) \
4394 do {\
4395 uint32_t value;\
4396 enum winreg_Type w_type;\
4397 uint32_t w_size;\
4398 uint32_t w_length;\
4399 uint8_t *w_data;\
4400 torture_assert(tctx,\
4401 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4402 &w_type, &w_size, &w_length, &w_data),\
4403 "failed to query winreg");\
4404 torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
4405 torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
4406 torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
4407 value = IVAL(w_data, 0);\
4408 torture_assert_int_equal(tctx, value, iname,\
4409 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
4410 } while(0);
4412 #define test_binary(wname, iname) \
4413 do {\
4414 enum winreg_Type w_type;\
4415 uint32_t w_size;\
4416 uint32_t w_length;\
4417 uint8_t *w_data;\
4418 torture_assert(tctx,\
4419 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4420 &w_type, &w_size, &w_length, &w_data),\
4421 "failed to query winreg");\
4422 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4423 torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
4424 torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
4425 "binary unequal");\
4426 } while(0);
4429 #define test_dm(wname, iname) \
4430 do {\
4431 DATA_BLOB blob;\
4432 struct spoolss_DeviceMode dm;\
4433 enum ndr_err_code ndr_err;\
4434 enum winreg_Type w_type;\
4435 uint32_t w_size;\
4436 uint32_t w_length;\
4437 uint8_t *w_data;\
4438 torture_assert(tctx,\
4439 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4440 &w_type, &w_size, &w_length, &w_data),\
4441 "failed to query winreg");\
4442 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4443 blob = data_blob(w_data, w_size);\
4444 ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
4445 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
4446 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
4447 torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
4448 "dm unequal");\
4449 } while(0);
4451 #define test_sd(wname, iname) \
4452 do {\
4453 DATA_BLOB blob;\
4454 struct security_descriptor sd;\
4455 enum ndr_err_code ndr_err;\
4456 enum winreg_Type w_type;\
4457 uint32_t w_size;\
4458 uint32_t w_length;\
4459 uint8_t *w_data;\
4460 torture_assert(tctx,\
4461 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4462 &w_type, &w_size, &w_length, &w_data),\
4463 "failed to query winreg");\
4464 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
4465 blob = data_blob(w_data, w_size);\
4466 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
4467 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
4468 torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
4469 torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
4470 "sd unequal");\
4471 } while(0);
4473 #define test_multi_sz(wname, iname) \
4474 do {\
4475 DATA_BLOB blob;\
4476 const char **array;\
4477 enum winreg_Type w_type;\
4478 uint32_t w_size;\
4479 uint32_t w_length;\
4480 uint8_t *w_data;\
4481 int i;\
4482 torture_assert(tctx,\
4483 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
4484 &w_type, &w_size, &w_length, &w_data),\
4485 "failed to query winreg");\
4486 torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
4487 blob = data_blob(w_data, w_size);\
4488 torture_assert(tctx, \
4489 pull_reg_multi_sz(tctx, &blob, &array),\
4490 "failed to pull multi sz");\
4491 for (i=0; array[i] != NULL; i++) {\
4492 torture_assert_str_equal(tctx, array[i], iname[i],\
4493 talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
4495 } while(0);
4497 if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
4498 TOP_LEVEL_CONTROL_PRINTERS_KEY,
4499 "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
4501 torture_warning(tctx, "failed to check for winreg symlink");
4504 for (i=0; i < ARRAY_SIZE(keys); i++) {
4506 const char *printer_key;
4507 struct policy_handle key_handle;
4509 printer_key = talloc_asprintf(tctx, "%s\\%s",
4510 keys[i], printer_name);
4512 torture_assert(tctx,
4513 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
4515 test_sz("Name", printername);
4516 test_sz("Share Name", sharename);
4517 test_sz("Port", info.info2.portname);
4518 test_sz("Printer Driver", info.info2.drivername);
4519 test_sz("Description", info.info2.comment);
4520 test_sz("Location", info.info2.location);
4521 test_sz("Separator File", info.info2.sepfile);
4522 test_sz("Print Processor", info.info2.printprocessor);
4523 test_sz("Datatype", info.info2.datatype);
4524 test_sz("Parameters", info.info2.parameters);
4525 /* winreg: 0, spoolss not */
4526 /* test_dword("Attributes", info.info2.attributes); */
4527 test_dword("Priority", info.info2.priority);
4528 test_dword("Default Priority", info.info2.defaultpriority);
4529 /* winreg: 60, spoolss: 0 */
4530 /* test_dword("StartTime", info.info2.starttime); */
4531 /* test_dword("UntilTime", info.info2.untiltime); */
4532 /* winreg != spoolss */
4533 /* test_dword("Status", info.info2.status); */
4534 test_dm("Default DevMode", info.info2.devmode);
4535 test_sd("Security", info.info2.secdesc);
4537 torture_assert(tctx,
4538 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4541 #undef test_dm
4542 #undef test_sd
4544 torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
4546 return true;
4549 static bool test_PrintProcessors(struct torture_context *tctx,
4550 struct dcerpc_binding_handle *b,
4551 const char *environment,
4552 struct dcerpc_binding_handle *winreg_handle,
4553 struct policy_handle *hive_handle)
4555 union spoolss_PrintProcessorInfo *info;
4556 uint32_t count;
4557 int i;
4559 torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
4561 torture_assert(tctx,
4562 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
4563 "failed to enum print processors level 1");
4565 for (i=0; i < count; i++) {
4567 const char *processor_key;
4568 struct policy_handle key_handle;
4570 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
4571 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4572 environment,
4573 info[i].info1.print_processor_name);
4575 torture_assert(tctx,
4576 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
4578 /* nothing to check in there so far */
4580 torture_assert(tctx,
4581 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4584 torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
4586 return true;
4589 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
4590 struct dcerpc_binding_handle *b,
4591 struct policy_handle *handle,
4592 const char *driver_name,
4593 const char *architecture,
4594 uint32_t level,
4595 uint32_t client_major_version,
4596 uint32_t client_minor_version,
4597 union spoolss_DriverInfo *info_p,
4598 WERROR *result);
4600 static const char *strip_path(const char *path)
4602 char *p;
4604 if (path == NULL) {
4605 return NULL;
4608 p = strrchr(path, '\\');
4609 if (p) {
4610 return p+1;
4613 return path;
4616 static const char **strip_paths(const char **path_array)
4618 int i;
4620 if (path_array == NULL) {
4621 return NULL;
4624 for (i=0; path_array[i] != NULL; i++) {
4625 path_array[i] = strip_path(path_array[i]);
4628 return path_array;
4631 static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
4633 time_t t;
4634 struct tm *tm;
4636 if (nt == 0) {
4637 return talloc_strdup(mem_ctx, "01/01/1601");
4640 t = nt_time_to_unix(nt);
4641 tm = localtime(&t);
4643 return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
4644 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
4647 static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
4649 return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
4650 (unsigned)((v >> 48) & 0xFFFF),
4651 (unsigned)((v >> 32) & 0xFFFF),
4652 (unsigned)((v >> 16) & 0xFFFF),
4653 (unsigned)(v & 0xFFFF));
4656 static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
4657 struct dcerpc_binding_handle *b,
4658 struct policy_handle *handle,
4659 const char *printer_name,
4660 const char *driver_name,
4661 const char *environment,
4662 enum spoolss_DriverOSVersion version,
4663 struct dcerpc_binding_handle *winreg_handle,
4664 struct policy_handle *hive_handle,
4665 const char *server_name_slash)
4667 WERROR result;
4668 union spoolss_DriverInfo info;
4669 const char *driver_key;
4670 struct policy_handle key_handle;
4672 const char *driver_path;
4673 const char *data_file;
4674 const char *config_file;
4675 const char *help_file;
4676 const char **dependent_files;
4678 const char *driver_date;
4679 const char *inbox_driver_date;
4681 const char *driver_version;
4682 const char *inbox_driver_version;
4684 torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
4686 driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
4687 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
4688 environment,
4689 version,
4690 driver_name);
4692 torture_assert(tctx,
4693 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
4694 "failed to open driver key");
4696 if (torture_setting_bool(tctx, "samba3", false) ||
4697 torture_setting_bool(tctx, "w2k3", false)) {
4698 goto try_level6;
4701 if (handle) {
4702 torture_assert(tctx,
4703 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
4704 "failed to get driver info level 8");
4705 } else {
4706 torture_assert(tctx,
4707 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
4708 "failed to get driver info level 8");
4711 if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
4712 goto try_level6;
4715 driver_path = strip_path(info.info8.driver_path);
4716 data_file = strip_path(info.info8.data_file);
4717 config_file = strip_path(info.info8.config_file);
4718 help_file = strip_path(info.info8.help_file);
4719 dependent_files = strip_paths(info.info8.dependent_files);
4721 driver_date = driver_winreg_date(tctx, info.info8.driver_date);
4722 inbox_driver_date = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
4724 driver_version = driver_winreg_version(tctx, info.info8.driver_version);
4725 inbox_driver_version = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
4727 test_sz("Configuration File", config_file);
4728 test_sz("Data File", data_file);
4729 test_sz("Datatype", info.info8.default_datatype);
4730 test_sz("Driver", driver_path);
4731 test_sz("DriverDate", driver_date);
4732 test_sz("DriverVersion", driver_version);
4733 test_sz("HardwareID", info.info8.hardware_id);
4734 test_sz("Help File", help_file);
4735 test_sz("InfPath", info.info8.inf_path);
4736 test_sz("Manufacturer", info.info8.manufacturer_name);
4737 test_sz("MinInboxDriverVerDate", inbox_driver_date);
4738 test_sz("MinInboxDriverVerVersion", inbox_driver_version);
4739 test_sz("Monitor", info.info8.monitor_name);
4740 test_sz("OEM URL", info.info8.manufacturer_url);
4741 test_sz("Print Processor", info.info8.print_processor);
4742 test_sz("Provider", info.info8.provider);
4743 test_sz("VendorSetup", info.info8.vendor_setup);
4744 test_multi_sz("ColorProfiles", info.info8.color_profiles);
4745 test_multi_sz("Dependent Files", dependent_files);
4746 test_multi_sz("CoreDependencies", info.info8.core_driver_dependencies);
4747 test_multi_sz("Previous Names", info.info8.previous_names);
4748 /* test_dword("Attributes", ?); */
4749 test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
4750 test_dword("Version", info.info8.version);
4751 /* test_dword("TempDir", ?); */
4753 try_level6:
4755 if (handle) {
4756 torture_assert(tctx,
4757 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
4758 "failed to get driver info level 6");
4759 } else {
4760 torture_assert(tctx,
4761 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
4762 "failed to get driver info level 6");
4765 driver_path = strip_path(info.info6.driver_path);
4766 data_file = strip_path(info.info6.data_file);
4767 config_file = strip_path(info.info6.config_file);
4768 help_file = strip_path(info.info6.help_file);
4769 dependent_files = strip_paths(info.info6.dependent_files);
4771 driver_date = driver_winreg_date(tctx, info.info6.driver_date);
4773 driver_version = driver_winreg_version(tctx, info.info6.driver_version);
4775 test_sz("Configuration File", config_file);
4776 test_sz("Data File", data_file);
4777 test_sz("Datatype", info.info6.default_datatype);
4778 test_sz("Driver", driver_path);
4779 if (torture_setting_bool(tctx, "w2k3", false)) {
4780 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
4781 push_nttime(blob.data, 0, info.info6.driver_date);
4782 test_binary("DriverDate", blob);
4783 SBVAL(blob.data, 0, info.info6.driver_version);
4784 test_binary("DriverVersion", blob);
4785 } else {
4786 test_sz("DriverDate", driver_date);
4787 test_sz("DriverVersion", driver_version);
4789 test_sz("HardwareID", info.info6.hardware_id);
4790 test_sz("Help File", help_file);
4791 test_sz("Manufacturer", info.info6.manufacturer_name);
4792 test_sz("Monitor", info.info6.monitor_name);
4793 test_sz("OEM URL", info.info6.manufacturer_url);
4794 test_sz("Provider", info.info6.provider);
4795 test_multi_sz("Dependent Files", dependent_files);
4796 test_multi_sz("Previous Names", info.info6.previous_names);
4797 /* test_dword("Attributes", ?); */
4798 test_dword("Version", info.info6.version);
4799 /* test_dword("TempDir", ?); */
4801 if (handle) {
4802 torture_assert(tctx,
4803 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
4804 "failed to get driver info level 3");
4805 } else {
4806 torture_assert(tctx,
4807 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
4808 "failed to get driver info level 3");
4811 driver_path = strip_path(info.info3.driver_path);
4812 data_file = strip_path(info.info3.data_file);
4813 config_file = strip_path(info.info3.config_file);
4814 help_file = strip_path(info.info3.help_file);
4815 dependent_files = strip_paths(info.info3.dependent_files);
4817 test_sz("Configuration File", config_file);
4818 test_sz("Data File", data_file);
4819 test_sz("Datatype", info.info3.default_datatype);
4820 test_sz("Driver", driver_path);
4821 test_sz("Help File", help_file);
4822 test_sz("Monitor", info.info3.monitor_name);
4823 test_multi_sz("Dependent Files", dependent_files);
4824 /* test_dword("Attributes", ?); */
4825 test_dword("Version", info.info3.version);
4826 /* test_dword("TempDir", ?); */
4829 torture_assert(tctx,
4830 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
4832 torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
4834 return true;
4837 #undef test_sz
4838 #undef test_dword
4840 static bool test_SetPrinterData(struct torture_context *tctx,
4841 struct dcerpc_binding_handle *b,
4842 struct policy_handle *handle,
4843 const char *value_name,
4844 enum winreg_Type type,
4845 uint8_t *data,
4846 uint32_t offered)
4848 struct spoolss_SetPrinterData r;
4850 r.in.handle = handle;
4851 r.in.value_name = value_name;
4852 r.in.type = type;
4853 r.in.data = data;
4854 r.in.offered = offered;
4856 torture_comment(tctx, "Testing SetPrinterData(%s)\n",
4857 r.in.value_name);
4859 torture_assert_ntstatus_ok(tctx,
4860 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
4861 "SetPrinterData failed");
4862 torture_assert_werr_ok(tctx, r.out.result,
4863 "SetPrinterData failed");
4865 return true;
4868 static bool test_SetPrinterData_matrix(struct torture_context *tctx,
4869 struct dcerpc_binding_handle *b,
4870 struct policy_handle *handle,
4871 const char *printer_name,
4872 struct dcerpc_binding_handle *winreg_handle,
4873 struct policy_handle *hive_handle)
4875 const char *values[] = {
4876 "spootyfoot",
4877 "spooty\\foot",
4878 #if 0
4879 /* FIXME: not working with s3 atm. */
4880 "spooty,foot",
4881 "spooty,fo,ot",
4882 #endif
4883 "spooty foot",
4884 #if 0
4885 /* FIXME: not working with s3 atm. */
4886 "spooty\\fo,ot",
4887 "spooty,fo\\ot"
4888 #endif
4890 int i;
4892 for (i=0; i < ARRAY_SIZE(values); i++) {
4894 enum winreg_Type type, expected_type = REG_SZ;
4895 DATA_BLOB blob;
4896 uint8_t *data;
4897 uint32_t needed;
4899 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
4900 type = REG_SZ;
4902 torture_assert(tctx,
4903 test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
4904 "SetPrinterData failed");
4906 torture_assert(tctx,
4907 test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
4908 "GetPrinterData failed");
4910 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
4911 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
4912 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
4914 if (winreg_handle && hive_handle) {
4916 enum winreg_Type w_type;
4917 uint32_t w_size;
4918 uint32_t w_length;
4919 uint8_t *w_data;
4921 torture_assert(tctx,
4922 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
4923 printer_name, "PrinterDriverData", values[i],
4924 &w_type, &w_size, &w_length, &w_data), "");
4926 torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
4927 torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
4928 torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
4929 torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
4932 torture_assert(tctx,
4933 test_DeletePrinterData(tctx, b, handle, values[i]),
4934 "DeletePrinterData failed");
4937 return true;
4941 static bool test_EnumPrinterKey(struct torture_context *tctx,
4942 struct dcerpc_binding_handle *b,
4943 struct policy_handle *handle,
4944 const char *key_name,
4945 const char ***array);
4947 static bool test_SetPrinterDataEx(struct torture_context *tctx,
4948 struct dcerpc_binding_handle *b,
4949 struct policy_handle *handle,
4950 const char *key_name,
4951 const char *value_name,
4952 enum winreg_Type type,
4953 uint8_t *data,
4954 uint32_t offered)
4956 NTSTATUS status;
4957 struct spoolss_SetPrinterDataEx r;
4959 r.in.handle = handle;
4960 r.in.key_name = key_name;
4961 r.in.value_name = value_name;
4962 r.in.type = type;
4963 r.in.data = data;
4964 r.in.offered = offered;
4966 torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
4967 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
4969 status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
4971 torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
4972 torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
4974 return true;
4977 static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
4978 struct dcerpc_pipe *p,
4979 struct policy_handle *handle)
4981 struct dcerpc_binding_handle *b = p->binding_handle;
4982 const char *value_name = "dog";
4983 const char *keys[] = {
4984 "torturedataex",
4985 "torture data ex",
4986 "torturedataex_with_subkey\\subkey",
4987 "torturedataex_with_subkey\\subkey:0",
4988 "torturedataex_with_subkey\\subkey:1",
4989 "torturedataex_with_subkey\\subkey\\subsubkey",
4990 "torturedataex_with_subkey\\subkey\\subsubkey:0",
4991 "torturedataex_with_subkey\\subkey\\subsubkey:1",
4992 "torture,data",
4993 "torture,data,ex",
4994 "torture,data\\ex",
4995 "torture\\data,ex",
4996 "torture/data",
4997 "torture/data ex",
4998 "torture/data ex/sub",
4999 "torture//data",
5000 "torture//data ex",
5001 "torture//data ex/sub",
5002 "torture//data ex//sub",
5004 int i;
5006 for (i=0; i < ARRAY_SIZE(keys); i++) {
5008 char *c;
5009 const char *key;
5010 enum winreg_Type type;
5011 DATA_BLOB blob_in, blob_out;
5012 const char **subkeys;
5013 uint32_t ecount;
5014 struct spoolss_PrinterEnumValues *einfo;
5015 uint32_t needed;
5017 blob_in = data_blob_talloc(tctx, NULL, 42);
5019 generate_random_buffer(blob_in.data, blob_in.length);
5021 torture_assert(tctx,
5022 test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
5023 "failed to call SetPrinterDataEx");
5025 torture_assert(tctx,
5026 test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
5027 "failed to call GetPrinterDataEx");
5029 blob_out.length = needed;
5030 torture_assert(tctx,
5031 test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
5032 "failed to call EnumPrinterDataEx");
5034 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5035 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5036 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5038 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5039 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5040 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5041 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5042 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5043 if (einfo[0].data_length > 0) {
5044 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5047 key = talloc_strdup(tctx, keys[i]);
5049 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
5050 return false;
5053 c = strchr(key, '\\');
5054 if (c) {
5055 int k;
5057 /* we have subkeys */
5059 *c = 0;
5061 if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
5062 return false;
5065 for (k=0; subkeys && subkeys[k]; k++) {
5067 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
5069 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
5070 return false;
5074 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5075 return false;
5078 } else {
5079 if (!test_DeletePrinterKey(tctx, b, handle, key)) {
5080 return false;
5085 return true;
5088 static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
5089 struct dcerpc_pipe *p,
5090 struct policy_handle *handle)
5092 struct dcerpc_binding_handle *b = p->binding_handle;
5093 const char *key = "torturedataex";
5094 const char *values[] = {
5095 "torture_value",
5096 "torture value",
5097 "torture,value",
5098 "torture/value",
5099 "torture\\value",
5100 "torture\\\\value"
5102 int i;
5104 for (i=0; i < ARRAY_SIZE(values); i++) {
5106 enum winreg_Type type;
5107 DATA_BLOB blob_in, blob_out;
5108 uint32_t ecount;
5109 struct spoolss_PrinterEnumValues *einfo;
5110 uint32_t needed;
5112 if (torture_setting_bool(tctx, "samba3", false)) {
5113 char *q;
5114 q = strrchr(values[i], ',');
5115 if (q) {
5116 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
5117 values[i]);
5118 continue;
5122 blob_in = data_blob_talloc(tctx, NULL, 42);
5124 generate_random_buffer(blob_in.data, blob_in.length);
5126 torture_assert(tctx,
5127 test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
5128 "failed to call SetPrinterDataEx");
5130 torture_assert(tctx,
5131 test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
5132 "failed to call GetPrinterDataEx");
5134 blob_out.length = needed;
5135 torture_assert(tctx,
5136 test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
5137 "failed to call EnumPrinterDataEx");
5139 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
5140 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
5141 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
5143 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5144 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
5145 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
5146 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
5147 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
5148 if (einfo[0].data_length > 0) {
5149 torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
5152 torture_assert(tctx,
5153 test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
5154 "failed to call DeletePrinterDataEx");
5157 return true;
5161 static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
5162 struct dcerpc_pipe *p,
5163 struct policy_handle *handle,
5164 const char *printername,
5165 struct dcerpc_binding_handle *winreg_handle,
5166 struct policy_handle *hive_handle)
5168 struct dcerpc_binding_handle *b = p->binding_handle;
5169 const char *value_name = "dog";
5170 const char *key_name = "torturedataex";
5171 enum winreg_Type types[] = {
5172 REG_SZ,
5173 REG_MULTI_SZ,
5174 REG_DWORD,
5175 REG_BINARY
5177 const char *str = "abcdefghi";
5178 int t, s;
5180 for (t=0; t < ARRAY_SIZE(types); t++) {
5181 for (s=0; s < strlen(str); s++) {
5183 enum winreg_Type type;
5184 const char *string = talloc_strndup(tctx, str, s);
5185 const char *array[2];
5186 DATA_BLOB blob = data_blob_string_const(string);
5187 DATA_BLOB data;
5188 uint8_t *data_out;
5189 uint32_t needed, offered = 0;
5190 uint32_t ecount;
5191 struct spoolss_PrinterEnumValues *einfo;
5193 array[0] = talloc_strdup(tctx, string);
5194 array[1] = NULL;
5196 if (types[t] == REG_DWORD) {
5197 s = 0xffff;
5200 switch (types[t]) {
5201 case REG_BINARY:
5202 data = blob;
5203 offered = blob.length;
5204 break;
5205 case REG_DWORD:
5206 data = data_blob_talloc(tctx, NULL, 4);
5207 SIVAL(data.data, 0, 0x12345678);
5208 offered = 4;
5209 break;
5210 case REG_SZ:
5211 torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
5212 type = REG_SZ;
5213 offered = data.length;
5214 /*strlen_m_term(data.string)*2;*/
5215 break;
5216 case REG_MULTI_SZ:
5217 torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
5218 type = REG_MULTI_SZ;
5219 offered = data.length;
5220 break;
5221 default:
5222 torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
5225 torture_assert(tctx,
5226 test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
5227 "failed to call SetPrinterDataEx");
5229 torture_assert(tctx,
5230 test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
5231 "failed to call GetPrinterDataEx");
5233 torture_assert(tctx,
5234 test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
5235 "failed to call EnumPrinterDataEx");
5237 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
5238 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
5239 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
5241 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
5242 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
5243 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
5244 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
5245 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
5246 if (einfo[0].data_length > 0) {
5247 torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
5250 if (winreg_handle && hive_handle) {
5251 enum winreg_Type w_type;
5252 uint32_t w_size;
5253 uint32_t w_length;
5254 uint8_t *w_data;
5256 torture_assert(tctx,
5257 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
5258 printername, key_name, value_name,
5259 &w_type, &w_size, &w_length, &w_data), "");
5261 torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
5262 torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
5263 torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
5264 torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
5267 torture_assert(tctx,
5268 test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
5269 "failed to call DeletePrinterDataEx");
5273 return true;
5276 static bool test_PrinterData_winreg(struct torture_context *tctx,
5277 struct dcerpc_pipe *p,
5278 struct policy_handle *handle,
5279 const char *printer_name)
5281 struct dcerpc_binding_handle *b = p->binding_handle;
5282 struct dcerpc_pipe *p2;
5283 bool ret = true;
5284 struct policy_handle hive_handle;
5285 struct dcerpc_binding_handle *b2;
5287 torture_assert_ntstatus_ok(tctx,
5288 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5289 "could not open winreg pipe");
5290 b2 = p2->binding_handle;
5292 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5294 ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
5295 ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
5297 test_winreg_CloseKey(tctx, b2, &hive_handle);
5299 talloc_free(p2);
5301 return ret;
5304 static bool test_Forms_winreg(struct torture_context *tctx,
5305 struct dcerpc_binding_handle *b,
5306 struct policy_handle *handle,
5307 bool print_server,
5308 const char *printer_name)
5310 struct dcerpc_pipe *p2;
5311 bool ret = true;
5312 struct policy_handle hive_handle;
5313 struct dcerpc_binding_handle *b2;
5315 torture_assert_ntstatus_ok(tctx,
5316 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5317 "could not open winreg pipe");
5318 b2 = p2->binding_handle;
5320 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5322 ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
5324 test_winreg_CloseKey(tctx, b2, &hive_handle);
5326 talloc_free(p2);
5328 return ret;
5331 static bool test_PrinterInfo_winreg(struct torture_context *tctx,
5332 struct dcerpc_pipe *p,
5333 struct policy_handle *handle,
5334 const char *printer_name)
5336 struct dcerpc_binding_handle *b = p->binding_handle;
5337 struct dcerpc_pipe *p2;
5338 bool ret = true;
5339 struct policy_handle hive_handle;
5340 struct dcerpc_binding_handle *b2;
5342 torture_assert_ntstatus_ok(tctx,
5343 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5344 "could not open winreg pipe");
5345 b2 = p2->binding_handle;
5347 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5349 ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
5351 test_winreg_CloseKey(tctx, b2, &hive_handle);
5353 talloc_free(p2);
5355 return ret;
5358 static bool test_DriverInfo_winreg(struct torture_context *tctx,
5359 struct dcerpc_pipe *p,
5360 struct policy_handle *handle,
5361 const char *printer_name,
5362 const char *driver_name,
5363 const char *environment,
5364 enum spoolss_DriverOSVersion version)
5366 struct dcerpc_binding_handle *b = p->binding_handle;
5367 struct dcerpc_pipe *p2;
5368 bool ret = true;
5369 struct policy_handle hive_handle;
5370 struct dcerpc_binding_handle *b2;
5372 torture_assert_ntstatus_ok(tctx,
5373 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5374 "could not open winreg pipe");
5375 b2 = p2->binding_handle;
5377 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5379 ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
5381 test_winreg_CloseKey(tctx, b2, &hive_handle);
5383 talloc_free(p2);
5385 return ret;
5388 static bool test_PrintProcessors_winreg(struct torture_context *tctx,
5389 struct dcerpc_binding_handle *b,
5390 const char *environment)
5392 struct dcerpc_pipe *p2;
5393 bool ret = true;
5394 struct policy_handle hive_handle;
5395 struct dcerpc_binding_handle *b2;
5397 torture_assert_ntstatus_ok(tctx,
5398 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
5399 "could not open winreg pipe");
5400 b2 = p2->binding_handle;
5402 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
5404 ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
5406 test_winreg_CloseKey(tctx, b2, &hive_handle);
5408 talloc_free(p2);
5410 return ret;
5413 static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
5414 struct dcerpc_pipe *p,
5415 struct policy_handle *handle,
5416 const char *printer_name)
5418 struct spoolss_SetPrinterInfoCtr info_ctr;
5419 struct spoolss_DevmodeContainer devmode_ctr;
5420 struct sec_desc_buf secdesc_ctr;
5421 union spoolss_SetPrinterInfo sinfo;
5422 union spoolss_PrinterInfo info;
5423 struct dcerpc_binding_handle *b = p->binding_handle;
5424 const char *pname;
5426 ZERO_STRUCT(info_ctr);
5427 ZERO_STRUCT(devmode_ctr);
5428 ZERO_STRUCT(secdesc_ctr);
5430 torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
5432 torture_assert(tctx,
5433 test_GetPrinter_level(tctx, b, handle, 2, &info),
5434 "failed to query Printer level 2");
5436 torture_assert(tctx,
5437 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
5438 "failed to convert");
5440 info_ctr.level = 2;
5441 info_ctr.info = sinfo;
5443 #define TEST_SZ(wname, iname) \
5444 do {\
5445 enum winreg_Type type;\
5446 uint8_t *data;\
5447 uint32_t needed;\
5448 DATA_BLOB blob;\
5449 const char *str;\
5450 torture_assert(tctx,\
5451 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5452 "failed to query");\
5453 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5454 blob = data_blob_const(data, needed);\
5455 torture_assert(tctx,\
5456 pull_reg_sz(tctx, &blob, &str),\
5457 "failed to pull REG_SZ");\
5458 torture_assert_str_equal(tctx, str, iname, "unexpected result");\
5459 } while(0);
5462 #define TEST_SET_SZ(wname, iname, val) \
5463 do {\
5464 enum winreg_Type type;\
5465 uint8_t *data;\
5466 uint32_t needed;\
5467 DATA_BLOB blob;\
5468 const char *str;\
5469 sinfo.info2->iname = val;\
5470 torture_assert(tctx,\
5471 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5472 "failed to call SetPrinter");\
5473 torture_assert(tctx,\
5474 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5475 "failed to query");\
5476 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
5477 blob = data_blob_const(data, needed);\
5478 torture_assert(tctx,\
5479 pull_reg_sz(tctx, &blob, &str),\
5480 "failed to pull REG_SZ");\
5481 torture_assert_str_equal(tctx, str, val, "unexpected result");\
5482 } while(0);
5484 #define TEST_SET_DWORD(wname, iname, val) \
5485 do {\
5486 enum winreg_Type type;\
5487 uint8_t *data;\
5488 uint32_t needed;\
5489 uint32_t value;\
5490 sinfo.info2->iname = val;\
5491 torture_assert(tctx,\
5492 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
5493 "failed to call SetPrinter");\
5494 torture_assert(tctx,\
5495 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
5496 "failed to query");\
5497 torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
5498 torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
5499 value = IVAL(data, 0); \
5500 torture_assert_int_equal(tctx, value, val, "unexpected result");\
5501 } while(0);
5503 TEST_SET_SZ("description", comment, "newval");
5504 TEST_SET_SZ("location", location, "newval");
5505 TEST_SET_SZ("driverName", drivername, "newval");
5506 /* TEST_SET_DWORD("priority", priority, 25); */
5508 torture_assert(tctx,
5509 test_GetPrinter_level(tctx, b, handle, 2, &info),
5510 "failed to query Printer level 2");
5512 TEST_SZ("description", info.info2.comment);
5513 TEST_SZ("driverName", info.info2.drivername);
5514 TEST_SZ("location", info.info2.location);
5516 pname = strrchr(info.info2.printername, '\\');
5517 if (pname == NULL) {
5518 pname = info.info2.printername;
5519 } else {
5520 pname++;
5522 TEST_SZ("printerName", pname);
5523 /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
5524 /* TEST_SZ("printShareName", info.info2.sharename); */
5526 /* FIXME gd: complete the list */
5528 #undef TEST_SZ
5529 #undef TEST_SET_SZ
5530 #undef TEST_DWORD
5532 torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
5534 return true;
5537 static bool test_print_processors_winreg(struct torture_context *tctx,
5538 void *private_data)
5540 struct test_spoolss_context *ctx =
5541 talloc_get_type_abort(private_data, struct test_spoolss_context);
5542 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5543 struct dcerpc_binding_handle *b = p->binding_handle;
5545 return test_PrintProcessors_winreg(tctx, b, ctx->environment);
5548 static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
5549 struct dcerpc_binding_handle *b,
5550 struct policy_handle *handle,
5551 uint32_t *change_id)
5553 enum winreg_Type type;
5554 uint8_t *data;
5555 uint32_t needed;
5557 torture_assert(tctx,
5558 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
5559 "failed to call GetPrinterData");
5561 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5562 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5564 *change_id = IVAL(data, 0);
5566 return true;
5569 static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
5570 struct dcerpc_pipe *p,
5571 struct policy_handle *handle,
5572 uint32_t *change_id)
5574 enum winreg_Type type;
5575 uint8_t *data;
5576 uint32_t needed;
5578 torture_assert(tctx,
5579 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
5580 "failed to call GetPrinterData");
5582 torture_assert(tctx, type == REG_DWORD, "unexpected type");
5583 torture_assert_int_equal(tctx, needed, 4, "unexpected size");
5585 *change_id = IVAL(data, 0);
5587 return true;
5590 static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
5591 struct dcerpc_binding_handle *b,
5592 struct policy_handle *handle,
5593 uint32_t *change_id)
5595 union spoolss_PrinterInfo info;
5597 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
5598 "failed to query Printer level 0");
5600 *change_id = info.info0.change_id;
5602 return true;
5605 static bool test_ChangeID(struct torture_context *tctx,
5606 struct dcerpc_pipe *p,
5607 struct policy_handle *handle)
5609 uint32_t change_id, change_id_ex, change_id_info;
5610 uint32_t change_id2, change_id_ex2, change_id_info2;
5611 union spoolss_PrinterInfo info;
5612 const char *comment;
5613 struct dcerpc_binding_handle *b = p->binding_handle;
5615 torture_comment(tctx, "Testing ChangeID: id change test #1\n");
5617 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5618 "failed to query for ChangeID");
5619 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5620 "failed to query for ChangeID");
5621 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5622 "failed to query for ChangeID");
5624 torture_assert_int_equal(tctx, change_id, change_id_ex,
5625 "change_ids should all be equal");
5626 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5627 "change_ids should all be equal");
5630 torture_comment(tctx, "Testing ChangeID: id change test #2\n");
5632 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5633 "failed to query for ChangeID");
5634 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5635 "failed to query Printer level 2");
5636 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5637 "failed to query for ChangeID");
5638 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5639 "failed to query for ChangeID");
5640 torture_assert_int_equal(tctx, change_id, change_id_ex,
5641 "change_id should not have changed");
5642 torture_assert_int_equal(tctx, change_id_ex, change_id_info,
5643 "change_id should not have changed");
5646 torture_comment(tctx, "Testing ChangeID: id change test #3\n");
5648 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
5649 "failed to query for ChangeID");
5650 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
5651 "failed to query for ChangeID");
5652 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
5653 "failed to query for ChangeID");
5654 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
5655 "failed to query Printer level 2");
5656 comment = talloc_strdup(tctx, info.info2.comment);
5659 struct spoolss_SetPrinterInfoCtr info_ctr;
5660 struct spoolss_DevmodeContainer devmode_ctr;
5661 struct sec_desc_buf secdesc_ctr;
5662 union spoolss_SetPrinterInfo sinfo;
5664 ZERO_STRUCT(info_ctr);
5665 ZERO_STRUCT(devmode_ctr);
5666 ZERO_STRUCT(secdesc_ctr);
5669 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5670 sinfo.info2->comment = "torture_comment";
5672 info_ctr.level = 2;
5673 info_ctr.info = sinfo;
5675 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5676 "failed to call SetPrinter");
5678 sinfo.info2->comment = comment;
5680 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5681 "failed to call SetPrinter");
5685 torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
5686 "failed to query for ChangeID");
5687 torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
5688 "failed to query for ChangeID");
5689 torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
5690 "failed to query for ChangeID");
5692 torture_assert_int_equal(tctx, change_id2, change_id_ex2,
5693 "change_ids should all be equal");
5694 torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
5695 "change_ids should all be equal");
5697 torture_assert(tctx, (change_id < change_id2),
5698 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5699 change_id2, change_id));
5700 torture_assert(tctx, (change_id_ex < change_id_ex2),
5701 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5702 change_id_ex2, change_id_ex));
5703 torture_assert(tctx, (change_id_info < change_id_info2),
5704 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
5705 change_id_info2, change_id_info));
5707 torture_comment(tctx, "ChangeID tests succeeded\n\n");
5709 return true;
5712 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
5713 struct dcerpc_pipe *p,
5714 struct policy_handle *handle)
5716 NTSTATUS status;
5717 struct dcerpc_binding *b;
5718 struct dcerpc_pipe *p2;
5719 struct spoolss_ClosePrinter cp;
5721 /* only makes sense on SMB */
5722 if (p->conn->transport.transport != NCACN_NP) {
5723 return true;
5726 torture_comment(tctx, "Testing close on secondary pipe\n");
5728 status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
5729 torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
5731 status = dcerpc_secondary_connection(p, &p2, b);
5732 torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
5734 status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
5735 torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
5737 cp.in.handle = handle;
5738 cp.out.handle = handle;
5740 status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
5741 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
5742 "ERROR: Allowed close on secondary connection");
5744 talloc_free(p2);
5746 return true;
5749 static bool test_OpenPrinter_badname(struct torture_context *tctx,
5750 struct dcerpc_binding_handle *b, const char *name)
5752 NTSTATUS status;
5753 struct spoolss_OpenPrinter op;
5754 struct spoolss_OpenPrinterEx opEx;
5755 struct policy_handle handle;
5756 bool ret = true;
5758 op.in.printername = name;
5759 op.in.datatype = NULL;
5760 op.in.devmode_ctr.devmode= NULL;
5761 op.in.access_mask = 0;
5762 op.out.handle = &handle;
5764 torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
5766 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
5767 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5768 torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
5769 "unexpected result");
5771 if (W_ERROR_IS_OK(op.out.result)) {
5772 ret &=test_ClosePrinter(tctx, b, &handle);
5775 opEx.in.printername = name;
5776 opEx.in.datatype = NULL;
5777 opEx.in.devmode_ctr.devmode = NULL;
5778 opEx.in.access_mask = 0;
5779 opEx.in.level = 1;
5780 opEx.in.userlevel.level1 = NULL;
5781 opEx.out.handle = &handle;
5783 torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
5785 status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
5786 torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
5787 torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAM,
5788 "unexpected result");
5790 if (W_ERROR_IS_OK(opEx.out.result)) {
5791 ret &=test_ClosePrinter(tctx, b, &handle);
5794 return ret;
5797 static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
5798 void *private_data)
5800 struct test_spoolss_context *ctx =
5801 talloc_get_type_abort(private_data, struct test_spoolss_context);
5803 const char *badnames[] = {
5804 "__INVALID_PRINTER__",
5805 "\\\\__INVALID_HOST__",
5807 "\\\\\\",
5808 "\\\\\\__INVALID_PRINTER__"
5810 const char *badname;
5811 struct dcerpc_pipe *p = ctx->spoolss_pipe;
5812 const char *server_name = dcerpc_server_name(p);
5813 struct dcerpc_binding_handle *b = p->binding_handle;
5814 int i;
5816 for (i=0; i < ARRAY_SIZE(badnames); i++) {
5817 torture_assert(tctx,
5818 test_OpenPrinter_badname(tctx, b, badnames[i]),
5819 "");
5822 badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
5823 torture_assert(tctx,
5824 test_OpenPrinter_badname(tctx, b, badname),
5825 "");
5827 badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
5828 torture_assert(tctx,
5829 test_OpenPrinter_badname(tctx, b, badname),
5830 "");
5832 return true;
5835 static bool test_OpenPrinter(struct torture_context *tctx,
5836 struct dcerpc_pipe *p,
5837 const char *name,
5838 const char *environment,
5839 bool open_only)
5841 NTSTATUS status;
5842 struct spoolss_OpenPrinter r;
5843 struct policy_handle handle;
5844 bool ret = true;
5845 struct dcerpc_binding_handle *b = p->binding_handle;
5847 r.in.printername = name;
5848 r.in.datatype = NULL;
5849 r.in.devmode_ctr.devmode= NULL;
5850 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5851 r.out.handle = &handle;
5853 torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
5855 status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
5857 torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
5859 torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
5861 if (open_only) {
5862 goto close_printer;
5865 if (!test_GetPrinter(tctx, b, &handle, environment)) {
5866 ret = false;
5869 if (!torture_setting_bool(tctx, "samba3", false)) {
5870 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
5871 ret = false;
5875 close_printer:
5876 if (!test_ClosePrinter(tctx, b, &handle)) {
5877 ret = false;
5880 return ret;
5883 static bool test_OpenPrinterEx(struct torture_context *tctx,
5884 struct dcerpc_binding_handle *b,
5885 const char *printername,
5886 const char *datatype,
5887 struct spoolss_DeviceMode *devmode,
5888 uint32_t access_mask,
5889 uint32_t level,
5890 union spoolss_UserLevel *userlevel,
5891 struct policy_handle *handle,
5892 WERROR expected_result)
5894 struct spoolss_OpenPrinterEx r;
5896 r.in.printername = printername;
5897 r.in.datatype = datatype;
5898 r.in.devmode_ctr.devmode= devmode;
5899 r.in.access_mask = access_mask;
5900 r.in.level = level;
5901 r.in.userlevel = *userlevel;
5902 r.out.handle = handle;
5904 torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
5906 torture_assert_ntstatus_ok(tctx,
5907 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
5908 "OpenPrinterEx failed");
5910 torture_assert_werr_equal(tctx, r.out.result, expected_result,
5911 "OpenPrinterEx failed");
5913 return true;
5916 static bool call_OpenPrinterEx(struct torture_context *tctx,
5917 struct dcerpc_pipe *p,
5918 const char *name,
5919 struct spoolss_DeviceMode *devmode,
5920 struct policy_handle *handle)
5922 union spoolss_UserLevel userlevel;
5923 struct spoolss_UserLevel1 userlevel1;
5924 struct dcerpc_binding_handle *b = p->binding_handle;
5926 userlevel1.size = 1234;
5927 userlevel1.client = "hello";
5928 userlevel1.user = "spottyfoot!";
5929 userlevel1.build = 1;
5930 userlevel1.major = 2;
5931 userlevel1.minor = 3;
5932 userlevel1.processor = 4;
5934 userlevel.level1 = &userlevel1;
5936 return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
5937 SEC_FLAG_MAXIMUM_ALLOWED,
5939 &userlevel,
5940 handle,
5941 WERR_OK);
5944 static bool test_printer_rename(struct torture_context *tctx,
5945 void *private_data)
5947 struct torture_printer_context *t =
5948 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
5949 struct dcerpc_pipe *p = t->spoolss_pipe;
5951 bool ret = true;
5952 union spoolss_PrinterInfo info;
5953 union spoolss_SetPrinterInfo sinfo;
5954 struct spoolss_SetPrinterInfoCtr info_ctr;
5955 struct spoolss_DevmodeContainer devmode_ctr;
5956 struct sec_desc_buf secdesc_ctr;
5957 const char *printer_name;
5958 const char *printer_name_orig;
5959 const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
5960 struct policy_handle new_handle;
5961 const char *q;
5962 struct dcerpc_binding_handle *b = p->binding_handle;
5964 ZERO_STRUCT(devmode_ctr);
5965 ZERO_STRUCT(secdesc_ctr);
5967 torture_comment(tctx, "Testing Printer rename operations\n");
5969 torture_assert(tctx,
5970 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5971 "failed to call GetPrinter level 2");
5973 printer_name_orig = talloc_strdup(tctx, info.info2.printername);
5975 q = strrchr(info.info2.printername, '\\');
5976 if (q) {
5977 torture_warning(tctx,
5978 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
5981 torture_assert(tctx,
5982 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
5984 sinfo.info2->printername = printer_name_new;
5986 info_ctr.level = 2;
5987 info_ctr.info = sinfo;
5989 torture_assert(tctx,
5990 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
5991 "failed to call SetPrinter level 2");
5993 torture_assert(tctx,
5994 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
5995 "failed to call GetPrinter level 2");
5997 printer_name = talloc_strdup(tctx, info.info2.printername);
5999 q = strrchr(info.info2.printername, '\\');
6000 if (q) {
6001 torture_warning(tctx,
6002 "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
6003 q++;
6004 printer_name = q;
6007 torture_assert_str_equal(tctx, printer_name, printer_name_new,
6008 "new printer name was not set");
6010 /* samba currently cannot fully rename printers */
6011 if (!torture_setting_bool(tctx, "samba3", false)) {
6012 torture_assert(tctx,
6013 test_OpenPrinter_badname(tctx, b, printer_name_orig),
6014 "still can open printer with oldname after rename");
6015 } else {
6016 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
6019 torture_assert(tctx,
6020 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
6021 "failed to open printer with new name");
6023 torture_assert(tctx,
6024 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
6025 "failed to call GetPrinter level 2");
6027 torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
6028 "new printer name was not set");
6030 torture_assert(tctx,
6031 test_ClosePrinter(tctx, b, &new_handle),
6032 "failed to close printer");
6034 torture_comment(tctx, "Printer rename operations test succeeded\n\n");
6036 return ret;
6039 static bool test_openprinter(struct torture_context *tctx,
6040 struct dcerpc_binding_handle *b,
6041 const char *real_printername)
6043 union spoolss_UserLevel userlevel;
6044 struct policy_handle handle;
6045 struct spoolss_UserLevel1 userlevel1;
6046 const char *printername = NULL;
6047 int i;
6049 struct {
6050 const char *suffix;
6051 WERROR expected_result;
6052 } tests[] = {
6054 .suffix = "rubbish",
6055 .expected_result = WERR_INVALID_PRINTER_NAME
6057 .suffix = ", LocalOnl",
6058 .expected_result = WERR_INVALID_PRINTER_NAME
6060 .suffix = ", localOnly",
6061 .expected_result = WERR_INVALID_PRINTER_NAME
6063 .suffix = ", localonl",
6064 .expected_result = WERR_INVALID_PRINTER_NAME
6066 .suffix = ",LocalOnl",
6067 .expected_result = WERR_INVALID_PRINTER_NAME
6069 .suffix = ",localOnl2",
6070 .expected_result = WERR_INVALID_PRINTER_NAME
6072 .suffix = ", DrvConver2t",
6073 .expected_result = WERR_INVALID_PRINTER_NAME
6075 .suffix = ", drvconvert",
6076 .expected_result = WERR_INVALID_PRINTER_NAME
6078 .suffix = ",drvconvert",
6079 .expected_result = WERR_INVALID_PRINTER_NAME
6081 .suffix = ", DrvConvert",
6082 .expected_result = WERR_OK
6084 .suffix = " , DrvConvert",
6085 .expected_result = WERR_INVALID_PRINTER_NAME
6087 .suffix = ",DrvConvert",
6088 .expected_result = WERR_OK
6090 .suffix = ", DrvConvertsadfasdf",
6091 .expected_result = WERR_OK
6093 .suffix = ",DrvConvertasdfasd",
6094 .expected_result = WERR_OK
6096 .suffix = ", LocalOnly",
6097 .expected_result = WERR_OK
6099 .suffix = " , LocalOnly",
6100 .expected_result = WERR_INVALID_PRINTER_NAME
6102 .suffix = ",LocalOnly",
6103 .expected_result = WERR_OK
6105 .suffix = ", LocalOnlysagi4gjfkd",
6106 .expected_result = WERR_OK
6108 .suffix = ",LocalOnlysagi4gjfkd",
6109 .expected_result = WERR_OK
6113 userlevel1.size = 1234;
6114 userlevel1.client = "hello";
6115 userlevel1.user = "spottyfoot!";
6116 userlevel1.build = 1;
6117 userlevel1.major = 2;
6118 userlevel1.minor = 3;
6119 userlevel1.processor = 4;
6121 userlevel.level1 = &userlevel1;
6123 torture_comment(tctx, "Testing openprinterex printername pattern\n");
6125 torture_assert(tctx,
6126 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0, 1,
6127 &userlevel, &handle,
6128 WERR_OK),
6129 "OpenPrinterEx failed");
6130 test_ClosePrinter(tctx, b, &handle);
6132 for (i=0; i < ARRAY_SIZE(tests); i++) {
6134 printername = talloc_asprintf(tctx, "%s%s",
6135 real_printername,
6136 tests[i].suffix);
6138 torture_assert(tctx,
6139 test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0, 1,
6140 &userlevel, &handle,
6141 tests[i].expected_result),
6142 "OpenPrinterEx failed");
6143 if (W_ERROR_IS_OK(tests[i].expected_result)) {
6144 test_ClosePrinter(tctx, b, &handle);
6148 return true;
6152 static bool test_existing_printer_openprinterex(struct torture_context *tctx,
6153 struct dcerpc_pipe *p,
6154 const char *name,
6155 const char *environment)
6157 struct policy_handle handle;
6158 bool ret = true;
6159 struct dcerpc_binding_handle *b = p->binding_handle;
6161 if (!test_openprinter(tctx, b, name)) {
6162 return false;
6165 if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
6166 return false;
6169 if (!test_PrinterInfo_SD(tctx, b, &handle)) {
6170 ret = false;
6173 if (!test_GetPrinter(tctx, b, &handle, environment)) {
6174 ret = false;
6177 if (!test_EnumForms_all(tctx, b, &handle, false)) {
6178 ret = false;
6181 if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
6182 ret = false;
6185 if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
6186 ret = false;
6189 if (!test_EnumPrinterData_all(tctx, p, &handle)) {
6190 ret = false;
6193 if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
6194 ret = false;
6197 if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
6198 ret = false;
6201 if (!test_printer_all_keys(tctx, b, &handle)) {
6202 ret = false;
6205 if (!test_PausePrinter(tctx, b, &handle)) {
6206 ret = false;
6209 if (!test_DoPrintTest(tctx, b, &handle)) {
6210 ret = false;
6213 if (!test_ResumePrinter(tctx, b, &handle)) {
6214 ret = false;
6217 if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
6218 ret = false;
6221 if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
6222 ret = false;
6225 if (!torture_setting_bool(tctx, "samba3", false)) {
6226 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
6227 ret = false;
6231 if (!test_ClosePrinter(tctx, b, &handle)) {
6232 ret = false;
6235 return ret;
6238 static bool test_EnumPrinters_old(struct torture_context *tctx,
6239 void *private_data)
6241 struct test_spoolss_context *ctx =
6242 talloc_get_type_abort(private_data, struct test_spoolss_context);
6243 struct spoolss_EnumPrinters r;
6244 NTSTATUS status;
6245 uint16_t levels[] = {1, 2, 4, 5};
6246 int i;
6247 bool ret = true;
6248 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6249 struct dcerpc_binding_handle *b = p->binding_handle;
6251 for (i=0;i<ARRAY_SIZE(levels);i++) {
6252 union spoolss_PrinterInfo *info;
6253 int j;
6254 uint32_t needed;
6255 uint32_t count;
6257 r.in.flags = PRINTER_ENUM_LOCAL;
6258 r.in.server = "";
6259 r.in.level = levels[i];
6260 r.in.buffer = NULL;
6261 r.in.offered = 0;
6262 r.out.needed = &needed;
6263 r.out.count = &count;
6264 r.out.info = &info;
6266 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
6268 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6269 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6271 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6272 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6273 r.in.buffer = &blob;
6274 r.in.offered = needed;
6275 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
6278 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
6280 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6282 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6284 if (!info) {
6285 torture_comment(tctx, "No printers returned\n");
6286 return true;
6289 for (j=0;j<count;j++) {
6290 if (r.in.level == 1) {
6291 char *unc = talloc_strdup(tctx, info[j].info1.name);
6292 char *slash, *name, *full_name;
6293 name = unc;
6294 if (unc[0] == '\\' && unc[1] == '\\') {
6295 unc +=2;
6297 slash = strchr(unc, '\\');
6298 if (slash) {
6299 slash++;
6300 name = slash;
6302 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
6303 dcerpc_server_name(p), name);
6304 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
6305 ret = false;
6307 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
6308 ret = false;
6310 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
6311 ret = false;
6313 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
6314 ret = false;
6320 return ret;
6323 static bool test_EnumPrinters_level(struct torture_context *tctx,
6324 struct dcerpc_binding_handle *b,
6325 uint32_t flags,
6326 const char *servername,
6327 uint32_t level,
6328 uint32_t *count_p,
6329 union spoolss_PrinterInfo **info_p)
6331 struct spoolss_EnumPrinters r;
6332 union spoolss_PrinterInfo *info;
6333 uint32_t needed;
6334 uint32_t count;
6336 r.in.flags = flags;
6337 r.in.server = servername;
6338 r.in.level = level;
6339 r.in.buffer = NULL;
6340 r.in.offered = 0;
6341 r.out.needed = &needed;
6342 r.out.count = &count;
6343 r.out.info = &info;
6345 torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
6346 r.in.server, r.in.level);
6348 torture_assert_ntstatus_ok(tctx,
6349 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6350 "EnumPrinters failed");
6351 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6352 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6353 r.in.buffer = &blob;
6354 r.in.offered = needed;
6355 torture_assert_ntstatus_ok(tctx,
6356 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
6357 "EnumPrinters failed");
6360 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
6362 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
6364 if (count_p) {
6365 *count_p = count;
6367 if (info_p) {
6368 *info_p = info;
6371 return true;
6374 static const char *get_short_printername(struct torture_context *tctx,
6375 const char *name)
6377 const char *short_name;
6379 if (name[0] == '\\' && name[1] == '\\') {
6380 name += 2;
6381 short_name = strchr(name, '\\');
6382 if (short_name) {
6383 return talloc_strdup(tctx, short_name+1);
6387 return name;
6390 static const char *get_full_printername(struct torture_context *tctx,
6391 const char *name)
6393 const char *full_name = talloc_strdup(tctx, name);
6394 char *p;
6396 if (name && name[0] == '\\' && name[1] == '\\') {
6397 name += 2;
6398 p = strchr(name, '\\');
6399 if (p) {
6400 return full_name;
6404 return NULL;
6407 static bool test_OnePrinter_servername(struct torture_context *tctx,
6408 struct dcerpc_pipe *p,
6409 struct dcerpc_binding_handle *b,
6410 const char *servername,
6411 const char *printername)
6413 union spoolss_PrinterInfo info;
6414 const char *short_name = get_short_printername(tctx, printername);
6415 const char *full_name = get_full_printername(tctx, printername);
6417 if (short_name) {
6418 struct policy_handle handle;
6419 torture_assert(tctx,
6420 call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
6421 "failed to open printer");
6423 torture_assert(tctx,
6424 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6425 "failed to get printer info");
6427 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
6428 "unexpected servername");
6429 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
6430 "unexpected printername");
6432 if (info.info2.devmode) {
6433 const char *expected_devicename;
6434 expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
6435 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6436 "unexpected devicemode devicename");
6439 torture_assert(tctx,
6440 test_ClosePrinter(tctx, b, &handle),
6441 "failed to close printer");
6444 if (full_name) {
6445 struct policy_handle handle;
6447 torture_assert(tctx,
6448 call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
6449 "failed to open printer");
6451 torture_assert(tctx,
6452 test_GetPrinter_level(tctx, b, &handle, 2, &info),
6453 "failed to get printer info");
6455 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
6456 "unexpected servername");
6457 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
6458 "unexpected printername");
6460 if (info.info2.devmode) {
6461 const char *expected_devicename;
6462 expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
6463 torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
6464 "unexpected devicemode devicename");
6467 torture_assert(tctx,
6468 test_ClosePrinter(tctx, b, &handle),
6469 "failed to close printer");
6472 return true;
6475 static bool test_EnumPrinters_servername(struct torture_context *tctx,
6476 void *private_data)
6478 struct test_spoolss_context *ctx =
6479 talloc_get_type_abort(private_data, struct test_spoolss_context);
6480 int i;
6481 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6482 struct dcerpc_binding_handle *b = p->binding_handle;
6483 uint32_t count;
6484 union spoolss_PrinterInfo *info;
6485 const char *servername;
6486 uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
6488 torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
6490 servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6492 torture_assert(tctx,
6493 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6494 "failed to enumerate printers");
6496 for (i=0; i < count; i++) {
6498 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
6499 "unexpected servername");
6501 torture_assert(tctx,
6502 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6503 "failed to check printer");
6506 servername = "";
6508 torture_assert(tctx,
6509 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
6510 "failed to enumerate printers");
6512 for (i=0; i < count; i++) {
6514 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
6515 "unexpected servername");
6517 torture_assert(tctx,
6518 test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
6519 "failed to check printer");
6523 return true;
6527 static bool test_GetPrinterDriver(struct torture_context *tctx,
6528 struct dcerpc_binding_handle *b,
6529 struct policy_handle *handle,
6530 const char *driver_name)
6532 struct spoolss_GetPrinterDriver r;
6533 uint32_t needed;
6535 r.in.handle = handle;
6536 r.in.architecture = "W32X86";
6537 r.in.level = 1;
6538 r.in.buffer = NULL;
6539 r.in.offered = 0;
6540 r.out.needed = &needed;
6542 torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
6544 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6545 "failed to call GetPrinterDriver");
6546 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6547 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6548 r.in.buffer = &blob;
6549 r.in.offered = needed;
6550 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
6551 "failed to call GetPrinterDriver");
6554 torture_assert_werr_ok(tctx, r.out.result,
6555 "failed to call GetPrinterDriver");
6557 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6559 return true;
6562 static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
6563 struct dcerpc_binding_handle *b,
6564 struct policy_handle *handle,
6565 const char *driver_name,
6566 const char *architecture,
6567 uint32_t level,
6568 uint32_t client_major_version,
6569 uint32_t client_minor_version,
6570 union spoolss_DriverInfo *info_p,
6571 WERROR *result_p)
6574 struct spoolss_GetPrinterDriver2 r;
6575 uint32_t needed;
6576 uint32_t server_major_version;
6577 uint32_t server_minor_version;
6579 r.in.handle = handle;
6580 r.in.architecture = architecture;
6581 r.in.client_major_version = client_major_version;
6582 r.in.client_minor_version = client_minor_version;
6583 r.in.buffer = NULL;
6584 r.in.offered = 0;
6585 r.in.level = level;
6586 r.out.needed = &needed;
6587 r.out.server_major_version = &server_major_version;
6588 r.out.server_minor_version = &server_minor_version;
6590 torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
6591 driver_name, r.in.level);
6593 torture_assert_ntstatus_ok(tctx,
6594 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6595 "failed to call GetPrinterDriver2");
6596 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
6597 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6598 r.in.buffer = &blob;
6599 r.in.offered = needed;
6600 torture_assert_ntstatus_ok(tctx,
6601 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
6602 "failed to call GetPrinterDriver2");
6605 if (result_p) {
6606 *result_p = r.out.result;
6609 if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
6610 switch (r.in.level) {
6611 case 101:
6612 case 8:
6613 torture_comment(tctx,
6614 "level %d not implemented, not considering as an error\n",
6615 r.in.level);
6616 return true;
6617 default:
6618 break;
6622 torture_assert_werr_ok(tctx, r.out.result,
6623 "failed to call GetPrinterDriver2");
6625 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
6627 if (info_p) {
6628 *info_p = *r.out.info;
6631 return true;
6634 static bool test_GetPrinterDriver2(struct torture_context *tctx,
6635 struct dcerpc_binding_handle *b,
6636 struct policy_handle *handle,
6637 const char *driver_name,
6638 const char *architecture)
6640 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
6641 int i;
6644 for (i=0;i<ARRAY_SIZE(levels);i++) {
6646 torture_assert(tctx,
6647 test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
6648 "");
6651 return true;
6654 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
6655 void *private_data)
6657 struct test_spoolss_context *ctx =
6658 talloc_get_type_abort(private_data, struct test_spoolss_context);
6659 uint16_t levels[] = {1, 2, 3, 4, 5, 6};
6660 int i;
6661 struct dcerpc_pipe *p = ctx->spoolss_pipe;
6662 struct dcerpc_binding_handle *b = p->binding_handle;
6663 const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
6665 for (i=0;i<ARRAY_SIZE(levels);i++) {
6667 uint32_t count;
6668 union spoolss_DriverInfo *info;
6670 torture_assert(tctx,
6671 test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
6672 "failed to enumerate drivers");
6674 if (!info) {
6675 torture_comment(tctx, "No printer drivers returned\n");
6676 break;
6680 return true;
6683 static bool test_DeletePrinter(struct torture_context *tctx,
6684 struct dcerpc_binding_handle *b,
6685 struct policy_handle *handle)
6687 struct spoolss_DeletePrinter r;
6689 torture_comment(tctx, "Testing DeletePrinter\n");
6691 r.in.handle = handle;
6693 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
6694 "failed to delete printer");
6695 torture_assert_werr_ok(tctx, r.out.result,
6696 "failed to delete printer");
6698 return true;
6701 static bool test_EnumPrinters_findname(struct torture_context *tctx,
6702 struct dcerpc_binding_handle *b,
6703 uint32_t flags,
6704 uint32_t level,
6705 const char *name,
6706 bool *found)
6708 struct spoolss_EnumPrinters e;
6709 uint32_t count;
6710 union spoolss_PrinterInfo *info;
6711 uint32_t needed;
6712 int i;
6714 *found = false;
6716 e.in.flags = flags;
6717 e.in.server = NULL;
6718 e.in.level = level;
6719 e.in.buffer = NULL;
6720 e.in.offered = 0;
6721 e.out.count = &count;
6722 e.out.info = &info;
6723 e.out.needed = &needed;
6725 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6726 "failed to enum printers");
6728 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
6729 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
6730 e.in.buffer = &blob;
6731 e.in.offered = needed;
6733 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
6734 "failed to enum printers");
6737 torture_assert_werr_ok(tctx, e.out.result,
6738 "failed to enum printers");
6740 for (i=0; i < count; i++) {
6742 const char *current = NULL;
6743 const char *q;
6745 switch (level) {
6746 case 1:
6747 current = info[i].info1.name;
6748 break;
6751 if (strequal(current, name)) {
6752 *found = true;
6753 break;
6756 q = strrchr(current, '\\');
6757 if (q) {
6758 if (!e.in.server) {
6759 torture_warning(tctx,
6760 "server returns printername %s incl. servername although we did not set servername", current);
6762 q++;
6763 if (strequal(q, name)) {
6764 *found = true;
6765 break;
6770 return true;
6773 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
6774 struct dcerpc_pipe *p,
6775 const char *printername,
6776 bool ex)
6778 WERROR result;
6779 struct spoolss_AddPrinter r;
6780 struct spoolss_AddPrinterEx rex;
6781 struct spoolss_SetPrinterInfoCtr info_ctr;
6782 struct spoolss_SetPrinterInfo1 info1;
6783 struct spoolss_DevmodeContainer devmode_ctr;
6784 struct sec_desc_buf secdesc_ctr;
6785 struct spoolss_UserLevelCtr userlevel_ctr;
6786 struct policy_handle handle;
6787 bool found = false;
6788 struct dcerpc_binding_handle *b = p->binding_handle;
6790 ZERO_STRUCT(devmode_ctr);
6791 ZERO_STRUCT(secdesc_ctr);
6792 ZERO_STRUCT(userlevel_ctr);
6793 ZERO_STRUCT(info1);
6795 torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
6796 ex ? "Ex":"", printername);
6798 /* try to add printer to wellknown printer list (level 1) */
6800 userlevel_ctr.level = 1;
6802 info_ctr.info.info1 = &info1;
6803 info_ctr.level = 1;
6805 rex.in.server = NULL;
6806 rex.in.info_ctr = &info_ctr;
6807 rex.in.devmode_ctr = &devmode_ctr;
6808 rex.in.secdesc_ctr = &secdesc_ctr;
6809 rex.in.userlevel_ctr = &userlevel_ctr;
6810 rex.out.handle = &handle;
6812 r.in.server = NULL;
6813 r.in.info_ctr = &info_ctr;
6814 r.in.devmode_ctr = &devmode_ctr;
6815 r.in.secdesc_ctr = &secdesc_ctr;
6816 r.out.handle = &handle;
6818 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6819 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6820 "failed to add printer");
6821 result = ex ? rex.out.result : r.out.result;
6822 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6823 "unexpected result code");
6825 info1.name = printername;
6826 info1.flags = PRINTER_ATTRIBUTE_SHARED;
6828 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6829 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6830 "failed to add printer");
6831 result = ex ? rex.out.result : r.out.result;
6832 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6833 "unexpected result code");
6835 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6836 better do a real check to see the printer is really there */
6838 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6839 PRINTER_ENUM_NETWORK, 1,
6840 printername,
6841 &found),
6842 "failed to enum printers");
6844 torture_assert(tctx, found, "failed to find newly added printer");
6846 info1.flags = 0;
6848 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6849 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6850 "failed to add printer");
6851 result = ex ? rex.out.result : r.out.result;
6852 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
6853 "unexpected result code");
6855 /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
6856 better do a real check to see the printer has really been removed
6857 from the well known printer list */
6859 found = false;
6861 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
6862 PRINTER_ENUM_NETWORK, 1,
6863 printername,
6864 &found),
6865 "failed to enum printers");
6866 #if 0
6867 torture_assert(tctx, !found, "printer still in well known printer list");
6868 #endif
6869 return true;
6872 static bool test_AddPrinter_normal(struct torture_context *tctx,
6873 struct dcerpc_pipe *p,
6874 struct policy_handle *handle_p,
6875 const char *printername,
6876 const char *drivername,
6877 const char *portname,
6878 struct spoolss_DeviceMode *devmode,
6879 bool ex)
6881 WERROR result;
6882 struct spoolss_AddPrinter r;
6883 struct spoolss_AddPrinterEx rex;
6884 struct spoolss_SetPrinterInfoCtr info_ctr;
6885 struct spoolss_SetPrinterInfo2 info2;
6886 struct spoolss_DevmodeContainer devmode_ctr;
6887 struct sec_desc_buf secdesc_ctr;
6888 struct spoolss_UserLevelCtr userlevel_ctr;
6889 struct policy_handle handle;
6890 bool found = false;
6891 bool existing_printer_deleted = false;
6892 struct dcerpc_binding_handle *b = p->binding_handle;
6894 ZERO_STRUCT(devmode_ctr);
6895 ZERO_STRUCT(secdesc_ctr);
6896 ZERO_STRUCT(userlevel_ctr);
6898 torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
6899 ex ? "Ex":"", printername);
6901 devmode_ctr.devmode = devmode;
6903 userlevel_ctr.level = 1;
6905 rex.in.server = NULL;
6906 rex.in.info_ctr = &info_ctr;
6907 rex.in.devmode_ctr = &devmode_ctr;
6908 rex.in.secdesc_ctr = &secdesc_ctr;
6909 rex.in.userlevel_ctr = &userlevel_ctr;
6910 rex.out.handle = &handle;
6912 r.in.server = NULL;
6913 r.in.info_ctr = &info_ctr;
6914 r.in.devmode_ctr = &devmode_ctr;
6915 r.in.secdesc_ctr = &secdesc_ctr;
6916 r.out.handle = &handle;
6918 again:
6920 /* try to add printer to printer list (level 2) */
6922 ZERO_STRUCT(info2);
6924 info_ctr.info.info2 = &info2;
6925 info_ctr.level = 2;
6927 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6928 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6929 "failed to add printer");
6930 result = ex ? rex.out.result : r.out.result;
6931 torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
6932 "unexpected result code");
6934 info2.printername = printername;
6936 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6937 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6938 "failed to add printer");
6939 result = ex ? rex.out.result : r.out.result;
6941 if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
6942 struct policy_handle printer_handle;
6944 if (existing_printer_deleted) {
6945 torture_fail(tctx, "already deleted printer still existing?");
6948 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
6949 "failed to open printer handle");
6951 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
6952 "failed to delete printer");
6954 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
6955 "failed to close server handle");
6957 existing_printer_deleted = true;
6959 goto again;
6962 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
6963 "unexpected result code");
6965 info2.portname = portname;
6967 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6968 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6969 "failed to add printer");
6970 result = ex ? rex.out.result : r.out.result;
6971 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
6972 "unexpected result code");
6974 info2.drivername = drivername;
6976 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6977 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6978 "failed to add printer");
6979 result = ex ? rex.out.result : r.out.result;
6981 /* w2k8r2 allows to add printer w/o defining printprocessor */
6983 if (!W_ERROR_IS_OK(result)) {
6984 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
6985 "unexpected result code");
6987 info2.printprocessor = "winprint";
6989 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
6990 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
6991 "failed to add printer");
6992 result = ex ? rex.out.result : r.out.result;
6993 torture_assert_werr_ok(tctx, result,
6994 "failed to add printer");
6997 *handle_p = handle;
6999 /* we are paranoid, really check if the printer is there now */
7001 torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
7002 PRINTER_ENUM_LOCAL, 1,
7003 printername,
7004 &found),
7005 "failed to enum printers");
7006 torture_assert(tctx, found, "failed to find newly added printer");
7008 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
7009 dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
7010 "failed to add printer");
7011 result = ex ? rex.out.result : r.out.result;
7012 torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
7013 "unexpected result code");
7015 return true;
7018 static bool test_printer_info(struct torture_context *tctx,
7019 void *private_data)
7021 struct torture_printer_context *t =
7022 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7023 struct dcerpc_pipe *p = t->spoolss_pipe;
7024 struct dcerpc_binding_handle *b = p->binding_handle;
7026 bool ret = true;
7028 if (torture_setting_bool(tctx, "samba3", false)) {
7029 torture_skip(tctx, "skipping printer info cross tests against samba 3");
7032 if (!test_PrinterInfo(tctx, b, &t->handle)) {
7033 ret = false;
7036 if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
7037 ret = false;
7040 return ret;
7043 static bool test_EnumPrinterKey(struct torture_context *tctx,
7044 struct dcerpc_binding_handle *b,
7045 struct policy_handle *handle,
7046 const char *key_name,
7047 const char ***array)
7049 struct spoolss_EnumPrinterKey r;
7050 uint32_t needed = 0;
7051 union spoolss_KeyNames key_buffer;
7052 int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
7053 uint32_t _ndr_size;
7054 int i;
7056 r.in.handle = handle;
7057 r.in.key_name = key_name;
7058 r.out.key_buffer = &key_buffer;
7059 r.out.needed = &needed;
7060 r.out._ndr_size = &_ndr_size;
7062 for (i=0; i < ARRAY_SIZE(offered); i++) {
7064 if (offered[i] < 0 && needed) {
7065 if (needed <= 4) {
7066 continue;
7068 r.in.offered = needed + offered[i];
7069 } else {
7070 r.in.offered = offered[i];
7073 ZERO_STRUCT(key_buffer);
7075 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
7077 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7078 "failed to call EnumPrinterKey");
7079 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
7081 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7082 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7083 _ndr_size, r.in.offered/2));
7085 r.in.offered = needed;
7086 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
7087 "failed to call EnumPrinterKey");
7090 if (offered[i] > 0) {
7091 torture_assert_werr_ok(tctx, r.out.result,
7092 "failed to call EnumPrinterKey");
7095 torture_assert(tctx, (_ndr_size == r.in.offered/2),
7096 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
7097 _ndr_size, r.in.offered/2));
7099 torture_assert(tctx, (*r.out.needed <= r.in.offered),
7100 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
7102 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
7103 talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
7105 if (key_buffer.string_array) {
7106 uint32_t calc_needed = 0;
7107 int s;
7108 for (s=0; key_buffer.string_array[s]; s++) {
7109 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
7111 if (!key_buffer.string_array[0]) {
7112 calc_needed += 2;
7114 calc_needed += 2;
7116 torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
7117 "EnumPrinterKey unexpected size");
7121 if (array) {
7122 *array = key_buffer.string_array;
7125 return true;
7128 bool test_printer_all_keys(struct torture_context *tctx,
7129 struct dcerpc_binding_handle *b,
7130 struct policy_handle *handle)
7132 const char **key_array = NULL;
7133 int i;
7135 torture_comment(tctx, "Testing Printer Keys\n");
7137 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
7138 "failed to call test_EnumPrinterKey");
7140 for (i=0; key_array && key_array[i]; i++) {
7141 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
7142 "failed to call test_EnumPrinterKey");
7144 for (i=0; key_array && key_array[i]; i++) {
7145 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
7146 "failed to call test_EnumPrinterDataEx");
7149 torture_comment(tctx, "Printer Keys test succeeded\n\n");
7151 return true;
7154 static bool test_openprinter_wrap(struct torture_context *tctx,
7155 void *private_data)
7157 struct torture_printer_context *t =
7158 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7159 struct dcerpc_pipe *p = t->spoolss_pipe;
7160 struct dcerpc_binding_handle *b = p->binding_handle;
7161 const char *printername = t->info2.printername;
7163 return test_openprinter(tctx, b, printername);
7166 static bool test_csetprinter(struct torture_context *tctx,
7167 void *private_data)
7169 struct torture_printer_context *t =
7170 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7171 struct dcerpc_pipe *p = t->spoolss_pipe;
7173 const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
7174 const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7175 const char *portname = t->info2.portname;
7177 union spoolss_PrinterInfo info;
7178 struct policy_handle new_handle, new_handle2;
7179 struct dcerpc_binding_handle *b = p->binding_handle;
7181 torture_comment(tctx, "Testing c_setprinter\n");
7183 torture_assert(tctx,
7184 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7185 "failed to get level 0 printer info");
7186 torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
7187 info.info0.c_setprinter);
7189 /* check if c_setprinter on 1st handle increases after a printer has
7190 * been added */
7192 torture_assert(tctx,
7193 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
7194 "failed to add new printer");
7195 torture_assert(tctx,
7196 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
7197 "failed to get level 0 printer info");
7198 torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
7199 info.info0.c_setprinter);
7201 /* check if c_setprinter on new handle increases after a printer has
7202 * been added */
7204 torture_assert(tctx,
7205 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
7206 "failed to get level 0 printer info");
7207 torture_comment(tctx, "csetprinter on created handle: %d\n",
7208 info.info0.c_setprinter);
7210 /* open the new printer and check if c_setprinter increases */
7212 torture_assert(tctx,
7213 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
7214 "failed to open created printer");
7215 torture_assert(tctx,
7216 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
7217 "failed to get level 0 printer info");
7218 torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
7219 info.info0.c_setprinter);
7221 /* cleanup */
7223 torture_assert(tctx,
7224 test_ClosePrinter(tctx, b, &new_handle2),
7225 "failed to close printer");
7226 torture_assert(tctx,
7227 test_DeletePrinter(tctx, b, &new_handle),
7228 "failed to delete new printer");
7230 return true;
7233 static bool compose_local_driver_directory(struct torture_context *tctx,
7234 const char *environment,
7235 const char *local_dir,
7236 const char **path)
7238 char *p;
7240 p = strrchr(local_dir, '/');
7241 if (!p) {
7242 return NULL;
7244 p++;
7246 if (strequal(environment, "Windows x64")) {
7247 if (!strequal(p, "x64")) {
7248 *path = talloc_asprintf(tctx, "%s/x64", local_dir);
7250 } else if (strequal(environment, "Windows NT x86")) {
7251 if (!strequal(p, "i386")) {
7252 *path = talloc_asprintf(tctx, "%s/i386", local_dir);
7254 } else {
7255 torture_assert(tctx, "unknown environment: '%s'\n", environment);
7258 return true;
7261 static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
7262 const char *devicename)
7264 struct spoolss_DeviceMode *r;
7266 r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
7267 if (r == NULL) {
7268 return NULL;
7271 r->devicename = talloc_strdup(r, devicename);
7272 r->specversion = DMSPEC_NT4_AND_ABOVE;
7273 r->driverversion = 0x0600;
7274 r->size = 0x00dc;
7275 r->__driverextra_length = 0;
7276 r->fields = DEVMODE_FORMNAME |
7277 DEVMODE_TTOPTION |
7278 DEVMODE_PRINTQUALITY |
7279 DEVMODE_DEFAULTSOURCE |
7280 DEVMODE_COPIES |
7281 DEVMODE_SCALE |
7282 DEVMODE_PAPERSIZE |
7283 DEVMODE_ORIENTATION;
7284 r->orientation = DMORIENT_PORTRAIT;
7285 r->papersize = DMPAPER_LETTER;
7286 r->paperlength = 0;
7287 r->paperwidth = 0;
7288 r->scale = 100;
7289 r->copies = 55;
7290 r->defaultsource = DMBIN_FORMSOURCE;
7291 r->printquality = DMRES_HIGH;
7292 r->color = DMRES_MONOCHROME;
7293 r->duplex = DMDUP_SIMPLEX;
7294 r->yresolution = 0;
7295 r->ttoption = DMTT_SUBDEV;
7296 r->collate = DMCOLLATE_FALSE;
7297 r->formname = talloc_strdup(r, "Letter");
7299 return r;
7302 static bool test_architecture_buffer(struct torture_context *tctx,
7303 void *private_data)
7305 struct test_spoolss_context *ctx =
7306 talloc_get_type_abort(private_data, struct test_spoolss_context);
7308 struct spoolss_OpenPrinterEx r;
7309 struct spoolss_UserLevel1 u1;
7310 struct policy_handle handle;
7311 uint32_t architectures[] = {
7312 PROCESSOR_ARCHITECTURE_INTEL,
7313 PROCESSOR_ARCHITECTURE_IA64,
7314 PROCESSOR_ARCHITECTURE_AMD64
7316 uint32_t needed[3];
7317 int i;
7318 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7319 struct dcerpc_binding_handle *b = p->binding_handle;
7321 for (i=0; i < ARRAY_SIZE(architectures); i++) {
7323 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
7325 u1.size = 0;
7326 u1.client = NULL;
7327 u1.user = NULL;
7328 u1.build = 0;
7329 u1.major = 3;
7330 u1.minor = 0;
7331 u1.processor = architectures[i];
7333 r.in.printername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7334 r.in.datatype = NULL;
7335 r.in.devmode_ctr.devmode= NULL;
7336 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7337 r.in.level = 1;
7338 r.in.userlevel.level1 = &u1;
7339 r.out.handle = &handle;
7341 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
7342 torture_assert_werr_ok(tctx, r.out.result, "");
7345 struct spoolss_EnumPrinters e;
7346 uint32_t count;
7347 union spoolss_PrinterInfo *info;
7349 e.in.flags = PRINTER_ENUM_LOCAL;
7350 e.in.server = NULL;
7351 e.in.level = 2;
7352 e.in.buffer = NULL;
7353 e.in.offered = 0;
7354 e.out.count = &count;
7355 e.out.info = &info;
7356 e.out.needed = &needed[i];
7358 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
7359 #if 0
7360 torture_comment(tctx, "needed was %d\n", needed[i]);
7361 #endif
7364 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
7367 for (i=1; i < ARRAY_SIZE(architectures); i++) {
7368 if (needed[i-1] != needed[i]) {
7369 torture_fail(tctx,
7370 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
7371 needed[i-1], architectures[i-1], needed[i], architectures[i]));
7375 return true;
7378 static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
7379 void *private_data)
7381 struct test_spoolss_context *ctx =
7382 talloc_get_type_abort(private_data, struct test_spoolss_context);
7383 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7384 struct dcerpc_binding_handle *b = p->binding_handle;
7386 return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
7389 static bool test_PrintServer_Forms(struct torture_context *tctx,
7390 void *private_data)
7392 struct test_spoolss_context *ctx =
7393 talloc_get_type_abort(private_data, struct test_spoolss_context);
7394 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7395 struct dcerpc_binding_handle *b = p->binding_handle;
7397 return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
7400 static bool test_PrintServer_EnumForms(struct torture_context *tctx,
7401 void *private_data)
7403 struct test_spoolss_context *ctx =
7404 talloc_get_type_abort(private_data, struct test_spoolss_context);
7405 struct dcerpc_pipe *p = ctx->spoolss_pipe;
7406 struct dcerpc_binding_handle *b = p->binding_handle;
7408 return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
7411 static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
7413 NTSTATUS status;
7415 status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
7417 torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
7419 torture_assert(tctx,
7420 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
7421 "failed to open printserver");
7422 torture_assert(tctx,
7423 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
7424 "failed to get environment");
7426 return true;
7429 static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
7431 struct test_spoolss_context *t;
7433 *data = t = talloc_zero(tctx, struct test_spoolss_context);
7435 return torture_rpc_spoolss_setup_common(tctx, t);
7438 static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
7440 test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
7442 return true;
7445 static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
7447 struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
7448 bool ret;
7450 ret = torture_rpc_spoolss_teardown_common(tctx, t);
7451 talloc_free(t);
7453 return ret;
7456 static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
7458 struct dcerpc_pipe *p;
7459 struct dcerpc_binding_handle *b;
7460 const char *server_name_slash;
7461 const char *driver_name;
7462 const char *printer_name;
7463 const char *port_name;
7465 torture_assert_ntstatus_ok(tctx,
7466 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
7467 "Error connecting to server");
7469 p = t->spoolss_pipe;
7470 b = p->binding_handle;
7471 server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
7473 t->driver.info8.version = SPOOLSS_DRIVER_VERSION_200X;
7474 t->driver.info8.driver_name = TORTURE_DRIVER;
7475 t->driver.info8.driver_path = "pscript5.dll";
7476 t->driver.info8.data_file = "cups6.ppd";
7477 t->driver.info8.config_file = "ps5ui.dll";
7478 t->driver.info8.help_file = "pscript.hlp";
7479 t->driver.info8.default_datatype = "RAW";
7480 t->driver.info8.dependent_files = talloc_zero(t, struct spoolss_StringArray);
7481 t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
7482 t->driver.info8.dependent_files->string[0] = "pscript5.dll";
7483 t->driver.info8.dependent_files->string[1] = "cups6.ppd";
7484 t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
7485 t->driver.info8.dependent_files->string[3] = "pscript.hlp";
7486 t->driver.info8.dependent_files->string[4] = "pscript.ntf";
7487 t->driver.info8.dependent_files->string[5] = "cups6.ini";
7488 t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
7489 t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
7491 t->driver.local.driver_directory= "/usr/share/cups/drivers";
7493 t->info2.drivername = "Microsoft XPS Document Writer";
7494 t->info2.portname = "LPT1:";
7496 printer_name = t->info2.printername;
7497 port_name = t->info2.portname;
7499 torture_assert(tctx,
7500 fillup_printserver_info(tctx, p, &t->driver),
7501 "failed to fillup printserver info");
7503 t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
7505 torture_assert(tctx,
7506 compose_local_driver_directory(tctx, t->driver.remote.environment,
7507 t->driver.local.driver_directory,
7508 &t->driver.local.driver_directory),
7509 "failed to compose local driver directory");
7511 if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
7512 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
7513 t->info2.drivername, t->driver.remote.environment);
7514 t->have_driver = true;
7515 goto try_add;
7518 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
7519 t->info2.drivername, t->driver.remote.environment);
7520 torture_comment(tctx, "trying to upload own driver\n");
7522 if (!directory_exist(t->driver.local.driver_directory)) {
7523 torture_warning(tctx, "no local driver is available!");
7524 t->have_driver = false;
7525 goto try_add;
7528 torture_assert(tctx,
7529 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
7530 "failed to upload printer driver");
7532 torture_assert(tctx,
7533 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
7534 "failed to add driver");
7536 t->added_driver = true;
7537 t->have_driver = true;
7539 try_add:
7540 driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7542 if (t->wellknown) {
7543 torture_assert(tctx,
7544 test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
7545 "failed to add wellknown printer");
7546 } else {
7547 torture_assert(tctx,
7548 test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
7549 "failed to add printer");
7552 return true;
7555 static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
7557 struct torture_printer_context *t;
7559 *data = t = talloc_zero(tctx, struct torture_printer_context);
7561 t->ex = false;
7562 t->wellknown = false;
7563 t->info2.printername = TORTURE_PRINTER;
7564 t->devmode = NULL;
7566 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7569 static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
7571 struct torture_printer_context *t;
7573 *data = t = talloc_zero(tctx, struct torture_printer_context);
7575 t->ex = true;
7576 t->wellknown = false;
7577 t->info2.printername = TORTURE_PRINTER_EX;
7578 t->devmode = NULL;
7580 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7583 static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
7585 struct torture_printer_context *t;
7587 *data = t = talloc_zero(tctx, struct torture_printer_context);
7589 t->ex = false;
7590 t->wellknown = true;
7591 t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
7592 t->devmode = NULL;
7594 /* FIXME */
7595 if (t->wellknown) {
7596 torture_skip(tctx, "skipping AddPrinter level 1");
7599 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7602 static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
7604 struct torture_printer_context *t;
7606 *data = t = talloc_zero(tctx, struct torture_printer_context);
7608 t->ex = true;
7609 t->wellknown = true;
7610 t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
7611 t->devmode = NULL;
7613 /* FIXME */
7614 if (t->wellknown) {
7615 torture_skip(tctx, "skipping AddPrinterEx level 1");
7618 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7621 static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
7623 struct torture_printer_context *t;
7625 *data = t = talloc_zero(tctx, struct torture_printer_context);
7627 t->ex = true;
7628 t->wellknown = false;
7629 t->info2.printername = TORTURE_PRINTER_EX;
7630 t->devmode = torture_devicemode(t, TORTURE_PRINTER_EX);
7632 return torture_rpc_spoolss_printer_setup_common(tctx, t);
7635 static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
7637 bool found = false;
7638 struct dcerpc_pipe *p = t->spoolss_pipe;
7639 struct dcerpc_binding_handle *b;
7640 const char *printer_name = t->info2.printername;
7642 if (t->added_driver) {
7643 torture_assert(tctx,
7644 remove_printer_driver(tctx, dcerpc_server_name(t->spoolss_pipe), &t->driver),
7645 "failed to remove printer driver");
7648 if (p) {
7649 b = p->binding_handle;
7652 if (!t->wellknown) {
7653 torture_assert(tctx,
7654 test_DeletePrinter(tctx, b, &t->handle),
7655 "failed to delete printer");
7657 torture_assert(tctx,
7658 test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
7659 printer_name, &found),
7660 "failed to enumerate printers");
7662 torture_assert(tctx, !found, "deleted printer still there");
7665 return true;
7668 static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
7670 struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
7671 bool ret;
7673 ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
7674 talloc_free(t);
7676 return ret;
7679 static bool test_print_test(struct torture_context *tctx,
7680 void *private_data)
7682 struct torture_printer_context *t =
7683 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7684 struct dcerpc_pipe *p = t->spoolss_pipe;
7685 struct dcerpc_binding_handle *b = p->binding_handle;
7687 torture_assert(tctx,
7688 test_PausePrinter(tctx, b, &t->handle),
7689 "failed to pause printer");
7691 torture_assert(tctx,
7692 test_DoPrintTest(tctx, b, &t->handle),
7693 "failed to do print test");
7695 torture_assert(tctx,
7696 test_ResumePrinter(tctx, b, &t->handle),
7697 "failed to resume printer");
7699 return true;
7702 static bool test_print_test_extended(struct torture_context *tctx,
7703 void *private_data)
7705 struct torture_printer_context *t =
7706 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7707 struct dcerpc_pipe *p = t->spoolss_pipe;
7708 struct dcerpc_binding_handle *b = p->binding_handle;
7709 bool ret = true;
7711 torture_assert(tctx,
7712 test_PausePrinter(tctx, b, &t->handle),
7713 "failed to pause printer");
7715 ret = test_DoPrintTest_extended(tctx, b, &t->handle);
7716 if (ret == false) {
7717 torture_comment(tctx, "WARNING! failed to do extended print test\n");
7718 if (torture_setting_bool(tctx, "samba3", false)) {
7719 torture_comment(tctx, "non-critical for samba3\n");
7720 ret = true;
7721 tctx->last_result = TORTURE_SKIP;
7725 torture_assert(tctx,
7726 test_ResumePrinter(tctx, b, &t->handle),
7727 "failed to resume printer");
7729 return ret;
7732 /* use smbd file IO to spool a print job */
7733 static bool test_print_test_smbd(struct torture_context *tctx,
7734 void *private_data)
7736 struct torture_printer_context *t =
7737 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7738 struct dcerpc_pipe *p = t->spoolss_pipe;
7739 struct dcerpc_binding_handle *b = p->binding_handle;
7740 NTSTATUS status;
7741 uint32_t count;
7742 union spoolss_JobInfo *info = NULL;
7743 int i;
7745 struct smb2_tree *tree;
7746 struct smb2_handle job_h;
7747 struct cli_credentials *credentials = cmdline_credentials;
7748 struct smbcli_options options;
7749 TALLOC_CTX *mem_ctx = talloc_new(tctx);
7750 const char *share = t->info2.printername;
7752 torture_comment(tctx, "Testing smbd job spooling\n");
7753 lpcfg_smbcli_options(tctx->lp_ctx, &options);
7755 status = smb2_connect(tctx,
7756 torture_setting_string(tctx, "host", NULL),
7757 lpcfg_smb_ports(tctx->lp_ctx),
7758 share,
7759 lpcfg_resolve_context(tctx->lp_ctx),
7760 credentials,
7761 &tree,
7762 tctx->ev,
7763 &options,
7764 lpcfg_socket_options(tctx->lp_ctx),
7765 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
7766 if (!NT_STATUS_IS_OK(status)) {
7767 printf("Failed to connect to SMB2 printer %s - %s\n",
7768 share, nt_errstr(status));
7769 return false;
7772 status = torture_smb2_testfile(tree, "smbd_spooler_job", &job_h);
7773 torture_assert_ntstatus_ok(tctx, status, "smbd spool job create");
7775 status = smb2_util_write(tree, job_h, "exciting print job data", 0,
7776 sizeof("exciting print job data"));
7777 torture_assert_ntstatus_ok(tctx, status, "smbd spool job write");
7779 /* check back end spoolss job was created */
7780 torture_assert(tctx,
7781 test_EnumJobs_args(tctx, b, &t->handle, 1, &count, &info),
7782 "EnumJobs level 1 failed");
7784 for (i = 0; i < count; i++) {
7785 if (!strcmp(info[i].info1.document_name, "smbd_spooler_job")) {
7786 break;
7789 torture_assert(tctx, (i != count), "smbd_spooler_job not found");
7791 status = smb2_util_close(tree, job_h);
7792 torture_assert_ntstatus_ok(tctx, status, "smbd spool job close");
7794 /* disconnect from printer share */
7795 talloc_free(mem_ctx);
7797 return true;
7800 static bool test_printer_sd(struct torture_context *tctx,
7801 void *private_data)
7803 struct torture_printer_context *t =
7804 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7805 struct dcerpc_pipe *p = t->spoolss_pipe;
7806 struct dcerpc_binding_handle *b = p->binding_handle;
7808 torture_assert(tctx,
7809 test_PrinterInfo_SD(tctx, b, &t->handle),
7810 "failed to test security descriptors");
7812 return true;
7815 static bool test_printer_dm(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_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
7824 "failed to test devicemodes");
7826 return true;
7829 static bool test_printer_info_winreg(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_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
7838 "failed to test printer info winreg");
7840 return true;
7843 static bool test_printer_change_id(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_ChangeID(tctx, p, &t->handle),
7852 "failed to test change id");
7854 return true;
7857 static bool test_printer_keys(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;
7863 struct dcerpc_binding_handle *b = p->binding_handle;
7865 torture_assert(tctx,
7866 test_printer_all_keys(tctx, b, &t->handle),
7867 "failed to test printer keys");
7869 return true;
7872 static bool test_printer_data_consistency(struct torture_context *tctx,
7873 void *private_data)
7875 struct torture_printer_context *t =
7876 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7877 struct dcerpc_pipe *p = t->spoolss_pipe;
7879 torture_assert(tctx,
7880 test_EnumPrinterData_consistency(tctx, p, &t->handle),
7881 "failed to test printer data consistency");
7883 return true;
7886 static bool test_printer_data_keys(struct torture_context *tctx,
7887 void *private_data)
7889 struct torture_printer_context *t =
7890 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7891 struct dcerpc_pipe *p = t->spoolss_pipe;
7893 torture_assert(tctx,
7894 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
7895 "failed to test printer data keys");
7897 return true;
7900 static bool test_printer_data_values(struct torture_context *tctx,
7901 void *private_data)
7903 struct torture_printer_context *t =
7904 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7905 struct dcerpc_pipe *p = t->spoolss_pipe;
7907 torture_assert(tctx,
7908 test_SetPrinterDataEx_values(tctx, p, &t->handle),
7909 "failed to test printer data values");
7911 return true;
7914 static bool test_printer_data_set(struct torture_context *tctx,
7915 void *private_data)
7917 struct torture_printer_context *t =
7918 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7919 struct dcerpc_pipe *p = t->spoolss_pipe;
7921 torture_assert(tctx,
7922 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
7923 "failed to test printer data set");
7925 return true;
7928 static bool test_printer_data_winreg(struct torture_context *tctx,
7929 void *private_data)
7931 struct torture_printer_context *t =
7932 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7933 struct dcerpc_pipe *p = t->spoolss_pipe;
7935 torture_assert(tctx,
7936 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
7937 "failed to test printer data winreg");
7939 return true;
7942 static bool test_printer_data_dsspooler(struct torture_context *tctx,
7943 void *private_data)
7945 struct torture_printer_context *t =
7946 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7947 struct dcerpc_pipe *p = t->spoolss_pipe;
7949 torture_assert(tctx,
7950 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
7951 "failed to test printer data winreg dsspooler");
7953 return true;
7956 static bool test_driver_info_winreg(struct torture_context *tctx,
7957 void *private_data)
7959 struct torture_printer_context *t =
7960 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
7961 struct dcerpc_pipe *p = t->spoolss_pipe;
7962 const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
7964 if (!t->have_driver) {
7965 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
7968 torture_assert(tctx,
7969 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
7970 "failed to test driver info winreg");
7972 return true;
7975 void torture_tcase_printer(struct torture_tcase *tcase)
7977 torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
7978 torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
7979 torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
7980 torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
7981 torture_tcase_add_simple_test(tcase, "print_test_smbd", test_print_test_smbd);
7982 torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
7983 torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
7984 torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
7985 torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
7986 torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
7987 torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
7988 torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
7989 torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
7990 torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
7991 torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
7992 torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
7993 torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
7994 torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
7995 torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
7998 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
8000 struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
8001 struct torture_tcase *tcase;
8003 tcase = torture_suite_add_tcase(suite, "addprinter");
8005 torture_tcase_set_fixture(tcase,
8006 torture_rpc_spoolss_printer_setup,
8007 torture_rpc_spoolss_printer_teardown);
8009 torture_tcase_printer(tcase);
8011 tcase = torture_suite_add_tcase(suite, "addprinterex");
8013 torture_tcase_set_fixture(tcase,
8014 torture_rpc_spoolss_printerex_setup,
8015 torture_rpc_spoolss_printer_teardown);
8017 torture_tcase_printer(tcase);
8019 tcase = torture_suite_add_tcase(suite, "addprinterwkn");
8021 torture_tcase_set_fixture(tcase,
8022 torture_rpc_spoolss_printerwkn_setup,
8023 torture_rpc_spoolss_printer_teardown);
8025 tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
8027 torture_tcase_set_fixture(tcase,
8028 torture_rpc_spoolss_printerexwkn_setup,
8029 torture_rpc_spoolss_printer_teardown);
8031 #if 0
8032 /* test is not correct */
8033 tcase = torture_suite_add_tcase(suite, "addprinterdm");
8035 torture_tcase_set_fixture(tcase,
8036 torture_rpc_spoolss_printerdm_setup,
8037 torture_rpc_spoolss_printer_teardown);
8039 torture_tcase_printer(tcase);
8040 #endif
8041 return suite;
8044 struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
8046 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
8047 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
8049 torture_tcase_set_fixture(tcase,
8050 torture_rpc_spoolss_setup,
8051 torture_rpc_spoolss_teardown);
8053 torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
8054 torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
8055 torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
8056 torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
8057 torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
8058 torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
8059 torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
8060 torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
8061 torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
8062 torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
8063 torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
8064 torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
8065 torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
8066 torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcDataTypes);
8067 torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
8068 torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
8069 torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
8070 torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
8071 torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
8072 torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
8074 torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
8076 return suite;
8079 static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
8080 struct dcerpc_binding_handle *b,
8081 const char *server,
8082 const char *environment,
8083 const char **dir_p)
8085 struct spoolss_GetPrinterDriverDirectory r;
8086 uint32_t needed;
8088 r.in.server = server;
8089 r.in.environment = environment;
8090 r.in.level = 1;
8091 r.in.buffer = NULL;
8092 r.in.offered = 0;
8093 r.out.needed = &needed;
8095 torture_assert_ntstatus_ok(tctx,
8096 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8097 "failed to query driver directory");
8099 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
8100 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
8101 r.in.buffer = &blob;
8102 r.in.offered = needed;
8104 torture_assert_ntstatus_ok(tctx,
8105 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
8106 "failed to query driver directory");
8109 torture_assert_werr_ok(tctx, r.out.result,
8110 "failed to query driver directory");
8112 if (dir_p) {
8113 *dir_p = r.out.info->info1.directory_name;
8116 return true;
8119 static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8121 if (info_ctr == NULL) {
8122 return NULL;
8125 switch (info_ctr->level) {
8126 case 1:
8127 return info_ctr->info.info1->driver_name;
8128 case 2:
8129 return info_ctr->info.info2->driver_name;
8130 case 3:
8131 return info_ctr->info.info3->driver_name;
8132 case 4:
8133 return info_ctr->info.info4->driver_name;
8134 case 6:
8135 return info_ctr->info.info6->driver_name;
8136 case 8:
8137 return info_ctr->info.info8->driver_name;
8138 default:
8139 return NULL;
8143 static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
8145 if (info_ctr == NULL) {
8146 return NULL;
8149 switch (info_ctr->level) {
8150 case 2:
8151 return info_ctr->info.info2->architecture;
8152 case 3:
8153 return info_ctr->info.info3->architecture;
8154 case 4:
8155 return info_ctr->info.info4->architecture;
8156 case 6:
8157 return info_ctr->info.info6->architecture;
8158 case 8:
8159 return info_ctr->info.info8->architecture;
8160 default:
8161 return NULL;
8166 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
8167 struct dcerpc_binding_handle *b,
8168 const char *servername,
8169 struct spoolss_AddDriverInfoCtr *info_ctr,
8170 WERROR expected_result)
8172 struct spoolss_AddPrinterDriver r;
8173 const char *drivername = get_driver_from_info(info_ctr);
8174 const char *environment = get_environment_from_info(info_ctr);
8176 r.in.servername = servername;
8177 r.in.info_ctr = info_ctr;
8179 torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
8180 drivername, info_ctr->level, environment);
8182 torture_assert_ntstatus_ok(tctx,
8183 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
8184 "spoolss_AddPrinterDriver failed");
8185 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8186 "spoolss_AddPrinterDriver failed with unexpected result");
8188 return true;
8192 static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
8193 struct dcerpc_binding_handle *b,
8194 const char *servername,
8195 struct spoolss_AddDriverInfoCtr *info_ctr,
8196 uint32_t flags,
8197 WERROR expected_result)
8199 struct spoolss_AddPrinterDriverEx r;
8200 const char *drivername = get_driver_from_info(info_ctr);
8201 const char *environment = get_environment_from_info(info_ctr);
8203 r.in.servername = servername;
8204 r.in.info_ctr = info_ctr;
8205 r.in.flags = flags;
8207 torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
8208 drivername, info_ctr->level, environment);
8210 torture_assert_ntstatus_ok(tctx,
8211 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
8212 "AddPrinterDriverEx failed");
8213 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8214 "AddPrinterDriverEx failed with unexpected result");
8216 return true;
8219 #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
8220 if (path && strlen(path)) {\
8221 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
8224 static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
8225 struct dcerpc_binding_handle *b,
8226 const char *server_name,
8227 struct spoolss_AddDriverInfo8 *r,
8228 uint32_t flags,
8229 bool ex,
8230 const char *remote_driver_dir)
8232 struct spoolss_AddDriverInfoCtr info_ctr;
8233 struct spoolss_AddDriverInfo1 info1;
8235 ZERO_STRUCT(info1);
8237 info_ctr.level = 1;
8238 info_ctr.info.info1 = &info1;
8240 if (ex) {
8241 torture_assert(tctx,
8242 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8243 "failed to test AddPrinterDriverEx level 1");
8244 } else {
8245 torture_assert(tctx,
8246 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8247 "failed to test AddPrinterDriver level 1");
8250 info1.driver_name = r->driver_name;
8252 if (ex) {
8253 torture_assert(tctx,
8254 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_UNKNOWN_LEVEL),
8255 "failed to test AddPrinterDriverEx level 1");
8256 } else {
8257 torture_assert(tctx,
8258 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8259 "failed to test AddPrinterDriver level 1");
8262 return true;
8265 static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
8266 struct dcerpc_binding_handle *b,
8267 const char *server_name,
8268 struct spoolss_AddDriverInfo8 *r,
8269 uint32_t flags,
8270 bool ex,
8271 const char *remote_driver_dir)
8273 struct spoolss_AddDriverInfoCtr info_ctr;
8274 struct spoolss_AddDriverInfo2 info2;
8275 union spoolss_DriverInfo info;
8277 ZERO_STRUCT(info2);
8279 info_ctr.level = 2;
8280 info_ctr.info.info2 = &info2;
8282 if (ex) {
8283 torture_assert(tctx,
8284 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8285 "failed to test AddPrinterDriverEx level 2");
8286 } else {
8287 torture_assert(tctx,
8288 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8289 "failed to test AddPrinterDriver level 2");
8292 info2.driver_name = r->driver_name;
8294 if (ex) {
8295 torture_assert(tctx,
8296 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8297 "failed to test AddPrinterDriverEx level 2");
8298 } else {
8299 torture_assert(tctx,
8300 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8301 "failed to test AddPrinterDriver level 2");
8304 info2.version = r->version;
8306 if (ex) {
8307 torture_assert(tctx,
8308 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8309 "failed to test AddPrinterDriverEx level 2");
8310 } else {
8311 torture_assert(tctx,
8312 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8313 "failed to test AddPrinterDriver level 2");
8316 info2.architecture = r->architecture;
8318 if (ex) {
8319 torture_assert(tctx,
8320 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8321 "failed to test AddPrinterDriverEx level 2");
8322 } else {
8323 torture_assert(tctx,
8324 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8325 "failed to test AddPrinterDriver level 2");
8328 info2.driver_path = r->driver_path;
8330 if (ex) {
8331 torture_assert(tctx,
8332 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8333 "failed to test AddPrinterDriverEx level 2");
8334 } else {
8335 torture_assert(tctx,
8336 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8337 "failed to test AddPrinterDriver level 2");
8340 info2.data_file = r->data_file;
8342 if (ex) {
8343 torture_assert(tctx,
8344 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAM),
8345 "failed to test AddPrinterDriverEx level 2");
8346 } else {
8347 torture_assert(tctx,
8348 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAM),
8349 "failed to test AddPrinterDriver level 2");
8352 info2.config_file = r->config_file;
8354 if (ex) {
8355 torture_assert(tctx,
8356 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAM),
8357 "failed to test AddPrinterDriverEx");
8360 if (ex) {
8361 torture_assert(tctx,
8362 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8363 "failed to test AddPrinterDriverEx level 2");
8364 } else {
8365 torture_assert(tctx,
8366 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8367 "failed to test AddPrinterDriver level 2");
8370 torture_assert(tctx,
8371 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
8372 "failed to find added printer driver");
8374 if (remote_driver_dir) {
8375 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
8376 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
8377 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
8380 return true;
8383 static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
8384 struct dcerpc_binding_handle *b,
8385 const char *server_name,
8386 struct spoolss_AddDriverInfo8 *r,
8387 uint32_t flags,
8388 bool ex,
8389 const char *remote_driver_dir)
8391 struct spoolss_AddDriverInfoCtr info_ctr;
8392 struct spoolss_AddDriverInfo3 info3;
8393 union spoolss_DriverInfo info;
8395 info3.driver_name = r->driver_name;
8396 info3.version = r->version;
8397 info3.architecture = r->architecture;
8398 info3.driver_path = r->driver_path;
8399 info3.data_file = r->data_file;
8400 info3.config_file = r->config_file;
8401 info3.help_file = r->help_file;
8402 info3.monitor_name = r->monitor_name;
8403 info3.default_datatype = r->default_datatype;
8404 info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8405 info3.dependent_files = r->dependent_files;
8407 info_ctr.level = 3;
8408 info_ctr.info.info3 = &info3;
8410 if (ex) {
8411 torture_assert(tctx,
8412 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8413 "failed to test AddPrinterDriverEx level 3");
8414 } else {
8415 torture_assert(tctx,
8416 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8417 "failed to test AddPrinterDriver level 3");
8420 torture_assert(tctx,
8421 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
8422 "failed to find added printer driver");
8424 if (remote_driver_dir) {
8425 int i;
8426 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
8427 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
8428 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
8429 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
8430 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
8431 ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
8435 return true;
8438 static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
8439 struct dcerpc_binding_handle *b,
8440 const char *server_name,
8441 struct spoolss_AddDriverInfo8 *r,
8442 uint32_t flags,
8443 bool ex,
8444 const char *remote_driver_dir)
8446 struct spoolss_AddDriverInfoCtr info_ctr;
8447 struct spoolss_AddDriverInfo4 info4;
8448 union spoolss_DriverInfo info;
8450 info4.version = r->version;
8451 info4.driver_name = r->driver_name;
8452 info4.architecture = r->architecture;
8453 info4.driver_path = r->driver_path;
8454 info4.data_file = r->data_file;
8455 info4.config_file = r->config_file;
8456 info4.help_file = r->help_file;
8457 info4.monitor_name = r->monitor_name;
8458 info4.default_datatype = r->default_datatype;
8459 info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8460 info4.dependent_files = r->dependent_files;
8461 info4._ndr_size_previous_names = r->_ndr_size_previous_names;
8462 info4.previous_names = r->previous_names;
8464 info_ctr.level = 4;
8465 info_ctr.info.info4 = &info4;
8467 if (ex) {
8468 torture_assert(tctx,
8469 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8470 "failed to test AddPrinterDriverEx level 4");
8471 } else {
8472 torture_assert(tctx,
8473 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
8474 "failed to test AddPrinterDriver level 4");
8477 torture_assert(tctx,
8478 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
8479 "failed to find added printer driver");
8481 if (remote_driver_dir) {
8482 int i;
8483 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
8484 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
8485 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
8486 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
8487 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
8488 ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
8492 return true;
8495 static bool test_AddPrinterDriver_args_level_6(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 struct spoolss_AddDriverInfo6 info6;
8505 union spoolss_DriverInfo info;
8507 info6.version = r->version;
8508 info6.driver_name = r->driver_name;
8509 info6.architecture = r->architecture;
8510 info6.driver_path = r->driver_path;
8511 info6.data_file = r->data_file;
8512 info6.config_file = r->config_file;
8513 info6.help_file = r->help_file;
8514 info6.monitor_name = r->monitor_name;
8515 info6.default_datatype = r->default_datatype;
8516 info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
8517 info6.dependent_files = r->dependent_files;
8518 info6._ndr_size_previous_names = r->_ndr_size_previous_names;
8519 info6.previous_names = r->previous_names;
8520 info6.driver_date = r->driver_date;
8521 info6.driver_version = r->driver_version;
8522 info6.manufacturer_name = r->manufacturer_name;
8523 info6.manufacturer_url = r->manufacturer_url;
8524 info6.hardware_id = r->hardware_id;
8525 info6.provider = r->provider;
8527 info_ctr.level = 6;
8528 info_ctr.info.info6 = &info6;
8530 if (ex) {
8531 torture_assert(tctx,
8532 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8533 "failed to test AddPrinterDriverEx level 6");
8534 } else {
8535 torture_assert(tctx,
8536 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8537 "failed to test AddPrinterDriver level 6");
8540 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8542 if (!ex) {
8543 return true;
8546 torture_assert(tctx,
8547 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
8548 "failed to find added printer driver");
8550 if (remote_driver_dir) {
8551 int i;
8552 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
8553 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
8554 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
8555 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
8556 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
8557 ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
8561 torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
8562 torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
8564 return true;
8567 static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
8568 struct dcerpc_binding_handle *b,
8569 const char *server_name,
8570 struct spoolss_AddDriverInfo8 *r,
8571 uint32_t flags,
8572 bool ex,
8573 const char *remote_driver_dir)
8575 struct spoolss_AddDriverInfoCtr info_ctr;
8576 union spoolss_DriverInfo info;
8578 info_ctr.level = 8;
8579 info_ctr.info.info8 = r;
8581 if (ex) {
8582 torture_assert(tctx,
8583 test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
8584 "failed to test AddPrinterDriverEx level 8");
8585 } else {
8586 torture_assert(tctx,
8587 test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_UNKNOWN_LEVEL),
8588 "failed to test AddPrinterDriver level 8");
8591 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8593 if (!ex) {
8594 return true;
8597 torture_assert(tctx,
8598 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
8599 "failed to find added printer driver");
8601 if (remote_driver_dir) {
8602 int i;
8603 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
8604 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
8605 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
8606 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
8607 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
8608 ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
8612 torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
8613 torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
8615 return true;
8618 #undef ASSERT_DRIVER_PATH
8620 static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
8621 struct dcerpc_binding_handle *b,
8622 const char *server,
8623 const char *driver,
8624 const char *environment,
8625 WERROR expected_result)
8627 struct spoolss_DeletePrinterDriver r;
8629 r.in.server = server;
8630 r.in.architecture = environment;
8631 r.in.driver = driver;
8633 torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
8635 torture_assert_ntstatus_ok(tctx,
8636 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
8637 "DeletePrinterDriver failed");
8638 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8639 "DeletePrinterDriver failed with unexpected result");
8641 return true;
8644 static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
8645 struct dcerpc_binding_handle *b,
8646 const char *server,
8647 const char *driver,
8648 const char *environment,
8649 uint32_t delete_flags,
8650 uint32_t version,
8651 WERROR expected_result)
8653 struct spoolss_DeletePrinterDriverEx r;
8655 r.in.server = server;
8656 r.in.architecture = environment;
8657 r.in.driver = driver;
8658 r.in.delete_flags = delete_flags;
8659 r.in.version = version;
8661 torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
8663 torture_assert_ntstatus_ok(tctx,
8664 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
8665 "DeletePrinterDriverEx failed");
8666 torture_assert_werr_equal(tctx, r.out.result, expected_result,
8667 "DeletePrinterDriverEx failed with unexpected result");
8669 return true;
8672 static bool test_DeletePrinterDriver(struct torture_context *tctx,
8673 struct dcerpc_binding_handle *b,
8674 const char *server_name,
8675 const char *driver,
8676 const char *environment)
8678 torture_assert(tctx,
8679 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
8680 "failed to delete driver");
8682 torture_assert(tctx,
8683 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
8684 "failed to delete driver");
8686 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8687 torture_fail(tctx, "deleted driver still enumerated");
8690 torture_assert(tctx,
8691 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
8692 "2nd delete failed");
8694 return true;
8697 static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
8698 struct dcerpc_binding_handle *b,
8699 const char *server_name,
8700 const char *driver,
8701 const char *environment,
8702 uint32_t delete_flags,
8703 uint32_t version)
8705 torture_assert(tctx,
8706 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
8707 "failed to delete driver");
8709 torture_assert(tctx,
8710 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
8711 "failed to delete driver");
8713 if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
8714 torture_fail(tctx, "deleted driver still enumerated");
8717 torture_assert(tctx,
8718 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
8719 "2nd delete failed");
8721 return true;
8724 static bool test_PrinterDriver_args(struct torture_context *tctx,
8725 struct dcerpc_binding_handle *b,
8726 const char *server_name,
8727 uint32_t level,
8728 struct spoolss_AddDriverInfo8 *r,
8729 uint32_t add_flags,
8730 uint32_t delete_flags,
8731 uint32_t delete_version,
8732 bool ex,
8733 const char *remote_driver_dir)
8735 bool ret = true;
8737 switch (level) {
8738 case 1:
8739 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8740 break;
8741 case 2:
8742 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8743 break;
8744 case 3:
8745 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8746 break;
8747 case 4:
8748 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8749 break;
8750 case 6:
8751 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8752 break;
8753 case 8:
8754 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
8755 break;
8756 default:
8757 return false;
8760 if (ret == false) {
8761 return ret;
8764 if (level == 1) {
8765 return ret;
8768 /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
8770 if (!ex && (level == 6 || level == 8)) {
8771 return ret;
8775 struct dcerpc_pipe *p2;
8776 struct policy_handle hive_handle;
8777 struct dcerpc_binding_handle *b2;
8779 torture_assert_ntstatus_ok(tctx,
8780 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
8781 "could not open winreg pipe");
8782 b2 = p2->binding_handle;
8784 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
8786 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
8788 test_winreg_CloseKey(tctx, b2, &hive_handle);
8790 talloc_free(p2);
8793 if (ex) {
8794 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
8795 } else {
8796 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
8800 static bool fillup_printserver_info(struct torture_context *tctx,
8801 struct dcerpc_pipe *p,
8802 struct torture_driver_context *d)
8804 struct policy_handle server_handle;
8805 struct dcerpc_binding_handle *b = p->binding_handle;
8806 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
8808 torture_assert(tctx,
8809 test_OpenPrinter_server(tctx, p, &server_handle),
8810 "failed to open printserver");
8811 torture_assert(tctx,
8812 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
8813 "failed to get environment");
8814 torture_assert(tctx,
8815 test_ClosePrinter(tctx, b, &server_handle),
8816 "failed to close printserver");
8818 torture_assert(tctx,
8819 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
8820 d->local.environment ? d->local.environment : d->remote.environment,
8821 &d->remote.driver_directory),
8822 "failed to get driver directory");
8824 return true;
8827 static const char *driver_directory_dir(const char *driver_directory)
8829 char *p;
8831 p = strrchr(driver_directory, '\\');
8832 if (p) {
8833 return p+1;
8836 return NULL;
8839 static const char *driver_directory_share(struct torture_context *tctx,
8840 const char *driver_directory)
8842 const char *p;
8843 char *tok;
8845 if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
8846 driver_directory += 2;
8849 p = talloc_strdup(tctx, driver_directory);
8851 torture_assert(tctx,
8852 next_token_talloc(tctx, &p, &tok, "\\"),
8853 "cannot explode uri");
8854 torture_assert(tctx,
8855 next_token_talloc(tctx, &p, &tok, "\\"),
8856 "cannot explode uri");
8858 return tok;
8861 static bool upload_printer_driver_file(struct torture_context *tctx,
8862 struct smbcli_state *cli,
8863 struct torture_driver_context *d,
8864 const char *file_name)
8866 XFILE *f;
8867 int fnum;
8868 uint8_t *buf;
8869 int maxwrite = 64512;
8870 off_t nread = 0;
8871 size_t start = 0;
8872 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
8873 const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
8874 const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
8876 if (!file_name || strlen(file_name) == 0) {
8877 return true;
8880 torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
8882 fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
8883 if (fnum == -1) {
8884 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
8887 f = x_fopen(local_name, O_RDONLY, 0);
8888 if (f == NULL) {
8889 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
8892 buf = talloc_array(tctx, uint8_t, maxwrite);
8893 if (!buf) {
8894 return false;
8897 while (!x_feof(f)) {
8898 int n = maxwrite;
8899 int ret;
8901 if ((n = x_fread(buf, 1, n, f)) < 1) {
8902 if((n == 0) && x_feof(f))
8903 break; /* Empty local file. */
8905 torture_warning(tctx,
8906 "failed to read file: %s\n", strerror(errno));
8907 break;
8910 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
8912 if (n != ret) {
8913 torture_warning(tctx,
8914 "failed to write file: %s\n", smbcli_errstr(cli->tree));
8915 break;
8918 nread += n;
8921 x_fclose(f);
8923 torture_assert_ntstatus_ok(tctx,
8924 smbcli_close(cli->tree, fnum),
8925 "failed to close file");
8927 return true;
8930 static bool connect_printer_driver_share(struct torture_context *tctx,
8931 const char *server_name,
8932 const char *share_name,
8933 struct smbcli_state **cli)
8935 struct smbcli_options smb_options;
8936 struct smbcli_session_options smb_session_options;
8938 torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
8939 share_name, server_name);
8941 lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
8942 lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
8944 torture_assert_ntstatus_ok(tctx,
8945 smbcli_full_connection(tctx, cli, server_name,
8946 lpcfg_smb_ports(tctx->lp_ctx),
8947 share_name, NULL,
8948 lpcfg_socket_options(tctx->lp_ctx),
8949 cmdline_credentials,
8950 lpcfg_resolve_context(tctx->lp_ctx),
8951 tctx->ev,
8952 &smb_options,
8953 &smb_session_options,
8954 lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
8955 "failed to open driver share");
8957 return true;
8960 static bool upload_printer_driver(struct torture_context *tctx,
8961 const char *server_name,
8962 struct torture_driver_context *d)
8964 struct smbcli_state *cli;
8965 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
8966 int i;
8968 torture_assert(tctx,
8969 connect_printer_driver_share(tctx, server_name, share_name, &cli),
8970 "failed to connect to driver share");
8972 torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
8973 server_name, share_name);
8975 torture_assert(tctx,
8976 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
8977 "failed to upload driver_path");
8978 torture_assert(tctx,
8979 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
8980 "failed to upload data_file");
8981 torture_assert(tctx,
8982 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
8983 "failed to upload config_file");
8984 torture_assert(tctx,
8985 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
8986 "failed to upload help_file");
8987 if (d->info8.dependent_files) {
8988 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
8989 torture_assert(tctx,
8990 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
8991 "failed to upload dependent_files");
8995 talloc_free(cli);
8997 return true;
9000 static bool check_printer_driver_file(struct torture_context *tctx,
9001 struct smbcli_state *cli,
9002 struct torture_driver_context *d,
9003 const char *file_name)
9005 const char *remote_arch_dir = driver_directory_dir(d->remote.driver_directory);
9006 const char *remote_name = talloc_asprintf(tctx, "%s\\%d\\%s",
9007 remote_arch_dir,
9008 d->info8.version,
9009 file_name);
9010 int fnum;
9012 torture_assert(tctx, (file_name && strlen(file_name) != 0), "invalid filename");
9014 torture_comment(tctx, "checking for driver file at %s\n", remote_name);
9016 fnum = smbcli_open(cli->tree, remote_name, O_RDONLY, DENY_NONE);
9017 if (fnum == -1) {
9018 return false;
9021 torture_assert_ntstatus_ok(tctx,
9022 smbcli_close(cli->tree, fnum),
9023 "failed to close driver file");
9025 return true;
9028 static bool check_printer_driver_files(struct torture_context *tctx,
9029 const char *server_name,
9030 struct torture_driver_context *d,
9031 bool expect_exist)
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, "checking %sexistent driver files at \\\\%s\\%s\n",
9042 (expect_exist ? "": "non-"),
9043 server_name, share_name);
9045 if (d->info8.driver_path && d->info8.driver_path[0]) {
9046 torture_assert(tctx,
9047 check_printer_driver_file(tctx, cli, d, d->info8.driver_path) == expect_exist,
9048 "failed driver_path check");
9050 if (d->info8.data_file && d->info8.data_file[0]) {
9051 torture_assert(tctx,
9052 check_printer_driver_file(tctx, cli, d, d->info8.data_file) == expect_exist,
9053 "failed data_file check");
9055 if (d->info8.config_file && d->info8.config_file[0]) {
9056 torture_assert(tctx,
9057 check_printer_driver_file(tctx, cli, d, d->info8.config_file) == expect_exist,
9058 "failed config_file check");
9060 if (d->info8.help_file && d->info8.help_file[0]) {
9061 torture_assert(tctx,
9062 check_printer_driver_file(tctx, cli, d, d->info8.help_file) == expect_exist,
9063 "failed help_file check");
9065 if (d->info8.dependent_files) {
9066 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9067 torture_assert(tctx,
9068 check_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]) == expect_exist,
9069 "failed dependent_files check");
9073 talloc_free(cli);
9075 return true;
9078 static bool remove_printer_driver_file(struct torture_context *tctx,
9079 struct smbcli_state *cli,
9080 struct torture_driver_context *d,
9081 const char *file_name)
9083 const char *remote_name;
9084 const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
9086 if (!file_name || strlen(file_name) == 0) {
9087 return true;
9090 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
9092 torture_comment(tctx, "Removing %s\n", remote_name);
9094 torture_assert_ntstatus_ok(tctx,
9095 smbcli_unlink(cli->tree, remote_name),
9096 "failed to unlink");
9098 return true;
9101 static bool remove_printer_driver(struct torture_context *tctx,
9102 const char *server_name,
9103 struct torture_driver_context *d)
9105 struct smbcli_state *cli;
9106 const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
9107 int i;
9109 torture_assert(tctx,
9110 connect_printer_driver_share(tctx, server_name, share_name, &cli),
9111 "failed to connect to driver share");
9113 torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
9114 server_name, share_name);
9116 torture_assert(tctx,
9117 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
9118 "failed to remove driver_path");
9119 torture_assert(tctx,
9120 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
9121 "failed to remove data_file");
9122 if (!strequal(d->info8.config_file, d->info8.driver_path)) {
9123 torture_assert(tctx,
9124 remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
9125 "failed to remove config_file");
9127 torture_assert(tctx,
9128 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
9129 "failed to remove help_file");
9130 if (d->info8.dependent_files) {
9131 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
9132 if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
9133 strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
9134 strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
9135 strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
9136 continue;
9138 torture_assert(tctx,
9139 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
9140 "failed to remove dependent_files");
9144 talloc_free(cli);
9146 return true;
9150 static bool test_add_driver_arg(struct torture_context *tctx,
9151 struct dcerpc_pipe *p,
9152 struct torture_driver_context *d)
9154 bool ret = true;
9155 struct dcerpc_binding_handle *b = p->binding_handle;
9156 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9157 uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
9158 int i;
9159 struct spoolss_AddDriverInfo8 info8;
9160 uint32_t add_flags = APD_COPY_NEW_FILES;
9161 uint32_t delete_flags = 0;
9163 ZERO_STRUCT(info8);
9165 torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
9166 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
9168 torture_assert(tctx,
9169 fillup_printserver_info(tctx, p, d),
9170 "failed to fillup printserver info");
9172 if (!directory_exist(d->local.driver_directory)) {
9173 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9176 torture_assert(tctx,
9177 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9178 "failed to upload printer driver");
9180 info8 = d->info8;
9181 if (d->info8.dependent_files) {
9182 info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
9183 if (d->info8.dependent_files->string) {
9184 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9186 info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
9187 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9188 info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
9192 info8.architecture = d->local.environment;
9194 for (i=0; i < ARRAY_SIZE(levels); i++) {
9196 if (torture_setting_bool(tctx, "samba3", false)) {
9197 switch (levels[i]) {
9198 case 2:
9199 case 4:
9200 case 8:
9201 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9202 continue;
9203 default:
9204 break;
9207 if (torture_setting_bool(tctx, "w2k3", false)) {
9208 switch (levels[i]) {
9209 case 8:
9210 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9211 continue;
9212 default:
9213 break;
9217 torture_comment(tctx,
9218 "Testing PrinterDriver%s '%s' add & delete level %d\n",
9219 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9221 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);
9224 info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
9225 info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
9226 if (d->info8.config_file) {
9227 info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
9229 if (d->info8.help_file) {
9230 info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
9232 if (d->info8.dependent_files && d->info8.dependent_files->string) {
9233 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
9234 info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
9238 for (i=0; i < ARRAY_SIZE(levels); i++) {
9240 if (torture_setting_bool(tctx, "samba3", false)) {
9241 switch (levels[i]) {
9242 case 2:
9243 case 4:
9244 case 8:
9245 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
9246 continue;
9247 default:
9248 break;
9251 if (torture_setting_bool(tctx, "w2k3", false)) {
9252 switch (levels[i]) {
9253 case 8:
9254 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
9255 continue;
9256 default:
9257 break;
9261 torture_comment(tctx,
9262 "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
9263 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
9265 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);
9268 torture_assert(tctx,
9269 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9270 "failed to remove printer driver");
9272 torture_comment(tctx, "\n");
9274 return ret;
9277 static bool test_add_driver_ex_64(struct torture_context *tctx,
9278 struct dcerpc_pipe *p)
9280 struct torture_driver_context *d;
9282 d = talloc_zero(tctx, struct torture_driver_context);
9284 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9285 d->info8.driver_name = TORTURE_DRIVER_EX;
9286 d->info8.architecture = NULL;
9287 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9288 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9289 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9290 d->local.environment = talloc_strdup(d, "Windows x64");
9291 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9292 d->ex = true;
9294 return test_add_driver_arg(tctx, p, d);
9297 static bool test_add_driver_ex_32(struct torture_context *tctx,
9298 struct dcerpc_pipe *p)
9300 struct torture_driver_context *d;
9302 d = talloc_zero(tctx, struct torture_driver_context);
9304 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9305 d->info8.driver_name = TORTURE_DRIVER_EX;
9306 d->info8.architecture = NULL;
9307 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9308 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9309 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9310 d->local.environment = talloc_strdup(d, "Windows NT x86");
9311 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9312 d->ex = true;
9314 return test_add_driver_arg(tctx, p, d);
9317 static bool test_add_driver_64(struct torture_context *tctx,
9318 struct dcerpc_pipe *p)
9320 struct torture_driver_context *d;
9322 d = talloc_zero(tctx, struct torture_driver_context);
9324 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9325 d->info8.driver_name = TORTURE_DRIVER;
9326 d->info8.architecture = NULL;
9327 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9328 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9329 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9330 d->local.environment = talloc_strdup(d, "Windows x64");
9331 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9332 d->ex = false;
9334 return test_add_driver_arg(tctx, p, d);
9337 static bool test_add_driver_32(struct torture_context *tctx,
9338 struct dcerpc_pipe *p)
9340 struct torture_driver_context *d;
9342 d = talloc_zero(tctx, struct torture_driver_context);
9344 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9345 d->info8.driver_name = TORTURE_DRIVER;
9346 d->info8.architecture = NULL;
9347 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9348 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9349 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9350 d->local.environment = talloc_strdup(d, "Windows NT x86");
9351 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9352 d->ex = false;
9354 return test_add_driver_arg(tctx, p, d);
9357 static bool test_add_driver_adobe(struct torture_context *tctx,
9358 struct dcerpc_pipe *p)
9360 struct torture_driver_context *d;
9362 if (!torture_setting_bool(tctx, "samba3", false)) {
9363 torture_skip(tctx, "skipping adobe test which only works against samba3");
9366 d = talloc_zero(tctx, struct torture_driver_context);
9368 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9369 d->info8.driver_name = TORTURE_DRIVER_ADOBE;
9370 d->info8.architecture = NULL;
9371 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9372 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9373 d->info8.config_file = talloc_strdup(d, "ADOBEPS4.DRV");
9374 #if 0
9375 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9376 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9377 #endif
9378 d->local.environment = talloc_strdup(d, "Windows 4.0");
9379 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9380 d->ex = false;
9382 return test_add_driver_arg(tctx, p, d);
9385 static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
9386 struct dcerpc_pipe *p)
9388 struct torture_driver_context *d;
9389 struct spoolss_StringArray *a;
9391 if (!torture_setting_bool(tctx, "samba3", false)) {
9392 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
9395 d = talloc_zero(tctx, struct torture_driver_context);
9397 d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
9398 d->info8.driver_name = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
9399 d->info8.architecture = NULL;
9400 d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
9401 d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
9402 d->info8.config_file = NULL;
9403 d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
9404 d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
9405 d->info8.default_datatype = talloc_strdup(d, "RAW");
9407 a = talloc_zero(d, struct spoolss_StringArray);
9408 a->string = talloc_zero_array(a, const char *, 7);
9409 a->string[0] = talloc_strdup(a->string, "ADOBEPS4.DRV");
9410 a->string[1] = talloc_strdup(a->string, "DEFPRTR2.PPD");
9411 a->string[2] = talloc_strdup(a->string, "ADOBEPS4.HLP");
9412 a->string[3] = talloc_strdup(a->string, "PSMON.DLL");
9413 a->string[4] = talloc_strdup(a->string, "ADFONTS.MFM");
9414 a->string[5] = talloc_strdup(a->string, "ICONLIB.DLL");
9416 d->info8.dependent_files = a;
9417 d->local.environment = talloc_strdup(d, "Windows 4.0");
9418 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
9419 d->ex = false;
9421 return test_add_driver_arg(tctx, p, d);
9424 static bool test_add_driver_timestamps(struct torture_context *tctx,
9425 struct dcerpc_pipe *p)
9427 struct torture_driver_context *d;
9428 struct timeval t = timeval_current();
9430 d = talloc_zero(tctx, struct torture_driver_context);
9432 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9433 d->info8.driver_name = TORTURE_DRIVER_TIMESTAMPS;
9434 d->info8.architecture = NULL;
9435 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9436 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9437 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9438 d->info8.driver_date = timeval_to_nttime(&t);
9439 d->local.environment = talloc_strdup(d, "Windows NT x86");
9440 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9441 d->ex = true;
9443 torture_assert(tctx,
9444 test_add_driver_arg(tctx, p, d),
9445 "");
9447 unix_to_nt_time(&d->info8.driver_date, 1);
9449 torture_assert(tctx,
9450 test_add_driver_arg(tctx, p, d),
9451 "");
9453 return true;
9456 static bool test_multiple_drivers(struct torture_context *tctx,
9457 struct dcerpc_pipe *p)
9459 struct torture_driver_context *d;
9460 struct dcerpc_binding_handle *b = p->binding_handle;
9461 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9462 int i;
9463 struct spoolss_AddDriverInfo8 info8;
9464 uint32_t add_flags = APD_COPY_NEW_FILES;
9465 uint32_t delete_flags = 0;
9467 d = talloc_zero(tctx, struct torture_driver_context);
9469 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9470 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9471 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9472 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9473 d->local.environment = talloc_strdup(d, "Windows NT x86");
9474 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
9475 d->ex = true;
9477 torture_assert(tctx,
9478 fillup_printserver_info(tctx, p, d),
9479 "failed to fillup printserver info");
9481 if (!directory_exist(d->local.driver_directory)) {
9482 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9485 torture_assert(tctx,
9486 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9487 "failed to upload printer driver");
9489 info8 = d->info8;
9490 info8.architecture = d->local.environment;
9492 for (i=0; i < 3; i++) {
9493 info8.driver_name = talloc_asprintf(d, "torture_test_driver_%d", i);
9495 torture_assert(tctx,
9496 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &info8, add_flags, true, NULL),
9497 "failed to add driver");
9500 torture_assert(tctx,
9501 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_0", info8.architecture, delete_flags, info8.version),
9502 "failed to delete driver");
9504 torture_assert(tctx,
9505 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_1", NULL),
9506 "torture_test_driver_1 no longer on the server");
9508 torture_assert(tctx,
9509 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
9510 "torture_test_driver_2 no longer on the server");
9512 torture_assert(tctx,
9513 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_1", info8.architecture, delete_flags, info8.version),
9514 "failed to delete driver");
9516 torture_assert(tctx,
9517 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
9518 "torture_test_driver_2 no longer on the server");
9520 torture_assert(tctx,
9521 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_2", info8.architecture, delete_flags, info8.version),
9522 "failed to delete driver");
9524 torture_assert(tctx,
9525 remove_printer_driver(tctx, dcerpc_server_name(p), d),
9526 "failed to remove printer driver");
9528 return true;
9531 static bool test_del_driver_all_files(struct torture_context *tctx,
9532 struct dcerpc_pipe *p)
9534 struct torture_driver_context *d;
9535 struct spoolss_StringArray *a;
9536 uint32_t add_flags = APD_COPY_NEW_FILES;
9537 uint32_t delete_flags = DPD_DELETE_ALL_FILES;
9538 struct dcerpc_binding_handle *b = p->binding_handle;
9539 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9541 d = talloc_zero(tctx, struct torture_driver_context);
9543 d->ex = true;
9544 d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9545 d->info8.driver_name = TORTURE_DRIVER_DELETER;
9546 d->info8.architecture = NULL;
9547 d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
9548 d->info8.data_file = talloc_strdup(d, "cups6.ppd");
9549 d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
9550 d->info8.help_file = talloc_strdup(d, "pscript.hlp");
9551 d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
9552 d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
9554 a = talloc_zero(d, struct spoolss_StringArray);
9555 a->string = talloc_zero_array(a, const char *, 3);
9556 a->string[0] = talloc_strdup(a->string, "cups6.inf");
9557 a->string[1] = talloc_strdup(a->string, "cups6.ini");
9559 d->info8.dependent_files = a;
9560 d->info8.architecture = d->local.environment;
9562 torture_assert(tctx,
9563 fillup_printserver_info(tctx, p, d),
9564 "failed to fillup printserver info");
9566 if (!directory_exist(d->local.driver_directory)) {
9567 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9570 torture_assert(tctx,
9571 upload_printer_driver(tctx, dcerpc_server_name(p), d),
9572 "failed to upload printer driver");
9574 torture_assert(tctx,
9575 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d->info8, add_flags, true, NULL),
9576 "failed to add driver");
9578 torture_assert(tctx,
9579 test_DeletePrinterDriverEx(tctx, b, server_name_slash,
9580 d->info8.driver_name,
9581 d->local.environment,
9582 delete_flags,
9583 d->info8.version),
9584 "failed to delete driver");
9586 torture_assert(tctx,
9587 check_printer_driver_files(tctx, dcerpc_server_name(p), d, false),
9588 "printer driver file check failed");
9590 talloc_free(d);
9591 return true;
9594 static bool test_del_driver_unused_files(struct torture_context *tctx,
9595 struct dcerpc_pipe *p)
9597 struct torture_driver_context *d1;
9598 struct torture_driver_context *d2;
9599 uint32_t add_flags = APD_COPY_NEW_FILES;
9600 struct dcerpc_binding_handle *b = p->binding_handle;
9601 const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
9603 d1 = talloc_zero(tctx, struct torture_driver_context);
9604 d1->ex = true;
9605 d1->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9606 d1->info8.driver_name = TORTURE_DRIVER_DELETER;
9607 d1->info8.architecture = NULL;
9608 d1->info8.driver_path = talloc_strdup(d1, "pscript5.dll");
9609 d1->info8.data_file = talloc_strdup(d1, "cups6.ppd");
9610 d1->info8.config_file = talloc_strdup(d1, "cupsui6.dll");
9611 d1->info8.help_file = talloc_strdup(d1, "pscript.hlp");
9612 d1->local.environment = talloc_strdup(d1, SPOOLSS_ARCHITECTURE_x64);
9613 d1->local.driver_directory = talloc_strdup(d1, "/usr/share/cups/drivers/x64");
9614 d1->info8.architecture = d1->local.environment;
9616 d2 = talloc_zero(tctx, struct torture_driver_context);
9617 d2->ex = true;
9618 d2->info8.version = SPOOLSS_DRIVER_VERSION_200X;
9619 d2->info8.driver_name = TORTURE_DRIVER_DELETERIN;
9620 d2->info8.architecture = NULL;
9621 d2->info8.driver_path = talloc_strdup(d2, "pscript5.dll"); /* overlapping */
9622 d2->info8.data_file = talloc_strdup(d2, "cupsps6.dll");
9623 d2->info8.config_file = talloc_strdup(d2, "cups6.ini");
9624 d2->info8.help_file = talloc_strdup(d2, "pscript.hlp"); /* overlapping */
9625 d2->local.environment = talloc_strdup(d2, SPOOLSS_ARCHITECTURE_x64);
9626 d2->local.driver_directory = talloc_strdup(d2, "/usr/share/cups/drivers/x64");
9627 d2->info8.architecture = d2->local.environment;
9629 torture_assert(tctx,
9630 fillup_printserver_info(tctx, p, d1),
9631 "failed to fillup printserver info");
9632 torture_assert(tctx,
9633 fillup_printserver_info(tctx, p, d2),
9634 "failed to fillup printserver info");
9636 if (!directory_exist(d1->local.driver_directory)) {
9637 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
9640 torture_assert(tctx,
9641 upload_printer_driver(tctx, dcerpc_server_name(p), d1),
9642 "failed to upload printer driver");
9643 torture_assert(tctx,
9644 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d1->info8, add_flags, true, NULL),
9645 "failed to add driver");
9647 torture_assert(tctx,
9648 upload_printer_driver(tctx, dcerpc_server_name(p), d2),
9649 "failed to upload printer driver");
9650 torture_assert(tctx,
9651 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d2->info8, add_flags, true, NULL),
9652 "failed to add driver");
9654 /* some files are in use by a separate driver, should fail */
9655 torture_assert(tctx,
9656 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9657 d1->info8.driver_name,
9658 d1->local.environment,
9659 DPD_DELETE_ALL_FILES,
9660 d1->info8.version,
9661 WERR_PRINTER_DRIVER_IN_USE),
9662 "invalid delete driver response");
9664 /* should only delete files not in use by other driver */
9665 torture_assert(tctx,
9666 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9667 d1->info8.driver_name,
9668 d1->local.environment,
9669 DPD_DELETE_UNUSED_FILES,
9670 d1->info8.version,
9671 WERR_OK),
9672 "failed to delete driver (unused files)");
9674 /* check non-overlapping were deleted */
9675 d1->info8.driver_path = NULL;
9676 d1->info8.help_file = NULL;
9677 torture_assert(tctx,
9678 check_printer_driver_files(tctx, dcerpc_server_name(p), d1, false),
9679 "printer driver file check failed");
9680 /* d2 files should be uneffected */
9681 torture_assert(tctx,
9682 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, true),
9683 "printer driver file check failed");
9685 torture_assert(tctx,
9686 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
9687 d2->info8.driver_name,
9688 d2->local.environment,
9689 DPD_DELETE_ALL_FILES,
9690 d2->info8.version,
9691 WERR_OK),
9692 "failed to delete driver");
9694 torture_assert(tctx,
9695 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, false),
9696 "printer driver file check failed");
9698 talloc_free(d1);
9699 talloc_free(d2);
9700 return true;
9703 struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
9705 struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
9707 struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
9708 "driver", &ndr_table_spoolss);
9709 torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
9710 torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
9712 torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
9713 torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
9715 torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
9717 torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
9719 torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
9721 torture_rpc_tcase_add_test(tcase, "multiple_drivers", test_multiple_drivers);
9723 torture_rpc_tcase_add_test(tcase, "del_driver_all_files", test_del_driver_all_files);
9725 torture_rpc_tcase_add_test(tcase, "del_driver_unused_files", test_del_driver_unused_files);
9727 return suite;